Initial Import from SVN
authoraebersol <aebersol@hystou.home>
Mon, 20 Dec 2021 21:17:25 +0000 (22:17 +0100)
committeraebersol <aebersol@hystou.home>
Mon, 20 Dec 2021 21:17:25 +0000 (22:17 +0100)
340 files changed:
CMakeLists.txt [new file with mode: 0644]
TODO.txt [new file with mode: 0644]
adt/CMakeLists.txt [new file with mode: 0644]
adt/asn1_constraint.cpp [new file with mode: 0644]
adt/asn1_constraint.h [new file with mode: 0644]
adt/asn1_constraint.inc [new file with mode: 0644]
adt/asn1_meta.h [new file with mode: 0644]
adt/asn1_meta.inc [new file with mode: 0644]
adt/asn1_module.cpp [new file with mode: 0644]
adt/asn1_module.h [new file with mode: 0644]
adt/asn1_node.cpp [new file with mode: 0644]
adt/asn1_node.h [new file with mode: 0644]
adt/asn1_node_alternative_choice.h [new file with mode: 0644]
adt/asn1_node_assignment.cpp [new file with mode: 0644]
adt/asn1_node_assignment.h [new file with mode: 0644]
adt/asn1_node_choice.cpp [new file with mode: 0644]
adt/asn1_node_choice.h [new file with mode: 0644]
adt/asn1_node_classdef.cpp [new file with mode: 0644]
adt/asn1_node_classdef.h [new file with mode: 0644]
adt/asn1_node_constructed.cpp [new file with mode: 0644]
adt/asn1_node_constructed.h [new file with mode: 0644]
adt/asn1_node_exports.h [new file with mode: 0644]
adt/asn1_node_field.cpp [new file with mode: 0644]
adt/asn1_node_field.h [new file with mode: 0644]
adt/asn1_node_imports.cpp [new file with mode: 0644]
adt/asn1_node_imports.h [new file with mode: 0644]
adt/asn1_node_object.cpp [new file with mode: 0644]
adt/asn1_node_object.h [new file with mode: 0644]
adt/asn1_node_parameters.cpp [new file with mode: 0644]
adt/asn1_node_parameters.h [new file with mode: 0644]
adt/asn1_node_primitive.cpp [new file with mode: 0644]
adt/asn1_node_primitive.h [new file with mode: 0644]
adt/asn1_node_selection.h [new file with mode: 0644]
adt/asn1_node_sequence.cpp [new file with mode: 0644]
adt/asn1_node_sequence.h [new file with mode: 0644]
adt/asn1_node_sequence_of.h [new file with mode: 0644]
adt/asn1_node_set.h [new file with mode: 0644]
adt/asn1_node_set_of.h [new file with mode: 0644]
adt/asn1_node_typenode.cpp [new file with mode: 0644]
adt/asn1_node_typenode.h [new file with mode: 0644]
adt/asn1_node_typeref.cpp [new file with mode: 0644]
adt/asn1_node_typeref.h [new file with mode: 0644]
adt/asn1_node_valuetype.cpp [new file with mode: 0644]
adt/asn1_node_valuetype.h [new file with mode: 0644]
adt/asn1_recursive_visitor.h [new file with mode: 0644]
adt/asn1_reference.cpp [new file with mode: 0644]
adt/asn1_reference.h [new file with mode: 0644]
adt/asn1_resolver.cpp [new file with mode: 0644]
adt/asn1_resolver.h [new file with mode: 0644]
adt/asn1_type.h [new file with mode: 0644]
adt/asn1_type.inc [new file with mode: 0644]
adt/asn1_value.cpp [new file with mode: 0644]
adt/asn1_value.h [new file with mode: 0644]
adt/asn1_visitor.h [new file with mode: 0644]
cmip/CMIPActionListener.h [new file with mode: 0644]
cmip/CMIPAgent.cpp [new file with mode: 0644]
cmip/CMIPAgent.h [new file with mode: 0644]
cmip/CMIPEventReportListener.h [new file with mode: 0644]
cmip/CMIPListener.h [new file with mode: 0644]
cmip/CMIPStack.cpp [new file with mode: 0644]
cmip/CMIPStack.h [new file with mode: 0644]
cmip/CMakeLists.txt [new file with mode: 0644]
cmip/main.cpp [new file with mode: 0644]
cmip/modules.txt [new file with mode: 0644]
csta/CMakeLists.txt [new file with mode: 0644]
csta/main.cpp [new file with mode: 0644]
csta/modules.txt [new file with mode: 0644]
cstav1/AtraceCurlReader.cpp [new file with mode: 0644]
cstav1/AtraceDecoder.h [new file with mode: 0644]
cstav1/AtraceListener.h [new file with mode: 0644]
cstav1/AtraceMsgs.h [new file with mode: 0644]
cstav1/AtraceReader.h [new file with mode: 0644]
cstav1/CExpatImpl.h [new file with mode: 0644]
cstav1/CMakeLists.txt [new file with mode: 0644]
cstav1/Call.h [new file with mode: 0644]
cstav1/Controler.cpp [new file with mode: 0644]
cstav1/Controler.h [new file with mode: 0644]
cstav1/CstaInsightLog.cpp [new file with mode: 0644]
cstav1/CstaInsightLog.h [new file with mode: 0644]
cstav1/HeaderView.cpp [new file with mode: 0644]
cstav1/HeaderView.h [new file with mode: 0644]
cstav1/IconFactory.cpp [new file with mode: 0644]
cstav1/IconFactory.h [new file with mode: 0644]
cstav1/Model.cpp [new file with mode: 0644]
cstav1/Model.h [new file with mode: 0644]
cstav1/Observer.h [new file with mode: 0644]
cstav1/Packet.cpp [new file with mode: 0644]
cstav1/Packet.h [new file with mode: 0644]
cstav1/Pcap.cpp [new file with mode: 0644]
cstav1/Pcap.h [new file with mode: 0644]
cstav1/PrivateEla.cpp [new file with mode: 0644]
cstav1/PrivateEla.h [new file with mode: 0644]
cstav1/SequenceView.cpp [new file with mode: 0644]
cstav1/SequenceView.h [new file with mode: 0644]
cstav1/SniffHeader.h [new file with mode: 0644]
cstav1/TLMsg.cpp [new file with mode: 0644]
cstav1/TLMsg.h [new file with mode: 0644]
cstav1/TLMsgCsta.h [new file with mode: 0644]
cstav1/TLMsgSip.h [new file with mode: 0644]
cstav1/TLMsgXml.h [new file with mode: 0644]
cstav1/Timeline.cpp [new file with mode: 0644]
cstav1/Timeline.h [new file with mode: 0644]
cstav1/XMLMessage.h [new file with mode: 0644]
cstav1/cstaspyui.fl [new file with mode: 0644]
cstav1/data/double_appel_csta.pcap [new file with mode: 0755]
cstav1/data/listen_vm_vhe_csta.pcap [new file with mode: 0755]
cstav1/data/ma_change_filtering_level_3_csta.pcap [new file with mode: 0755]
cstav1/data/ma_change_filtering_level_filtering_to_screening_csta.pcap [new file with mode: 0755]
cstav1/data/ma_change_filtering_level_none_to_filtering_csta.pcap [new file with mode: 0755]
cstav1/data/make_call_csta.pcap [new file with mode: 0755]
cstav1/data/make_call_redirect_vm_csta.pcap [new file with mode: 0755]
cstav1/data/myicoffice_monitor_sip_transfer_call_withoutsip_releasing.pcap [new file with mode: 0755]
cstav1/data/myicoffice_msip130_make_call_ua.pcap [new file with mode: 0755]
cstav1/data/ots_start_csta.pcap [new file with mode: 0755]
cstav1/data/sip130_make_call_ua.pcap [new file with mode: 0755]
cstav1/images/Funnel_16.png [new file with mode: 0755]
cstav1/images/Lighting_16.png [new file with mode: 0755]
cstav1/images/RequestSoap_16.png [new file with mode: 0755]
cstav1/images/Request_16.png [new file with mode: 0755]
cstav1/images/ResponseError_16.png [new file with mode: 0755]
cstav1/images/ResponseReject_16.png [new file with mode: 0755]
cstav1/images/ResponseSoap_16.png [new file with mode: 0755]
cstav1/images/Response_16.png [new file with mode: 0755]
cstav1/images/Server_24.png [new file with mode: 0755]
cstav1/images/Server_48.png [new file with mode: 0755]
cstav1/images/Sip_16.png [new file with mode: 0755]
cstav1/images/VTSip_24.png [new file with mode: 0755]
cstav1/images/VTSip_48.png [new file with mode: 0755]
cstav1/images/VT_24.png [new file with mode: 0755]
cstav1/images/VT_48.png [new file with mode: 0755]
cstav1/main.cpp [new file with mode: 0644]
cstav1/modules.txt [new file with mode: 0644]
cstav1/sigslot.h [new file with mode: 0755]
gsm/CMakeLists.txt [new file with mode: 0644]
gsm/modules.txt [new file with mode: 0644]
gsmmap/CMakeLists.txt [new file with mode: 0644]
gsmmap/module.txt [new file with mode: 0644]
h248/CMakeLists.txt [new file with mode: 0644]
h248/main.cpp [new file with mode: 0644]
h248/modules.txt [new file with mode: 0644]
h323/CMakeLists.txt [new file with mode: 0644]
h323/modules.txt [new file with mode: 0644]
ledger/CMakeLists.txt [new file with mode: 0644]
ledger/main.cpp [new file with mode: 0644]
ledger/modules.txt [new file with mode: 0644]
libgen/CMakeLists.txt [new file with mode: 0644]
libgen/asn1_gen_auto_tag.cpp [new file with mode: 0644]
libgen/asn1_gen_auto_tag.h [new file with mode: 0644]
libgen/asn1_gen_codec_cpp.cpp [new file with mode: 0644]
libgen/asn1_gen_codec_cpp.h [new file with mode: 0644]
libgen/asn1_gen_config.h.in [new file with mode: 0644]
libgen/asn1_gen_constraints.cpp [new file with mode: 0644]
libgen/asn1_gen_constraints.h [new file with mode: 0644]
libgen/asn1_gen_cpp.cpp [new file with mode: 0644]
libgen/asn1_gen_cpp.h [new file with mode: 0644]
libgen/asn1_gen_hpp.cpp [new file with mode: 0644]
libgen/asn1_gen_hpp.h [new file with mode: 0644]
libgen/asn1_gen_optimizer.cpp [new file with mode: 0644]
libgen/asn1_gen_optimizer.h [new file with mode: 0644]
libgen/asn1_generator.cpp [new file with mode: 0644]
libgen/asn1_generator.h [new file with mode: 0644]
libgen/asn1_generator_helper.h [new file with mode: 0644]
libgen/cpp/cgcpp_helper.cpp [new file with mode: 0644]
libgen/cpp/cgcpp_helper.h [new file with mode: 0644]
libgen/cpp/cgcpph_bitstring.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_bitstring.h [new file with mode: 0644]
libgen/cpp/cgcpph_boolean.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_boolean.h [new file with mode: 0644]
libgen/cpp/cgcpph_choice.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_choice.h [new file with mode: 0644]
libgen/cpp/cgcpph_enumerated.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_enumerated.h [new file with mode: 0644]
libgen/cpp/cgcpph_import.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_import.h [new file with mode: 0644]
libgen/cpp/cgcpph_integer.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_integer.h [new file with mode: 0644]
libgen/cpp/cgcpph_object.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_object.h [new file with mode: 0644]
libgen/cpp/cgcpph_objectset.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_objectset.h [new file with mode: 0644]
libgen/cpp/cgcpph_octetstring.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_octetstring.h [new file with mode: 0644]
libgen/cpp/cgcpph_oid.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_oid.h [new file with mode: 0644]
libgen/cpp/cgcpph_primitive.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_primitive.h [new file with mode: 0644]
libgen/cpp/cgcpph_real.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_real.h [new file with mode: 0644]
libgen/cpp/cgcpph_sequence.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_sequence.h [new file with mode: 0644]
libgen/cpp/cgcpph_sequenceof.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_sequenceof.h [new file with mode: 0644]
libgen/cpp/cgcpph_set.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_set.h [new file with mode: 0644]
libgen/cpp/cgcpph_setof.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_setof.h [new file with mode: 0644]
libgen/cpp/cgcpph_string.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_string.h [new file with mode: 0644]
libgen/cpp/cgcpph_typeref.cpp [new file with mode: 0644]
libgen/cpp/cgcpph_typeref.h [new file with mode: 0644]
libgen/cpp/cgh_construct.cpp [new file with mode: 0644]
libgen/cpp/cgh_construct.h [new file with mode: 0644]
libgen/cpp/cgh_hconstruct.cpp [new file with mode: 0644]
libgen/cpp/cgh_hconstruct.h [new file with mode: 0644]
libgen/cpp/cgh_object.cpp [new file with mode: 0644]
libgen/cpp/cgh_object.h [new file with mode: 0644]
libgen/cpp/cgh_value.cpp [new file with mode: 0644]
libgen/cpp/cgh_value.h [new file with mode: 0644]
libgen/cpp/cghpp_helper.cpp [new file with mode: 0644]
libgen/cpp/cghpp_helper.h [new file with mode: 0644]
libgen/cpp/cghpph_bitstring.cpp [new file with mode: 0644]
libgen/cpp/cghpph_bitstring.h [new file with mode: 0644]
libgen/cpp/cghpph_boolean.cpp [new file with mode: 0644]
libgen/cpp/cghpph_boolean.h [new file with mode: 0644]
libgen/cpp/cghpph_choice.cpp [new file with mode: 0644]
libgen/cpp/cghpph_choice.h [new file with mode: 0644]
libgen/cpp/cghpph_classdef.cpp [new file with mode: 0644]
libgen/cpp/cghpph_classdef.h [new file with mode: 0644]
libgen/cpp/cghpph_enumerated.cpp [new file with mode: 0644]
libgen/cpp/cghpph_enumerated.h [new file with mode: 0644]
libgen/cpp/cghpph_import.cpp [new file with mode: 0644]
libgen/cpp/cghpph_import.h [new file with mode: 0644]
libgen/cpp/cghpph_integer.cpp [new file with mode: 0644]
libgen/cpp/cghpph_integer.h [new file with mode: 0644]
libgen/cpp/cghpph_object.cpp [new file with mode: 0644]
libgen/cpp/cghpph_object.h [new file with mode: 0644]
libgen/cpp/cghpph_octetstring.cpp [new file with mode: 0644]
libgen/cpp/cghpph_octetstring.h [new file with mode: 0644]
libgen/cpp/cghpph_oid.cpp [new file with mode: 0644]
libgen/cpp/cghpph_oid.h [new file with mode: 0644]
libgen/cpp/cghpph_primitive.cpp [new file with mode: 0644]
libgen/cpp/cghpph_primitive.h [new file with mode: 0644]
libgen/cpp/cghpph_real.cpp [new file with mode: 0644]
libgen/cpp/cghpph_real.h [new file with mode: 0644]
libgen/cpp/cghpph_sequence.cpp [new file with mode: 0644]
libgen/cpp/cghpph_sequence.h [new file with mode: 0644]
libgen/cpp/cghpph_sequenceof.cpp [new file with mode: 0644]
libgen/cpp/cghpph_sequenceof.h [new file with mode: 0644]
libgen/cpp/cghpph_set.cpp [new file with mode: 0644]
libgen/cpp/cghpph_set.h [new file with mode: 0644]
libgen/cpp/cghpph_setof.cpp [new file with mode: 0644]
libgen/cpp/cghpph_setof.h [new file with mode: 0644]
libgen/cpp/cghpph_string.cpp [new file with mode: 0644]
libgen/cpp/cghpph_string.h [new file with mode: 0644]
libgen/cpp/cghpph_typeref.cpp [new file with mode: 0644]
libgen/cpp/cghpph_typeref.h [new file with mode: 0644]
libgen/cpp/cghpph_value.cpp [new file with mode: 0644]
libgen/cpp/cghpph_value.h [new file with mode: 0644]
libgen/js/asn1_gen_js.cpp [new file with mode: 0644]
libgen/js/asn1_gen_js.h [new file with mode: 0644]
libgen/lds/asn1_gen_lds.cpp [new file with mode: 0644]
libgen/lds/asn1_gen_lds.h [new file with mode: 0644]
libgen/uml/asn1_gen_uml.cpp [new file with mode: 0644]
libgen/uml/asn1_gen_uml.h [new file with mode: 0644]
libparser/CMakeLists.txt [new file with mode: 0644]
libparser/asn1.l [new file with mode: 0644]
libparser/asn1.y [new file with mode: 0644]
libparser/asn1_parser.cpp [new file with mode: 0644]
libparser/asn1_parser.h [new file with mode: 0644]
libparser/asn1_parser_listener.h [new file with mode: 0644]
main.cpp [new file with mode: 0644]
megaco/CMakeLists.txt [new file with mode: 0644]
megaco/main.cpp [new file with mode: 0644]
megaco/modules.txt [new file with mode: 0644]
optionparser.h [new file with mode: 0755]
pasn1/parser.i [new file with mode: 0644]
pkix/CMakeLists.txt [new file with mode: 0644]
pkix/main_pkix.cpp [new file with mode: 0644]
pkix/result.txt [new file with mode: 0644]
pkix/sample-Certificate-1.der [new file with mode: 0644]
rtasn1/CMakeLists.txt [new file with mode: 0644]
rtasn1/asn1.h [new file with mode: 0644]
rtasn1/asn1_codec.h [new file with mode: 0644]
rtasn1/asn1_codec_ber.cpp [new file with mode: 0644]
rtasn1/asn1_codec_ber.h [new file with mode: 0644]
rtasn1/asn1_codec_jer.cpp [new file with mode: 0644]
rtasn1/asn1_codec_jer.h [new file with mode: 0644]
rtasn1/asn1_codec_oer.cpp [new file with mode: 0644]
rtasn1/asn1_codec_oer.h [new file with mode: 0644]
rtasn1/asn1_codec_per.cpp [new file with mode: 0644]
rtasn1/asn1_codec_per.h [new file with mode: 0644]
rtasn1/asn1_config.h.in [new file with mode: 0644]
rtasn1/asn1_context.cpp [new file with mode: 0644]
rtasn1/asn1_context.h [new file with mode: 0644]
rtasn1/asn1_debug.h [new file with mode: 0644]
rtasn1/asn1_errors.h [new file with mode: 0644]
rtasn1/asn1_rose.h [new file with mode: 0644]
rtasn1/asn1_tag.h [new file with mode: 0644]
rtasn1/asn1_types.cpp [new file with mode: 0644]
rtasn1/asn1_types.h [new file with mode: 0644]
rtasn1/asn1_types.hpp [new file with mode: 0644]
rtasn1/asn1_types.inc [new file with mode: 0644]
rtasn1/cjson/LICENSE [new file with mode: 0644]
rtasn1/cjson/README [new file with mode: 0644]
rtasn1/cjson/cJSON.c [new file with mode: 0644]
rtasn1/cjson/cJSON.h [new file with mode: 0644]
rtasn1/cjson/test.c [new file with mode: 0644]
rtasn1/cjson/tests/test1 [new file with mode: 0644]
rtasn1/cjson/tests/test2 [new file with mode: 0644]
rtasn1/cjson/tests/test3 [new file with mode: 0644]
rtasn1/cjson/tests/test4 [new file with mode: 0644]
rtasn1/cjson/tests/test5 [new file with mode: 0644]
rtasn1/cpp/CMakeLists.txt [new file with mode: 0644]
rtasn1/cpp/prim_GeneralizedTime.h [new file with mode: 0644]
rtasn1/cpp/prim_UTCTime.h [new file with mode: 0644]
rtasn1/cpp/prim_oid.cpp [new file with mode: 0644]
rtasn1/cpp/prim_oid.h [new file with mode: 0644]
rtasn1/json_token.h.inc [new file with mode: 0644]
rtasn1/prim_types.cpp [new file with mode: 0644]
rtasn1/prim_types.h [new file with mode: 0644]
tests/CMakeLists.txt [new file with mode: 0644]
tests/UNIT-TEST-basic-types-choice.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-choice.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-enum.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-enum.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-explicit.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-explicit.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-implicit.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-implicit.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-optional.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-optional.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-sequence.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-sequence.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-set.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-set.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types-tagged.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types-tagged.h [new file with mode: 0644]
tests/UNIT-TEST-basic-types.cpp [new file with mode: 0644]
tests/UNIT-TEST-basic-types.h [new file with mode: 0644]
tests/UNIT-TEST-ber-primary-types.cpp [new file with mode: 0644]
tests/UNIT-TEST-ber-primary-types.h [new file with mode: 0644]
tests/UNIT-TEST-private-types-choice.cpp [new file with mode: 0644]
tests/UNIT-TEST-private-types-choice.h [new file with mode: 0644]
tests/UNIT-TEST-type-parameter.h [new file with mode: 0644]
tests/main_asn1_type_sizes.cpp [new file with mode: 0644]
tests/main_test.cpp [new file with mode: 0644]
tests/modules.txt [new file with mode: 0644]
tests/poc-codec.h [new file with mode: 0644]
tests/poc-codec.hpp [new file with mode: 0644]
tests/source.asn1 [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..afa8c93
--- /dev/null
@@ -0,0 +1,180 @@
+PROJECT(asn1)
+
+SET(ASN1_VERSION_MAJOR 1)
+SET(ASN1_VERSION_MINOR 0)
+SET(ASN1_VERSION_PATCH 2)
+SET(ASN1_VERSION "${ASN1_VERSION_MAJOR}.${ASN1_VERSION_MINOR}.${ASN1_VERSION_PATCH}")
+
+OPTION(WITH_CMIP "Build Asn1 CMIP test directory" OFF)
+OPTION(WITH_CSTA "Build Asn1 CSTA v2 test directory" ON)
+OPTION(WITH_CSTAV1 "Build Asn1 CSTA v1 test directory" ON)
+OPTION(WITH_GSM  "Build Asn1 GSM  test directory" ON)
+OPTION(WITH_H323 "Build Asn1 H323 test directory" ON)
+OPTION(WITH_ASN1_GEN_UML "Build UML Code Generator library" OFF)
+OPTION(WITH_ASN1_GEN_JS  "Build Javascript Code Generator library" ON)
+OPTION(WITH_ASN1_GEN_CPP "Build C++ Code Generator library" ON)
+OPTION(WITH_ASN1_GEN_LDS "Build Lds Code Generator library" OFF)
+
+IF(CMAKE_CROSSCOMPILING)
+    SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point to the
+    export file from native build")
+    INCLUDE(${IMPORT_EXECUTABLES})
+ENDIF(CMAKE_CROSSCOMPILING)
+
+IF (NOT CMAKE_BUILD_TYPE)
+  SET(CMAKE_BUILD_TYPE Debug)
+ENDIF(NOT CMAKE_BUILD_TYPE)
+
+ADD_DEFINITIONS(-DBUILD_VERSION=\"${ASN1_VERSION}\")
+ADD_DEFINITIONS(-DBUILD_TYPE=\"${CMAKE_BUILD_TYPE}\")
+# Only for Linux not MAC
+IF(APPLE)
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG ")
+ELSEIF(WIN32)  
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG ")
+ELSE(APPLE)
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -std=c++0x")
+  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
+ENDIF(APPLE)
+
+#
+# Set VARIABLES used by subdirs
+#  eg: fltk, cppunit, expat, pcap, winpcap
+
+#
+# Libraries first. Process sub dirs 
+#
+IF(NOT CMAKE_CROSSCOMPILING)
+SUBDIRS(rtasn1 adt libparser libgen tests pkix cstav1 ledger csta gsm h323 megaco h248
+    cmip)
+ELSE(NOT CMAKE_CROSSCOMPILING)
+SUBDIRS(rtasn1  pkix cstav1 ledger csta gsm h323 megaco h248)
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+INCLUDE(${rules_SOURCE_DIR}/flex.cmake)
+
+IF(NOT WIN32)
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -D__FILENAME__='\"$(subst ${CMAKE_CURRENT_SOURCE_DIR}/,,$<)\"'")
+ENDIF(NOT WIN32)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/libgen)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/adt)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${aebutils_SOURCE_DIR})
+
+#
+# MAC specific addon files for target
+#
+IF(APPLE)
+  SET(ASN1PADDONS
+    ${CMAKE_CURRENT_SOURCE_DIR}/../Resources/squarelogo.jpg      
+    ${CMAKE_CURRENT_SOURCE_DIR}/../Resources/cstainsight.icns    
+     ) 
+ELSE(APPLE)
+  SET(ASN1PADDONS "")  
+ENDIF(APPLE)
+#
+# EXECUTALBE
+#
+IF (NOT CMAKE_CROSSCOMPILING)
+
+  ADD_EXECUTABLE(asn1p 
+    main.cpp
+    ${ASN1PADDONS}
+    )
+  IF (WIN32)
+    SET_TARGET_PROPERTIES(asn1p PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:console")        
+    SET_TARGET_PROPERTIES(asn1p PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")         
+    SET_TARGET_PROPERTIES(asn1p PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:console")      
+    SET_TARGET_PROPERTIES(asn1p PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE")       
+  ENDIF(WIN32)   
+  MESSAGE("Export Executables to ${CMAKE_BINARY_DIR}")
+  EXPORT(TARGETS asn1p FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake
+      NAMESPACE native-)
+  TARGET_LINK_LIBRARIES(asn1p asn1adt libgen libasn1p)
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+#
+# Cross compiling ...
+#
+IF(CMAKE_CROSSCOMPILING)
+    SET(asn1p_EXE native-asn1p)
+    GET_TARGET_PROPERTY(test ${asn1p_EXE} IMPORTED_LOCATION_DEBUG)
+    SET(asn1p_EXE ${test})
+ELSE(CMAKE_CROSSCOMPILING)
+    SET(asn1p_EXE ${CMAKE_CURRENT_BINARY_DIR}/asn1p)
+ENDIF(CMAKE_CROSSCOMPILING)
+
+#
+# Install Stuff
+#
+IF(APPLE)
+  ADD_EXECUTABLE(Smartasn1 
+    main.cpp
+    ${ASN1PADDONS}
+  )
+  TARGET_LINK_LIBRARIES(Smartasn1 asn1adt libgen libasn1p)
+
+  SET(MACOSX_RESOURCE_FILES
+       ${CMAKE_CURRENT_SOURCE_DIR}/../Resources/cstainsight.icns
+  )
+  SET_TARGET_PROPERTIES(Smartasn1 PROPERTIES
+        MACOSX_BUNDLE TRUE
+       MACOSX_BUNDLE_STARTUP_COMMAND betfan.sh
+       MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}
+       MACOSX_BUNDLE_BUNDLE_VERSION ${ASN1_VERSION}
+       MACOSX_BUNDLE_LONG_VERSION_STRING "${ASN1_VERSION}"
+       MACOSX_BUNDLE_SHORT_VERSION_STRING "${ASN1_VERSION}"
+       MACOSX_BUNDLE_GUI_IDENTIFIER "fr.ebersold.Smartasn1"
+       #       MACOSX_BUNDLE_ICON_FILE "betfan.icns"
+       MACOSX_BUNDLE_ICON_FILE "cstainsight.icns"
+    )
+  SET_SOURCE_FILES_PROPERTIES(
+       ${CMAKE_CURRENT_SOURCE_DIR}/../Resources/squarelogo.icns
+       PROPERTIES MACOSX_PACKAGE_LOCATION Resources
+       )       
+  SET_SOURCE_FILES_PROPERTIES(
+       ${CMAKE_CURRENT_SOURCE_DIR}/../Resources/cstainsight.icns
+       PROPERTIES MACOSX_PACKAGE_LOCATION Resources
+       )
+  SET(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
+  SET(APPS "\$ENV{DESTDIR}/Smartasn1.app")
+  SET(DIRS "")  
+ENDIF(APPLE)
+IF(WIN32)
+  SET_TARGET_PROPERTIES(asn1p PROPERTIES WIN32_EXECUTABLE TRUE)        
+ENDIF(WIN32)
+
+IF (NOT CMAKE_CROSSCOMPILING)
+  IF(APPLE)
+    INSTALL(TARGETS Smartasn1
+            BUNDLE DESTINATION .
+           COMPONENT Asn1
+           RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin/
+           LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/
+           ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/
+    )
+    INSTALL(TARGETS asn1p 
+           COMPONENT Asn1
+           DESTINATION Smartasn1.app/Contents/bin/
+           RUNTIME DESTINATION Smartasn1.app/Contents/bin/
+           LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/
+           ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/
+    )
+
+    #INSTALL(CODE "
+    #  include(BundleUtilities)
+    #  fixup_bundle(\"${APP}\" \"\" \"${DIRS}\")
+    #  " COMPONENT Asn1)    
+  ELSE(APPLE)
+  #
+  # Unix Install
+  #  
+    INSTALL(TARGETS asn1p
+         COMPONENT Asn1
+         DESTINATION bin/)
+  ENDIF(APPLE)  
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+
diff --git a/TODO.txt b/TODO.txt
new file mode 100644 (file)
index 0000000..c1cd967
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,184 @@
+2012/01/27 : Solve the issue with type identifier
+2012/01/27 : Solve the issue with parameterized types 
+
+SIGNED{ToBeSigned} ::= SEQUENCE {
+  tobeSigned ToBeSigned;
+}
+
+2012/07/27 : Codec for Enum is needed specificaly when there is an explicit
+tag
+2012/07/27 : ANY IDENTIFY BY See If I can replace it by something else.
+
+2012/07/27 : Choice should have set/get operation as inline. Default
+constructors for each choice. !!! might be an issue when several choices have
+the same type.
+
+2012/07/31 : ObjectSet code generation is missing
+2012/07/31 : Constraint management, for sized elements
+2012/07/31 : Better support for Optional values in codec
+2012/07/31 : asn1::error class / codes for error management in codec
+2012/07/31 : Log results in file, Logger class
+
+2012/08/01 : Tags in attributes for sequence
+2012/08/01 : Tags in attributes for choice
+2012/08/01 : Tags in attributes for set
+
+2012/08/13 : Decoders have a problem with [0] IMPLICIT BOOLEAN. The issue is
+linked to tag checks.
+
+2014/10/02 : Size of csta_insight has increased 7934911 to 8662504
+8662504
+7934911
+8810664 2017/04/28 
+8175720 2017/07/21
+8115936 2017/07/28
+
+2014/11/02 : First version of cstav1 with optional and new choice.
+ - URGENT printf of new choice.
+ - remove attributes from choice.
+ - remplace code in choice_codec
+ - review the way to initialize defaults. New Constructor prototype ?
+ - review decode of optionnal. Maybe destroy existing value if one.
+ - Write tests : SEQUENCE OF, SEQUENCE with defaults that are tagged.
+ - purge traces in parser (generator.cpp) all std::cout should be put under log
+ - add log traces filter at generation level. (DEBUG_CTOR, DEBUG_CODEC, DEBUG_COMMENT)
+   * a flag that will remove all comments from source code.
+   * a flag that will remove debug traces
+   * a flag that will even remove ERROR traces. 
+ - ENUMRATED, put implementation in cpp file.
+ - BIT_STRING, if there is a size contraint, I should use it.
+ 2014/11/18: ASN1 spec 2008
+ --------------------------
+ Take into account the news introduced in X.680 2008 there are changes
+ -> new reserved keywords : DATE / DATE-TIME / DURATION / ENCODING-CONTROL /
+ INSTRUCTIONS / NOT-A-NUMBER / OID-IRI / RELATIVE-OID-IRI / SETTINGS / TIME /
+ TIME-OF-DAY
+ new tags:
+ TIME           tag UNIVERSAL 14
+ DATE           tag UNIVERSAL 31
+ TIME-OF-DAY    tag 32
+ DATE-TIME      tag UNIVERSAL 33
+ DURATION  tag UNIVERSAL 34
+
+ add ENCODING-CONTROL part
+ in definition, rule encoding_instruction_defaults
+
+2015/08/19:
+-----------
+Move files abstract datatypes to adt directory and make a library out of it.
+create a new version 2 for asn1.l asn1.y to use common project of parser.
+
+Also solve asn1p issues with gsm and H323
+-------------
+
+Generaration of CODE SEQUENCE_OF<primitivetype>
+ leads to duplicate codecs 
+
+Generation of CODEC for private CHOICE in sequence
+  missing codec for private choice
+
+Issue with CODEC generation with SEQUENCE OF SEQUENCE 
+
+2016/01/20:
+-----------
+ - Finalize helper generator for cpp et hpp
+ - Finalize flatten option. or unested code generation.
+ - Add prefix option
+ - Add namespace option
+ - Put all asn1 file and definition name in a file to allow the parser to resolve imports.
+ - OER encoded needs to be added.
+ - Solve issue with duplicated name types in nested environments specially in h248.
+ - Issue with BIT_STRING primitive class. should not be an array needs to be rewritten
+ - Rework handling of reference generation as I got a better understanding 
+ - Add a resolver class in adt. The purpose is to find the type for a given reference.
+ - Better handling of struct name assignment
+ - BIT STRING types are not defined in header. compilation of gsm fails
+
+2016/04/06:
+-----------
+ - Fixed parsing objects and checking against class
+ - Fixed nested issue
+ - Fixed SELECTION TYPE
+ - Fixed COMPONENTS OF for sequence / set. Missing one check
+ - Fixed Duplicate Types in h248
+ - Fixed encoding for object classes
+ - Fixed resolver added in adt.
+ - Fixed ROS syntax with parameter generation. Missing Init of object sets
+
+2017/01/10:
+-----------    
+ - remove begin / end for all calls where it is not required
+ - handling of values to be aligned. valuetype class should be used. Clarify
+   valuetype and value class !!! seems to have the same purpose
+
+2017/04/28:
+-----------
+ - Fixed H323 generation. Compiles again ... Was broken during source reworking
+ - Improved Asn1 Object data types to facilitate parsing and understanding.
+ - Better distinction in generator between actual parameter and parameter.
+ - Optimizer, Added processing of SELECTION Type
+ - Reworked Codec classes .... added dummy per and oer codecs. Seems to be promissing
+ - Tests have still 5 failures.
+ - DONE move asn1 folder to rtasn1 meaning : asn1 runtime to avoid confusion with root
+   directory.
+ - In choice, add parameter handling for Types like Invoke... 
+
+2017/05/14:
+-----------
+ - make a clear separation between typenodes and assignments
+   * move m_reference and its API from node to typeref
+   * move m_type and its API from node to assignment and field
+   * remove node iterator, and introduce assignement iterator and field iterator
+2017/06/20:
+-----------
+ - TODO For typeref add methods like get_canonical() return the primivite type
+ - TODO For typeref add get_prev_typeref which will return preview declaration. It's useful
+   to build tag list chaine.
+ - TODO For typeref also add method get_prev_typenode()
+ - TODO Before optimization, I should built the type map and resolve the references.
+   this would save me a lot of time during processing where is often use lookup
+ - TODO Attribute-ASN1Module uses class typeref. I do not generate code for this type :-(
+2018/05/19:
+-----------
+
+Generator      | BER   | BER   | JER   | OER   | PER   | XER   | ctors | print | equal | copy
+cpp/Type       | Old   | Codec | Codec | Codec | Codec |       |       |       |       |
+
+Typeref                |       | 30%   | 40%   |       |       |       |       |       |       |
+BOOLEAN                | 100%  | 50%   | 50%   | 20%   |       |       | DONE  | DONE | DONE | DONE
+INTEGER                | 70%   | 30%   | 30%   | 20%   | 20%   |       |       |       |       |
+ENUMERATED     | 70%   | 30%   | 30%   | 20%   | 20%   |       |       |       |       |
+NULL           | 100%  | 20%   | 50%   | 20%   | 20%   |       |       |       |       |
+REAL           | 5%    |       | 20%   |       |       |       |       |       |       |
+OCTET_STRING   | 80%   | 30%   | 40%   | 20%   | 20%   |       |       |       |       |
+BIT_STRING     | 70%   | 20%   | 30%   | 20%   | 20%   |       |       |       |       |
+SEQUENCE       | 60%   | 20%   | 40%   |       |       |       |       |       |       |
+SET            | 50%   |       | 0%    |       |       |       |       |       |       |
+CHOICE         | 70%   | 20%   | 30%   |       |       |       |       |       |       |
+SEQUENCE OF    | 60%   | 20%   | 40%   | 20%   | 20%   |       |       |       |       |
+SET OF         | 60%   | 20%   | 20%   | 20%   |       |       |       |       |       |
+CLASSDEF       | 60%   |       | 0%    |       |       |       |       |       |       |
+OBJECT         | 60%   |       | 0%    |       |       |       |       |       |       |
+OID            | 60%   | 20%   | 20%   | 20%   |       |       |       |       |       |
+ROID           | 0%    |       | 0%    |       |       |       |       |       |       |
+TIME           | 0%    |       | 0%    |       |       |       |       |       |       |
+TIME-OF-DAY    | 0%    |       | 0%    |       |       |       |       |       |       |
+GeneralizeUTC  | 0%    |       | 0%    |       |       |       |       |       |       |
+DATA-TIME      | 0%    |       | 0%    |       |       |       |       |       |       |
+DURATION       | 0%    |       | 0%    |       |       |       |       |       |       |
+STRING         | 60%   |       | 20%   |       |       |       |       |       |       |
+EXTERNAL       | 0%    |       | 0%    |       |       |       |       |       |       |
+EMBEDDED-PDV   | 0%    |       | 0%    |       |       |       |       |       |       |
+
+ - TODO JER start decoding implementation.
+ - TODO move encode/decode BER to BER codec way. Goal : remove Old BER style.
+ - TODO update helpers to be more unified. encode/decode into generate_ber
+ - TODO set/sequence equal
+ - TODO BIT_STRING or ENUMERATED with constraint in SEQUENCE or SET should lead to a new type!
+ - TODO disable default ber in generator.
+ - TODO improve ber generation so that switch --codecs will work. Either codec or embeded enc/dec
+ - TODO I think there is a constrcutor missing with OID. ASN1 speficitation use a lot of OID value
+ - TODO Provide allocator class to allocate asn1 objects. Might be easier with codec. 
diff --git a/adt/CMakeLists.txt b/adt/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2800e62
--- /dev/null
@@ -0,0 +1,24 @@
+PROJECT(libasn1adt)
+
+ADD_LIBRARY(asn1adt
+      asn1_node.cpp
+      asn1_node_typenode.cpp
+      asn1_node_sequence.cpp
+      asn1_node_choice.cpp
+      asn1_node_classdef.cpp
+      asn1_node_object.cpp
+      asn1_node_parameters.cpp
+      asn1_node_assignment.cpp
+      asn1_node_constructed.cpp
+      asn1_node_field.cpp
+      asn1_node_typeref.cpp
+      asn1_node_primitive.cpp
+      asn1_node_imports.cpp
+      asn1_constraint.cpp
+      asn1_value.cpp
+      asn1_resolver.cpp
+      asn1_reference.cpp
+      asn1_node_valuetype.cpp
+      asn1_module.cpp
+    )
+
diff --git a/adt/asn1_constraint.cpp b/adt/asn1_constraint.cpp
new file mode 100644 (file)
index 0000000..4f0ce3f
--- /dev/null
@@ -0,0 +1,293 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <list>
+#include <vector>
+
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "asn1_node.h"
+
+namespace asn1 {
+
+std::string 
+constraint::name()
+{
+  std::ostringstream os;
+  switch(type())
+      {
+        case asn1::constraint::EL_TYPE:     /* T (contained subtype )      */
+          os<<" type("<<m_value->name();
+          os<<")";
+          break;
+        case asn1::constraint::EL_VALUE:    /* 123, "X" (elementary value) */
+          os<<" value("<<m_value->name();
+          os<<")";
+          break;
+        case asn1::constraint::EL_RANGE:    /* 1..5 (basic range)          */  
+        case asn1::constraint::EL_LLRANGE:  /* 1<..3                       */
+        case asn1::constraint::EL_RLRANGE:  /* 1..<4                       */
+        case asn1::constraint:: EL_ULRANGE: /* 1<..<3 (basic range)        */
+         {
+           asn1::constraint_range *cr = as_constraint_range();
+           os<<" range(";
+           if (cr && cr->get_min())
+           {
+             os<<cr->get_min()->name();
+             os<<" .."<<cr->get_max()->name();
+           }
+           os<<")";
+         }
+          break;
+        case asn1::constraint::EL_EXT:       /* ... (extensible mark)      */
+          os<<" extensible ";
+          break;
+
+      /*Constraint type */
+        case asn1::constraint::CT_SIZE:
+          os<<" !!! size(";
+          if ((! m_elements.empty()) && m_elements.front() != NULL)
+            os<<((m_elements.front()))->name();
+          os<<")";
+          break;
+        case asn1::constraint::CT_FROM:
+        default:
+          os<<" constraint not handled "<<type();
+  };
+
+    return os.str();
+}
+
+/**
+ *
+ */ 
+std::string 
+constraint_type::name()
+{
+  std::ostringstream os;
+  switch(type())
+  {
+    case asn1::constraint::CT_SIZE:
+      os<<" size(";
+      if ( (! m_elements.empty()) && (m_elements.front() != NULL))
+        os<<((m_elements.front()))->name();
+      os<<")";
+      break;
+    case asn1::constraint::CT_FROM:
+      os<<"from ";  
+      if (m_elements.front() != NULL)
+         os<<((m_elements.front()))->name()<<" ";
+    break;
+    case asn1::constraint::CT_WCOMP:
+    {
+      os<<"with component ";  
+      iterator it = m_elements.begin();
+      os<<(*it)->name();
+    }
+    break;
+    case asn1::constraint::CT_WCOMPS:
+    {
+      os<<"with components ";  
+      for (iterator it = m_elements.begin() 
+          ; it != m_elements.end()
+          ; ++it)
+          os<<" "<<(*it)->name()<<" ";
+    }
+    break;
+    case asn1::constraint::CT_CTDBY:
+      os<<"constrained by ";
+      if (m_value)
+        os<<m_value->name();  
+    break;
+    case asn1::constraint::CT_CTNG:
+      os<<"constaining ";  
+      if (m_value)
+        os<<m_value->name();  
+    break;
+    default:
+      os<<" constraint not handled ";
+  }
+  return os.str();
+}
+
+std::string 
+constraint_array::name()
+{
+  std::ostringstream os;
+  switch(type())
+  {
+    case asn1::constraint::CA_SET:
+      os<<"set ";
+      for (iterator it = m_elements.begin() 
+          ; it != m_elements.end()
+          ; ++it)
+          os<<"("<<(*it)->name()<<")";
+      os<<"";
+    break;
+    case asn1::constraint::CA_CRC:
+    {
+      os<<"crc ";  
+      iterator it = m_elements.begin();
+      os<<"{"<<(*it)->name()<<"}";
+      ++it;
+      os<<"{@ ? "<<(*it)->name()<<"}";
+    }
+    break;
+    case asn1::constraint::CA_CSV:
+      os<<"csv";  
+    break;
+    case asn1::constraint::CA_UNI:
+      os<<"union";  
+    break;
+    case asn1::constraint::CA_INT:
+      os<<"intersection";  
+    break;
+    case asn1::constraint::CA_EXC:
+      os<<"except";  
+    break;
+    case asn1::constraint::CA_AEX:
+    {
+      os<<"all except ";  
+      iterator it = m_elements.begin();
+      os<<(*it)->name();
+    }
+    break;
+
+    default:
+      os<<"array constraint";  
+  }
+  return os.str();
+}
+    
+asn1::constraint_type *
+constraint::as_constraint_type()
+{
+  return dynamic_cast<asn1::constraint_type *>(this);
+}
+
+asn1::constraint_element *
+constraint::as_constraint_element()
+{
+  return dynamic_cast<asn1::constraint_element *>(this);
+}
+
+
+asn1::ctype_size *
+constraint::as_constraint_size()
+{
+  return dynamic_cast<asn1::ctype_size *>(this);
+}
+
+
+/**
+ * constraint_element
+ */ 
+
+asn1::valuetype *
+constraint_element::get_valuetype() const 
+{
+  return (m_value?m_value->as_value_type():NULL);
+}
+
+
+/**
+ * celt_type specificities
+ */ 
+celt_type::celt_type(asn1::typeref *t)
+   : constraint_element(EL_TYPE)
+{ 
+  value(t) ;
+}
+
+//
+asn1::typeref *
+celt_type::get_type() const
+{
+  return value()->as_typeref();
+}
+
+/**
+ * ctype_size object type
+ * subelement constraint is either value or range.
+ *  range is of type constraint_range
+ *  value is of type constraint_element or
+ */
+asn1::celt_value *
+ctype_size::get_value() const
+{
+  asn1::constraint_element *subelem  =           (*m_elements.begin())->as_constraint_element();
+  return (subelem?subelem->as_celt_value():NULL);
+}
+
+asn1::constraint_range*
+ctype_size::get_range() const
+{
+  asn1::constraint_element *subelem  =           (*m_elements.begin())->as_constraint_element();
+  return (subelem?subelem->as_constraint_range():NULL);
+}
+
+/**
+ *
+ */
+constraint_range *
+constraint::as_constraint_range() 
+{
+  return dynamic_cast<asn1::constraint_range *>(this);
+} 
+    
+#define ELEMENT_CONSTRAINT(elt,cls,parent) \
+cls * \
+constraint::as_##cls() \
+{                      \
+  return dynamic_cast<asn1::cls *>(this); \
+}
+
+#include "asn1_constraint.inc"
+
+/**
+ * constraint_range code
+ */
+    
+constraint_range::constraint_range(types_type t,asn1::node *_min,asn1::node *_max)
+ : m_min(_min),m_max(_max),constraint_element(t)
+{
+}
+    
+constraint_range::~constraint_range()
+{
+}
+
+    
+void 
+constraint_range::set_min(asn1::node *s)
+{
+  m_min = s;
+  //m_elements.push_back(new constraint("value",s,EL_VALUE));
+}
+
+void 
+constraint_range::set_max(asn1::node *s)
+{ 
+  m_max = s;
+  //m_elements.push_back(new constraint("value",s,EL_VALUE));
+}
+
+void 
+constraint_range::set_min_max(asn1::node *_min,asn1::node *_max )
+{
+  m_min = _min;
+  m_max = _max;
+}
+
+bool 
+constraint_range::get_min_max(long &min,long &max)
+{
+  asn1::valuetype *_min_type = (m_min != NULL)?m_min->as_value_type(): NULL;
+  asn1::valuetype *_max_type = (m_max != NULL)?m_max->as_value_type(): NULL;
+  min = (_min_type)?_min_type->value_long():0;
+  max = (_max_type)?_max_type->value_long():0;
+  return ( (_min_type != NULL) && ( _max_type != NULL));
+}    
+
+
+}
diff --git a/adt/asn1_constraint.h b/adt/asn1_constraint.h
new file mode 100644 (file)
index 0000000..d34e2ea
--- /dev/null
@@ -0,0 +1,226 @@
+#ifndef ASN1_CONSTRAINT_H__
+#define ASN1_CONSTRAINT_H__
+
+namespace asn1 {
+class node;
+class typeref;
+class valuetype;
+class constraint_element;
+class constraint_range;
+class constraint_type;
+class ctype_size;
+class ctype_from;
+
+#define ELEMENT_CONSTRAINT(elt,cls,parent) \
+    class cls ;
+
+#include "asn1_constraint.inc"
+
+class constraint 
+{
+  public:
+
+    typedef std::list<constraint *> contraints;
+
+    typedef contraints::iterator iterator;
+    typedef contraints::const_iterator const_iterator;
+
+    typedef enum {
+      EL_INVALID,
+      /* Element type */
+      EL_TYPE,         /* T (contained subtype )       */
+      EL_VALUE,        /* 123, "X" (elementary value)  */
+      EL_RANGE,                /* 1..5 (basic range)                   */  
+      EL_LLRANGE,      /* 1<..3                                                */
+      EL_RLRANGE,      /* 1..<4                                                */
+      EL_ULRANGE,      /* 1<..<3 (basic range)                 */
+      EL_ENCODEDBY,    /* encoded by type              */
+      EL_EXT,          /* ... (extensible mark)                */
+
+      /*Constraint type */
+      CT_SIZE,         /* SIZE Constraint type */
+      CT_FROM,         /* */
+      CT_WCOMP,                /* WITH COMPONENT */
+      CT_WCOMPS,       /* WITH COMPONENTS*/
+      CT_CTDBY,                /* CONSTRAINED BY */
+      CT_CTNG,         /* CONTAINING */
+      /* Array Constraints */
+      CA_SET,          /* A set of constraints: (c1)(c2) */
+      CA_CRC,          /* Comp. relation c-t: ({a}{@b}) */
+      CA_CSV,          /* Comma-separated constraints array */
+      CA_UNI,          /* UNION (|) */
+      CA_INT,          /* INTERSECTION (^) */
+      CA_EXC,          /* EXCEPT */
+      CA_AEX           /* ALL EXCEPT */      
+    } types_type;
+
+    inline bool is_constraint_array() { return m_type>= CA_SET  && m_type <= CA_AEX  ; }
+    inline bool is_constraint_type()  { return m_type>= CT_SIZE && m_type <= CT_CTNG ; }
+    inline bool is_constraint_elem()  { return m_type>= EL_TYPE && m_type <= EL_EXT  ; }
+
+    typedef enum {
+      DEFAULT,
+      PRESENT,
+      ABSENT,
+      OPTIONAL_
+    } presence_type;
+
+    constraint(const char *name,types_type t = EL_INVALID) :m_type(t),m_value(NULL) {}
+    constraint(const char *name,asn1::node *n,types_type t = EL_INVALID) :m_type(t),m_value(n) {}
+    constraint(const constraint &c) : m_type(c.m_type),m_value(c.m_value) {};
+    ~constraint() {};
+
+    virtual std::string name();
+    /* Avoid using iterator. Not all constraints use containers */
+    iterator begin() {return m_elements.begin();}
+    const_iterator begin() const {return m_elements.begin();}
+    iterator end()  {return m_elements.end();}
+    const_iterator end() const {return m_elements.end();}
+
+    void append(constraint *c) {m_elements.push_back(c);};
+
+    /*  Value associated with the constraint */
+    inline void value(asn1::node *n) {m_value = n;};
+
+    inline asn1::node* value() const {return m_value;};
+    
+    inline void presence(presence_type p) {m_presence = p;};
+    
+    inline size_t size() const { return m_elements.size();};
+    /* Cast opertors    */
+    constraint_type    *as_constraint_type();
+    constraint_element *as_constraint_element();
+    constraint_range   *as_constraint_range() ;
+    ctype_size         *as_constraint_size() ;
+
+#define ELEMENT_CONSTRAINT(elt,cls,parent) \
+    cls *as_##cls() ;
+#include "asn1_constraint.inc"
+
+    // Type of constraint
+    inline types_type   type() const {return m_type;};
+    inline void type(types_type t) {m_type = t;};
+  protected:
+    contraints       m_elements;
+    asn1::node      *m_value;
+    types_type       m_type;
+    presence_type    m_presence;
+};
+
+
+/**
+ *
+ */ 
+class constraint_element : public constraint
+{
+  public:
+    constraint_element(types_type t) :constraint("ELEMENT",t) {} ;
+    ~constraint_element() {};
+    /**
+     * valuetype is asn1 value some how. 
+     * Here, we leave the constraint syntax
+     */
+    asn1::valuetype *get_valuetype() const ;
+};
+
+/**
+ *  A range is composed of two values.  
+ *  min .. max
+ */ 
+class constraint_range : public constraint_element
+{
+    asn1::node      *m_min;
+    asn1::node      *m_max;
+  public:
+    constraint_range(types_type t,asn1::node *_min = NULL,asn1::node *_max = NULL);
+    
+    ~constraint_range() ;
+    
+    void set_min(asn1::node *s);
+    
+    void set_max(asn1::node *s);
+    asn1::node *get_min() const { return m_min ; }
+    
+    asn1::node *get_max() const { return m_max ; }
+   
+    void set_min_max(asn1::node *_min,asn1::node *_max );
+    
+    bool get_min_max(long &min,long &max);
+};
+
+/**
+ *
+ */ 
+class constraint_type : public constraint
+{
+  public:
+    constraint_type(types_type t) : constraint("TYPE",t) {};
+    ~constraint_type() {};
+    std::string name();
+};
+
+/**
+ *
+ */ 
+class constraint_array : public constraint
+{
+  public:
+    constraint_array(types_type t) : constraint( "ARRAY",t) {} ;
+    ~constraint_array() {} ;
+    
+    std::string name();
+};
+/* Element type */
+#define ELEMENT_CONSTRAINT_EXTEND_celt_type   \
+  celt_type(asn1::typeref *t); \
+  asn1::typeref *get_type() const;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_value   ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_range      ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_llrange         ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_rlrange  ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_ulrange          ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_encodedby ;
+#define ELEMENT_CONSTRAINT_EXTEND_celt_ext           ;
+
+/*Constraint type */
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_size             \
+  asn1::celt_value *get_value() const;            \
+  asn1::constraint_range *get_range() const;      \
+
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_from           ;
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_wcomp  ;
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_wcomps      ;
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_ctdby        ;
+#define ELEMENT_CONSTRAINT_EXTEND_ctype_ctng           ;
+
+/* Array Constraints */
+#define ELEMENT_CONSTRAINT_EXTEND_ca_set ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_crc ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_csv ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_uni ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_int ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_exc ;
+#define ELEMENT_CONSTRAINT_EXTEND_ca_aex ;
+
+
+#define ELEMENT_CONSTRAINT_GEN(elt,cls,parent) \
+  class cls : public parent \
+  {\
+     public:\
+       cls() : parent(elt) {}; \
+       ~cls() {} \
+
+//  }; 
+
+#define ELEMENT_CONSTRAINT(elt,cls,parent) \
+          ELEMENT_CONSTRAINT_GEN(elt,cls,parent) ELEMENT_CONSTRAINT_EXTEND_##cls };
+
+#include "asn1_constraint.inc"
+
+}
+
+/*
+vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/adt/asn1_constraint.inc b/adt/asn1_constraint.inc
new file mode 100644 (file)
index 0000000..7801f4f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef ELEMENT_CONSTRAINT
+#define ELEMENT_CONSTRAINT(elt,cls,parent)
+#endif
+/* Element type */
+ELEMENT_CONSTRAINT(EL_TYPE,celt_type,constraint_element)        /* t (contained subtype )      */
+ELEMENT_CONSTRAINT(EL_VALUE,celt_value,constraint_element)     /* 123, "x" (elementary value)  */
+ELEMENT_CONSTRAINT(EL_RANGE,celt_range,constraint_range)      /* 1..5 (basic range)                    */  
+ELEMENT_CONSTRAINT(EL_LLRANGE,celt_llrange,constraint_range)   /* 1<..3                                                */
+ELEMENT_CONSTRAINT(EL_RLRANGE,celt_rlrange,constraint_range)  /* 1..<4                                         */
+ELEMENT_CONSTRAINT(EL_ULRANGE,celt_ulrange,constraint_range)    /* 1<..<3 (basic range)                */
+ELEMENT_CONSTRAINT(EL_ENCODEDBY,celt_encodedby,constraint_range) /* encoded by type            */
+ELEMENT_CONSTRAINT(EL_EXT,celt_ext,constraint_element)           /* ... (extensible mark)              */
+
+/*Constraint type */
+#ifndef ELEMENT_CONSTRAINT_TYPE
+#define ELEMENT_CONSTRAINT_TYPE(elt,cls,parent) ELEMENT_CONSTRAINT(elt,cls,parent)
+#endif
+ELEMENT_CONSTRAINT_TYPE(CT_SIZE,ctype_size,constraint_type)            /* size constraint type */
+ELEMENT_CONSTRAINT_TYPE(CT_FROM,ctype_from,constraint_type)            /* */
+ELEMENT_CONSTRAINT_TYPE(CT_WCOMP,ctype_wcomp,constraint_type)  /* with component       */
+ELEMENT_CONSTRAINT_TYPE(CT_WCOMPS,ctype_wcomps,constraint_type)      /* with components      */
+ELEMENT_CONSTRAINT_TYPE(CT_CTDBY,ctype_ctdby,constraint_type)        /* constrained by       */
+ELEMENT_CONSTRAINT_TYPE(CT_CTNG,ctype_ctng,constraint_type)            /* containing           */
+
+/* Array Constraints */
+#ifndef ELEMENT_CONSTRAINT_ARRAY
+#define ELEMENT_CONSTRAINT_ARRAY(elt,cls,parent) ELEMENT_CONSTRAINT(elt,cls,parent)
+#endif
+ELEMENT_CONSTRAINT_ARRAY(CA_SET,ca_set,constraint_array) /* a set of constraints: (c1)(c2)    */
+ELEMENT_CONSTRAINT_ARRAY(CA_CRC,ca_crc,constraint_array) /* comp. relation c-t: ({a}{@b})     */
+ELEMENT_CONSTRAINT_ARRAY(CA_CSV,ca_csv,constraint_array) /* comma-separated constraints array */
+ELEMENT_CONSTRAINT_ARRAY(CA_UNI,ca_uni,constraint_array) /* union (|)                         */
+ELEMENT_CONSTRAINT_ARRAY(CA_INT,ca_int,constraint_array) /* intersection (^)                  */
+ELEMENT_CONSTRAINT_ARRAY(CA_EXC,ca_exc,constraint_array) /* except                            */
+ELEMENT_CONSTRAINT_ARRAY(CA_AEX,ca_aex,constraint_array) /* all except                        */ 
+
+#undef ELEMENT_CONSTRAINT
+#undef ELEMENT_CONSTRAINT_TYPE
+#undef ELEMENT_CONSTRAINT_ARRAY
diff --git a/adt/asn1_meta.h b/adt/asn1_meta.h
new file mode 100644 (file)
index 0000000..51e8b11
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef ASN1_META_H__
+#define ASN1_META_H__
+#include <iostream>
+
+namespace asn1
+{
+
+  class meta
+  {
+    public:
+      typedef enum {
+        INVALID = 0 ,
+        TYPEREF,     /* Type2 := Type1                 */
+        TYPE,        /* Type1 := INTEGER               */
+        VALUE,       /* value Type1 := 1               */
+        VALUESET,    /* Vset  Type1 := {value 1}       */
+        OBJECT,      /* object CLASS := {...}          */
+        OBJECTCLASS, /* FCT := CLASS {}                */
+        OBJECTSET,   /* objref DefinedObject :=  {set }                */
+        OBJECTFIELD,
+        MAX
+      } id;
+      inline meta(meta::id id = INVALID) : m_id(id) {};
+      inline meta(const meta &m) : m_id(m.m_id) {};
+      inline meta &operator =( const meta &m) {m_id = m.m_id; return *this;};
+      inline meta &operator =( const id i) {m_id = i; return *this;};
+      inline ~meta()  {};
+      inline bool operator >(const meta &a) {return m_id > a.m_id; };
+      inline bool operator <(const meta &a) {return m_id < a.m_id; };
+      inline bool operator ==(const meta &a) {return m_id == a.m_id; };
+      inline bool operator ==(const meta::id a) {return m_id == a; };
+
+       friend std::ostream & operator <<(std::ostream &os, const meta &m)
+       {
+           os<<m.m_id;
+           return os;
+       }
+      inline id operator()()
+      {
+          return m_id;
+      }
+    protected:
+      id    m_id;
+  };
+}
+#endif
diff --git a/adt/asn1_meta.inc b/adt/asn1_meta.inc
new file mode 100644 (file)
index 0000000..4a9da44
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ASSIGNMENT
+#define ASSIGNMENT(tp,class,parent)    
+#endif
+
+ASSIGNMENT(TYPEREF,typeref,assignment)
+ASSIGNMENT(TYPE,type,assignment)
+ASSIGNMENT(VALUE,value,assignment)
+ASSIGNMENT(VALUESET,valueset,assignment)
+ASSIGNMENT(OBJECT,object,assignment)
+ASSIGNMENT(OBJECTCLASS,objectclass,assignment)
+ASSIGNMENT(OBJECTSET,objectset,assignment)
+ASSIGNMENT(OBJECTFIELD,objectfield,assignment)
+
+#undef ASSIGNMENT
diff --git a/adt/asn1_module.cpp b/adt/asn1_module.cpp
new file mode 100644 (file)
index 0000000..3770f5e
--- /dev/null
@@ -0,0 +1,159 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+/**
+ * Useful method to resolve references. before
+ * optimization.
+ */
+void 
+module::resolve(asn1::resolver &r)
+{
+  struct do_resolve {
+    do_resolve(asn1::resolver &_r) : m_resolver(_r) {};
+
+    void operator () (std::pair<const std::string ,asn1::assignment *> &p)
+    {
+      p.second->get_type()->resolve(m_resolver);
+    }
+    asn1::resolver &m_resolver;
+  } ;
+
+  std::cerr<<__FUNCTION__<<" TODO"<<std::endl;
+
+  std::for_each( m_symbols.begin()
+         , m_symbols.end()
+         ,do_resolve(r));
+}
+
+/**
+ * retrieve assignment initialy declared in asn1 file.
+ * not those reparented through optimization
+ */
+asn1::assignment *
+module::get_assignment(const std::string &n)
+{
+  symt_iterator it = m_symbols.find(n);
+  if (it != m_symbols.end())
+    return it->second;
+  return NULL;
+}
+
+
+
+asn1::assignment *
+module::lookup(asn1::node *reference)
+{
+  asn1::node::iterator nit = std::find_if(begin(),
+       end(),
+       asn1::find_node(reference->name()));
+  if ( nit != end() )
+  {
+    return dynamic_cast<asn1::assignment *>(*nit);
+  }
+  return NULL;
+}
+
+/**
+ * All assignments added through this function are
+ * in m_symbols map. 
+ * -> Those reworked by optimize will not be
+ *  seen in the map. That allows a distinction between
+ *  reparented structures and declared types.
+ */
+void 
+module::add_type(asn1::assignment *n)
+{
+  assert((n != NULL) && "add_type parameter assignment must not be NULL");
+  append(n);
+  if ( n && n->meta_id()() == asn1::meta::OBJECT)
+  {
+    m_has_objects = true; 
+  }
+  symt_iterator it = m_symbols.find(n->name());
+  if ( it == m_symbols.end())
+    m_symbols[n->name()] = n;
+}
+
+//
+void
+module::enter_symbol(asn1::node *n,asn1::type::id id)
+{
+  if (!m_context.empty())
+  {
+    if (n->get_parent() == NULL)
+    {
+      n->set_parent(m_context.top());
+    } else
+    {
+      std::cerr<<"module::enter_symbol the node already has a parent"<<std::endl;
+    }
+    m_context.top()->append(n);
+  } else 
+  {
+    std::cerr<<"module::enter_symbol "<<n->name()<<" can't add on empty context"<<std::endl;
+  }
+}
+
+//
+void 
+module::enter_context(asn1::constructed *_n)
+{
+  m_context.push(_n);
+}
+
+//
+asn1::constructed *
+module::current_context()
+{
+  if (m_context.empty())
+    return reinterpret_cast<asn1::constructed *>(this);
+  return m_context.top() ;
+}
+//
+asn1::constructed *
+module::leave_context()
+{
+  asn1::constructed *r =  m_context.top();
+  m_context.pop();
+  return r;
+}
+
+
+
+
+asn1::import *
+module::get_import(const std::string &imp) const
+{
+  // pre condition, m_imports != NULL
+  if ( ! m_imports)
+    return NULL;
+
+  asn1::node::iterator found = std::find_if( m_imports->begin()
+                                           , m_imports->end()
+                                           , asn1::find_node(imp));
+  if (found != m_imports->end())
+    return dynamic_cast<asn1::import *>(*found);
+  return NULL;
+}
+
+}
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/adt/asn1_module.h b/adt/asn1_module.h
new file mode 100644 (file)
index 0000000..a243126
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef ASN1_MODULE_H__
+#define ASN1_MODULE_H__
+
+#include <vector>
+#include <stack>
+#include <map>
+
+#include "asn1_node.h"
+
+namespace asn1 {
+
+  class import_list;
+  class import;
+  class module;
+  class resolver ;
+  struct  find_module
+  {
+    find_module(const std::string &s) : m_s(s) {} 
+    bool operator ()(asn1::module *n);
+    std::string m_s;
+  };
+
+/**
+ * A module contains all definitions. When we start a new definition,
+ * the parser shall call enter context and at the end, it shall call
+ * leave_context
+ */
+class module : public asn1::constructed
+{
+  public:
+    typedef std::map<std::string ,asn1::assignment *> symtable_type;
+    typedef symtable_type::iterator                   symt_iterator;
+    typedef std::vector<asn1::module *>               modules_type;
+    typedef std::stack<asn1::constructed *>           context_stack_type;
+
+  public:
+
+    module(const char *name ) : asn1::constructed(name,type::INVALID) 
+                                ,m_root(NULL)
+                                ,m_has_objects(false)
+                                ,m_imports(NULL)
+                                ,m_exports(NULL) {};
+
+    module(const module &m) 
+      : asn1::constructed(m)
+      , m_has_objects(m.m_has_objects)  
+    {
+      std::cerr<<"module::module(const module &m)"<<std::endl;
+    };
+    // Default destructor
+    virtual ~module() {};
+  
+    inline bool has_objects() const {return m_has_objects; } ;
+    /**
+     * The parser uses this function to add assignment tp
+     * the module. 
+     */
+    void add_type(asn1::assignment *a);
+    //
+    void enter_symbol(asn1::node *n,asn1::type::id id) ;
+    //
+    void enter_context(asn1::constructed *_n) ;
+    //
+    asn1::constructed *current_context() ;
+    //
+    asn1::constructed *leave_context() ;
+
+    /**
+     * Useful method to resolve references. before
+     * optimization.
+     */
+    void resolve(asn1::resolver &r); 
+    /**
+     * retrieve assignment initialy declared in asn1 file.
+     * not those reparented through optimization
+     */
+    asn1::assignment *get_assignment(const std::string &n);  
+    /**
+     *
+     */ 
+    asn1::assignment *lookup(asn1::node *reference);
+
+    inline void exports(asn1::exports *exp) { m_exports = exp;  };
+    inline asn1::exports  *exports(void )   { return m_exports; };
+
+    inline void imports(asn1::import_list *exp)    { m_imports = exp;  };
+    inline asn1::import_list *imports(void )       { return m_imports; };
+    inline asn1::import_list *imports(void ) const { return m_imports; };
+    /**
+     * lookup if we import elements from module imp.
+     */
+    asn1::import *get_import(const std::string &imp) const;
+  protected:
+    context_stack_type  m_context;
+    symtable_type       m_symbols;
+    bool                m_has_objects;
+    asn1::node          *m_root;
+    asn1::exports       *m_exports;
+    asn1::import_list   *m_imports;
+};
+
+
+   inline bool find_module::operator ()(asn1::module *n) 
+    {
+      return !m_s.compare(n->name());
+    };
+
+}
+
+/**
+vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/adt/asn1_node.cpp b/adt/asn1_node.cpp
new file mode 100644 (file)
index 0000000..7c297eb
--- /dev/null
@@ -0,0 +1,742 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_reference.h"
+#include "asn1_module.h"
+
+namespace asn1 {
+// Counter to help computing an unique identifier for each node. 
+static long g_counter = 0;
+
+static 
+char  lop_substitute(char c)
+{
+    return (c == '&')?'_':c;
+}
+/**
+ *
+ *
+ */
+node::node(const std::string name, meta  m ) : m_is_generated(CL_GREEN) , 
+                m_ref(0),m_name(name),m_meta(m),
+                m_next(NULL)
+                , m_constraints("VIDE")
+                , m_identifier(NULL)
+                ,m_parameters(NULL)
+                ,m_value(NULL)
+                ,m_type(NULL)
+                       ,m_parent(NULL)      
+                ,m_marker(marker_type::FL_NONE)
+{
+  m_tag.m_mode   = tag_type::TM_DEFAULT;
+  m_tag.m_class  = tag_type::TC_NOCLASS;
+  m_tag.m_value  = -1;
+  m_tag.m_set    = false;
+  std::ostringstream oss;
+  std::string cppname;
+  cppname.resize(m_name.size());
+  std::transform(m_name.begin(),m_name.end(),cppname.begin(),asn1::lop_substitute);
+  oss<<cppname<<"_"<<g_counter;
+  m_uid = oss.str();
+  g_counter++;
+}
+
+node *
+node::clone()
+{
+  std::cerr<<"node::clone Should not happend "<<name()<< "type:"<<type_id()()<<std::endl;      
+  return new node(*this);
+};
+
+/**
+ *
+ *
+ */
+node::node(const std::string name, type  t ,meta m ) : m_is_generated(CL_GREEN),
+          m_ref(0),m_meta(m),m_type_id(t),m_name(name),
+          m_next(NULL)
+          ,m_constraints("VIDE")
+          ,m_identifier(NULL)
+          ,m_parameters(NULL)
+             ,m_parent(NULL)        
+          ,m_value(NULL)
+                ,m_type(NULL)
+                ,m_marker(marker_type::FL_NONE)
+{
+  m_marker.m_flags = marker_type::FL_NONE; 
+  m_tag.m_mode   = tag_type::TM_DEFAULT;
+  m_tag.m_class  = tag_type::TC_NOCLASS;
+  m_tag.m_value  = -1;
+  m_tag.m_set    = false;
+  std::ostringstream oss;
+  std::string cppname;
+  cppname.resize(m_name.size());
+  std::transform(m_name.begin(),m_name.end(),cppname.begin(),asn1::lop_substitute);
+  oss<<cppname<<"_"<<g_counter;
+  m_uid = oss.str();
+  g_counter++;
+  switch (t())
+  {
+        case asn1::type::ASN1_REFERENCE:
+       break;
+        case asn1::type::ASN1_EXPORTVAR:
+       break;
+       // case asn1::type::ASN1_UNIVERSAL: break;
+       // case asn1::type::ASN1_BITVECTOR: break;
+        case asn1::type::ASN1_EXTENSIBLE:
+       break;
+        case asn1::type::ASN1_COMPONENTS_OF:
+       break;
+        case asn1::type::ASN1_VALUESET:
+       break;
+        case asn1::type::ASN1_CLASSDEF:
+       break;
+      //  case asn1::type::ASN1_INSTANCE: break;
+        
+        /**
+         * Class Field type
+         */
+        case asn1::type::ASN1_CLASSFIELD_TF:
+       break;      /* Type Field                   */
+        case asn1::type::ASN1_CLASSFIELD_FTVF:
+       break;    /* Fixed Type Value Field       */
+        case asn1::type::ASN1_CLASSFIELD_VTVF:
+       break;    /* Variable Type Value Field    */
+        case asn1::type::ASN1_CLASSFIELD_FTVSF:
+       break;   /* Fixed Type Value Set Field   */
+        case asn1::type::ASN1_CLASSFIELD_VTVSF:
+       break;   /* Variable Type Value Set Field*/
+        case asn1::type::ASN1_CLASSFIELD_OF:
+       break;      /* Object Field                 */
+        case asn1::type::ASN1_CLASSFIELD_OSF:
+       break;     /* Object Set Field             */
+        /* Constructed Types
+         */
+        case asn1::type::ASN1_SEQUENCE:
+          m_tag.m_value  = 16;
+       break;           /* 17 */
+        case asn1::type::ASN1_CHOICE:
+       break;
+        case asn1::type::ASN1_SET:
+          m_tag.m_value  = 17;
+       break;
+        case asn1::type::ASN1_SEQUENCE_OF:
+          m_tag.m_value  = 16;
+       break;
+        case asn1::type::ASN1_SET_OF:
+          m_tag.m_value  = 17;
+       break;
+        case asn1::type::ASN1_SELECTION:
+       break;
+        /* Basic Types
+         */
+        case asn1::type::ASN1_ANY:
+       break;
+        case asn1::type::ASN1_BOOLEAN:
+          m_tag.m_value  = 1;
+       break;
+        case asn1::type::ASN1_INTEGER:
+          m_tag.m_value  = 2;
+       break;
+        case asn1::type::ASN1_BIT_STRING:
+          m_tag.m_value  = 3;
+       break;
+        case asn1::type::ASN1_OCTET_STRING:
+          m_tag.m_value  = 4;
+       break;
+        case asn1::type::ASN1_NULL:
+          m_tag.m_value  = 5;
+       break;
+        case asn1::type::ASN1_OBJECT_IDENTIFIER:
+          m_tag.m_value  = 6;
+       break;
+        case asn1::type::ASN1_OBJECT_DESCRIPTOR:
+       break;
+        case asn1::type::ASN1_REAL:
+          m_tag.m_value  = 9;
+       break;
+        case asn1::type::ASN1_ENUMERATED:
+          m_tag.m_value  = 10;
+       break;
+        case asn1::type::ASN1_RELATIVE_OID:
+       break;
+        case asn1::type::ASN1_EXTERNAL:
+          m_tag.m_value  = 8;
+       break;
+        case asn1::type::ASN1_EMBEDDED_PDV:
+       break;
+        case asn1::type::ASN1_CHARACTER_STRING:
+       break;
+        case asn1::type::ASN1_UTCTime:
+          m_tag.m_value  = 23;
+       break;
+        case asn1::type::ASN1_GeneralizedTime:
+          m_tag.m_value  = 24;
+       break;
+        /* String Types
+         */
+
+        case asn1::type::ASN1_STRING:
+       break;
+        case asn1::type::ASN1_STRING_IA5String:
+          m_tag.m_value  = 22;
+       break;
+        case asn1::type::ASN1_STRING_PrintableString:
+          m_tag.m_value  = 19;
+       break;
+        case asn1::type::ASN1_STRING_VisibleString:
+          m_tag.m_value  = 26;
+       break;
+        case asn1::type::ASN1_STRING_ISO646String:
+       break;    /* aka VisibleString */
+        case asn1::type::ASN1_STRING_NumericString:
+          m_tag.m_value  = 18;
+       break;
+        case asn1::type::ASN1_STRING_UniversalString:
+          m_tag.m_value  = 29;
+       break;
+        case asn1::type::ASN1_STRING_BMPString:
+          m_tag.m_value  = 30;
+       break;
+        case asn1::type::ASN1_STRING_UTF8String  :
+          m_tag.m_value  = 12;
+       break;
+        case asn1::type::ASN1_STRING_GeneralString:
+          m_tag.m_value  = 27;
+       break;
+        case asn1::type::ASN1_STRING_GraphicString:
+          m_tag.m_value  = 25;
+       break;
+        case asn1::type::ASN1_STRING_TeletexString:
+          m_tag.m_value  = 20;
+       break;
+        case asn1::type::ASN1_STRING_T61String:
+       break;
+        case asn1::type::ASN1_STRING_VideotexString:
+          m_tag.m_value  = 21;
+       break;
+        case asn1::type::ASN1_STRING_ObjectDescriptor:
+       break;
+       default:
+       ;
+  }
+}
+
+/**
+ * copy constructor 
+ *
+ */
+node::node(const node &n) : m_is_generated(n.m_is_generated),m_meta(n.m_meta),m_type_id(n.m_type_id),
+          m_name(n.m_name), m_next(n.m_next)
+          ,m_constraints(n.m_constraints)
+          ,m_marker(n.m_marker)
+          ,m_identifier(NULL)
+          ,m_tag(n.m_tag)
+          ,m_parameters(NULL)
+          ,m_value(n.m_value)
+          ,m_type(n.m_type)
+          ,m_uid(n.m_uid)
+          ,m_parent(n.m_parent)     
+{
+}
+
+/**
+ *
+ *
+ */
+node::node(const char *name) :m_is_generated(CL_GREEN) , m_ref(0), m_name(name)
+                ,m_next(NULL)
+                ,m_constraints("")
+                ,m_identifier(NULL)
+                ,m_parameters(NULL)
+                ,m_value(NULL)
+                ,m_type(NULL)
+                ,m_parent(NULL)   
+                ,m_marker(marker_type::FL_NONE)
+{
+#ifdef DEBUG
+//  std::cout<<"New Node:"<<m_name<<std::endl;
+#endif
+  if ((name == NULL) || (strlen(name)==0))
+  {
+    std::cout<<"ERROR not goof"<<std::endl;
+    exit(1);
+  }
+  m_tag.m_mode   = tag_type::TM_DEFAULT;
+  m_tag.m_class  = tag_type::TC_NOCLASS;
+  m_tag.m_value  = -1;
+  std::ostringstream oss;
+  std::string cppname;
+  cppname.resize(m_name.size());
+  std::transform(m_name.begin(),m_name.end(),cppname.begin(),asn1::lop_substitute);
+  oss<<cppname<<"_"<<g_counter;
+  m_uid = oss.str();
+  g_counter++;
+}
+
+
+//
+//
+//
+const std::string 
+node::name() const
+{
+  std::string ref_name("error");
+  if (const asn1::selection *sel = dynamic_cast<const asn1::selection *>(this))
+  {
+    return m_name;
+  } 
+  if (const asn1::typeref *tref = as_typeref()) 
+  {
+      
+     ref_name = "error-ref";
+     if ( tref->get_reference() &&
+         (*(tref->get_reference()->begin()) ).m_identifier.compare("TYPE-IDENTIFIER") == 0)
+     {
+       ref_name = "error-ref-type-identifier";
+       if (m_constraints.begin() != m_constraints.end())
+       {
+         ref_name = "error-ref-type-identifier-has-constraint";
+         asn1::constraint::const_iterator cit = m_constraints.begin(); 
+         if ( (*cit)->type() == asn1::constraint::EL_TYPE )
+              {
+           asn1::node *value = (*cit)->value();
+           ref_name = value->name();//+"/*CTY*/";
+         } 
+       }
+     } else
+     {
+      if (tref->get_reference())
+        ref_name = tref->get_reference()->name();
+     }
+   } else 
+    ref_name = m_name;
+#if 0
+   // Does not work.
+   if (meta_id() == meta::VALUE
+       && m_value)
+   {
+     ref_name = m_value->cpp_name();
+   }
+#endif
+  return ref_name; 
+}
+
+
+//
+//
+//
+const std::string 
+node::cpp_name()
+{
+std::string lname = name();
+#if 0
+std::string s; 
+s.resize(name().size());
+std::transform(lname.begin(),lname.end(),s.begin(),op_substitute);
+if (lname.compare("private") == 0) {
+  return std::string("_private");
+} else if (lname.compare("operator") == 0) {
+  return std::string("_operator");
+} else if (lname.compare("...") == 0) {
+  return std::string("_treedot");
+} else if (lname.compare("bool") == 0) {
+  return std::string("_bool");
+} else if (lname.compare("true") == 0) {
+  return std::string("_true");
+} else if (lname.compare("false") == 0) {
+  return std::string("_false");
+} else if (lname.compare("auto") == 0) {
+  return std::string("_auto");
+} else if (lname.compare("explicit") == 0) {
+  return std::string("_explicit");
+} else if (lname.compare("continue") == 0) {
+  return std::string("_continue");
+} else if (lname.compare("default") == 0) {
+  return std::string("_default");
+} else if (lname.compare("NULL") == 0) {
+  return std::string("Null");
+} else
+return s;
+#else
+  return asn1::cpp_name(lname);
+#endif
+}
+
+const std::string
+cpp_name(const std::string &lname)
+{
+  std::string s; 
+  s.resize(lname.size());
+  std::transform(lname.begin(),lname.end(),s.begin(),op_substitute);
+  if (lname.compare("private") == 0) {
+    return std::string("_private");
+  } else if (lname.compare("operator") == 0) {
+    return std::string("_operator");
+  } else if (lname.compare("...") == 0) {
+    return std::string("_treedot");
+  } else if (lname.compare("bool") == 0) {
+    return std::string("_bool");
+  } else if (lname.compare("true") == 0) {
+    return std::string("_true");
+  } else if (lname.compare("false") == 0) {
+    return std::string("_false");
+  } else if (lname.compare("auto") == 0) {
+    return std::string("_auto");
+  } else if (lname.compare("explicit") == 0) {
+    return std::string("_explicit");
+  } else if (lname.compare("continue") == 0) {
+    return std::string("_continue");
+  } else if (lname.compare("default") == 0) {
+    return std::string("_default");
+  } else if (lname.compare("NULL") == 0) {
+    return std::string("Null");
+  } else
+  return s;
+}
+
+//
+//
+//
+const std::string 
+node::identifier_name()
+{
+  if (m_identifier !=NULL) {
+    return m_identifier->name();
+  } else {
+     std::cerr<<"Identifier is NULL"<<std::endl;
+     assert(0 && "node::identifier_name is NULL not good");
+     return std::string("null");
+  }
+}
+
+//
+//
+//
+const std::string 
+node::identifier_cpp_name()
+{
+//std::cerr<<__FUNCTION__<<" HERE 1 "<<m_name<<std::endl;
+if (this->m_identifier == NULL) {
+  std::cerr<<"ERROR indentifier == NULL"<<std::endl;
+}
+//std::cerr<<"HERE 25 "<<std::endl;
+const std::string &name = m_identifier->name(); 
+//std::cerr<<"HERE 2 "<<std::endl;
+std::string s("unknown"); 
+//std::cerr<<"HERE"<<std::endl;
+if (name.size()>0) {
+  s.resize(name.size());
+  std::transform(name.begin(),name.end(),s.begin(),op_substitute);
+} 
+if (name.compare("private") == 0) {
+  return std::string("_private");
+} else if (name.compare("...") == 0) {
+  return std::string("_treedot");
+} else if (name.compare("bool") == 0) {
+  return std::string("_bool");
+} else if (name.compare("true") == 0) {
+  return std::string("_true");
+} else if (name.compare("false") == 0) {
+  return std::string("_false");
+} else if (name.compare("default") == 0) {
+  return std::string("_default");
+} else
+return s;
+}
+
+
+// Generated stuff
+void node::set_generated(bool b)
+{
+  if (b == false) {
+    m_is_generated = CL_GREEN;
+  } else {
+    if (m_is_generated != CL_RED)
+      m_is_generated = color(m_is_generated + 1);
+  }
+
+}
+
+//
+//
+//
+bool node::is_generated()
+{
+  switch(m_type_id())
+  {
+    case asn1::type::ASN1_INTEGER:
+    case asn1::type::ASN1_OCTET_STRING:
+      return true;
+      break;
+    default:
+      return m_is_generated == CL_RED;
+  };
+}
+
+//
+//
+//
+void   
+node::path2module(std::list<asn1::node *> &l)  const
+{ 
+  long depth = 0;
+  asn1::node *p = m_parent;
+  if ( p == NULL)
+  {
+    std::cerr<<"node::path2module p (parent ) is NULL for node "<<name()<<" "<<std::endl;
+    assert(0);
+  }
+  // Parent must be set.
+  assert(m_parent != NULL);
+  if (dynamic_cast<asn1::module *>(p))
+  {
+    l.push_front(const_cast<asn1::node *>(this));
+    return;
+  }
+  do 
+  {
+    if ( p == NULL)
+    {
+      std::cerr<<"node::path2module p is NULL "<<name()<<" "<<std::endl;
+      assert(0);
+    }
+    switch (p->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE_OF:
+      case asn1::type::ASN1_SET_OF:
+        p = p->get_parent();
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+      case asn1::type::ASN1_CHOICE:
+      case asn1::type::ASN1_SET:
+        if ( p->identifier() == NULL)
+        {
+          std::cerr<<"node::path2module ASSERT "<<name()<<" "<<p->name()<<std::endl;
+          // assert(0);
+         if (asn1::module *nm = dynamic_cast<asn1::module *>( p->get_parent()))
+         {
+            std::cerr<<"node::path2module ASSERT return  "<<name()<<" "<<p->name()<<std::endl;
+            l.push_front(p);
+            return;
+         } else
+         {
+            std::cerr<<"node::path2module ASSERT parent not module "<<name()<<" "<<p->name()<<std::endl;
+         } 
+        }
+        l.push_front(p);
+        p = p->get_parent();
+        break;
+     default:
+        l.push_front(p);
+        p = p->get_parent();
+        depth++;
+    }       
+  } while( (p != NULL) && (dynamic_cast<asn1::module *>(p) == NULL) && depth < 20) ;
+  assert((depth < 20) && (p != NULL));
+}
+
+/**
+ *
+ */ 
+asn1::module *node::from_module() const
+{
+  asn1::node *p = m_parent;
+  node_list nl;        
+  
+  if (asn1::module *mo = dynamic_cast<asn1::module *>(p))
+  {
+    return mo;
+  }
+  path2module(nl);
+
+
+  asn1::module *t_module = dynamic_cast<asn1::module *>(nl.front()->get_parent());
+  return t_module;
+}
+
+//
+//
+//
+bool   
+node::is_private()  const
+{ 
+  int depth = 0;
+  if (dynamic_cast<module *>(m_parent) != NULL ) 
+    return false;
+  asn1::node *p = m_parent;
+  do 
+  {
+    if ( p == NULL)
+    {
+      std::cerr<<"is_private p is NULL no parent for type "<<name()<<" "<<std::endl;
+      assert(0);
+    }
+    switch (p->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE_OF:
+      case asn1::type::ASN1_SET_OF:
+        p = p->get_parent();
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+      case asn1::type::ASN1_CHOICE:
+      case asn1::type::ASN1_SET:
+        if ( p->identifier() == NULL)
+        {
+          std::cerr<<"is_private ASSERT "<<name()<<" "<<p->name()<<std::endl;
+          assert(0);
+        } else
+        return true;
+        break;
+     default:
+       p = p->get_parent();
+       depth++;
+    }       
+  } while( (p != NULL) && (dynamic_cast<asn1::module *>(p) == NULL) && depth < 20) ;
+  assert((depth < 20) && (p != NULL));
+  return false; 
+} 
+
+asn1::valuetype   *
+node::as_value_type()
+{
+  return dynamic_cast<asn1::valuetype *>(this);
+}
+
+asn1::typenode   *
+node::as_typenode()
+{
+  return dynamic_cast<asn1::typenode *>(this);
+}
+
+asn1::enumerated   *
+node::as_enumerated()
+{
+  return dynamic_cast<asn1::enumerated *>(this);
+}
+
+
+asn1::typeref   *
+node::as_typeref()
+{
+  return dynamic_cast<asn1::typeref *>(this);
+}
+const asn1::typeref   *
+node::as_typeref() const
+{
+  return dynamic_cast<const asn1::typeref *>(this);
+}
+
+asn1::constructed *
+node::as_constructed()
+{
+  return dynamic_cast<asn1::constructed *>(this);
+}
+
+asn1::sequence *
+node::as_sequence()
+{
+  return dynamic_cast<asn1::sequence *>(this);
+}
+asn1::choice *
+node::as_choice()
+{
+  return dynamic_cast<asn1::choice *>(this);
+}
+
+asn1::set *
+node::as_set()
+{
+  return dynamic_cast<asn1::set *>(this);
+}
+
+asn1::object *
+node::as_object()
+{
+  return dynamic_cast<asn1::object *>(this);
+}
+
+asn1::integer *
+node::as_integer()
+{
+  return dynamic_cast<asn1::integer *>(this);
+}
+
+asn1::assignment *
+node::as_assignment()
+{
+  return dynamic_cast<asn1::assignment *>(this);
+}
+
+asn1::object_identifier *
+node::as_object_identifier()
+{
+  return dynamic_cast<asn1::object_identifier *>(this);
+}
+
+asn1::parameters *
+node::as_parameters()
+{
+  return dynamic_cast<asn1::parameters *>(this);
+}
+asn1::parameter *
+node::as_parameter()
+{
+  return dynamic_cast<asn1::parameter *>(this);
+}
+
+
+asn1::act_parameters *
+node::as_act_parameters()
+{
+  return dynamic_cast<asn1::act_parameters *>(this);
+}
+
+asn1::parameters *node::parameters() const
+{
+  return m_parameters->as_parameters() ;
+}
+
+asn1::act_parameters *node::act_parameters() const
+{
+  return m_parameters->as_act_parameters() ;
+}
+
+const char *
+type::name() const
+{
+  switch (m_id)
+  {
+
+#define ASN1_TYPE(cls,parent,id) \
+    case ASN1_##id : return #id;
+
+#define ASN1_STRING_TYPE(cls,parent,id) \
+    case ASN1_STRING_##id : return #id;
+
+#include "adt/asn1_type.inc" 
+    default:
+    {
+      std::cerr<<"type::name ERROR unknow : "<<m_id<<std::endl;
+      return "unknown type ";
+    }
+  }
+
+}
+
+}
+/*
+vim:et:sw=2:ts=2:
+ */
diff --git a/adt/asn1_node.h b/adt/asn1_node.h
new file mode 100644 (file)
index 0000000..23abb71
--- /dev/null
@@ -0,0 +1,397 @@
+#ifndef ASN1_NODE_H__
+#define ASN1_NODE_H__
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ *10000 \
+                     + __GNUC_MINOR__ * 100 \
+                     + __GNUC_PATCHLEVEL__ )
+#endif
+#include <iostream>
+#include <list>
+#include <set>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <memory>     // std::shared_ptr
+#include <stdexcept>  // exception
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/sys/log.h"
+#include "aeb/pointer/intrusive_ptr.h"
+
+namespace asn1
+{
+  class object_identifier;
+  class parameters;
+  class parameter;
+  class act_parameters;
+  class typeref;
+  class integer;
+  class sequence;
+  class assignment;
+  class enumerated;
+  class choice;
+  class set;
+  class object;
+
+  inline char  op_substitute(char c)
+  {
+    return (c == '-')?'_':c;
+  }
+  class node;
+  class reference;
+  class simple_reference;
+  class objectclass_reference;
+  class module;
+  class constructed;
+  class valuetype;
+  class typenode;
+  /**
+   *
+   */
+  struct  find_node {
+    find_node(const std::string &s) : m_s(s){} 
+    bool operator ()(asn1::node *n) ;
+    std::string m_s;
+  };
+  /**
+   *
+   */
+  struct  find_type {
+    find_type(const std::string &s) : m_s(s){} 
+    bool operator ()(asn1::node *n) ;
+    std::string m_s;
+  };
+  /**
+   *
+   */
+  struct  find_value {
+    find_value(const std::string &s) : m_s(s){} 
+    bool operator ()(asn1::node *n) ;
+    std::string m_s;
+  };
+  /**
+   * This is a generic class for all kind of elements that can
+   * be found in an ASN1 definition. In terme, this class shall
+   * become an asbstract class so that it cannot be instantiated.
+   *
+   */
+  class node
+  {
+    INTRUSIVE_DECLARATION(node)
+    public:
+      typedef std::list<node *> node_list;
+      typedef std::list<node *>::iterator iterator;
+      typedef std::list<node *>::const_iterator const_iterator;
+
+    public:
+      // Constructor , Destructors
+      node(const std::string name, meta  m = meta::INVALID); 
+      
+      node(const std::string name, type  t = type::INVALID,meta m = meta::INVALID);
+      
+      node(const node &n) ;
+
+      node(const char *name) ;
+      
+      virtual ~node() {};
+      // Deep copy
+      virtual node *clone() ;
+      
+      enum color {
+        CL_GREEN     = 0,
+        CL_ORANGE    = 1,
+        CL_REENTRANT = 2,
+        CL_RED       = 3
+      };
+      
+      // Generated stuff
+      void set_generated(bool b) ;
+
+      color get_color(void)const
+      {return m_is_generated;};
+      
+      void  set_color(asn1::node::color c)
+      {m_is_generated = c;};
+      
+      bool is_generated() ;
+
+      // Name stuff 
+      const std::string name() const; 
+      
+      const void name(const std::string &n)
+      {m_name = n;}; 
+      
+      const std::string cpp_name() ;
+      // Casts
+      asn1::integer       *as_integer();
+      asn1::valuetype     *as_value_type();
+      const asn1::typeref *as_typeref() const;
+      asn1::typeref       *as_typeref() ;
+      asn1::typenode      *as_typenode();
+
+      asn1::constructed *as_constructed();
+      
+      asn1::choice      *as_choice();
+      asn1::sequence    *as_sequence();
+      asn1::enumerated  *as_enumerated();
+      asn1::set         *as_set();
+      asn1::object      *as_object();
+      
+      asn1::object_identifier *as_object_identifier();
+      
+      asn1::parameters     *as_parameters();
+      asn1::parameter      *as_parameter();
+      asn1::act_parameters *as_act_parameters();
+      asn1::assignment     *as_assignment();
+      // Iterators ...
+#define NODE_REMOVE_ITERATORS
+      //
+      inline bool is_primitive() const
+      { return m_type_id() >= type::ASN1_BOOLEAN 
+               && m_type_id() <= type::ASN1_STRING_ObjectDescriptor ;
+      }
+      inline bool is_constructed() const
+      { return (m_type_id() >= type::ASN1_SEQUENCE 
+               && m_type_id() <= type::ASN1_SELECTION )
+               || m_type_id() == type::ASN1_ENUMERATED;
+      }
+
+      inline bool is_object_identifier() const
+      { return m_type_id() == type::ASN1_OBJECT_IDENTIFIER ; };
+    
+      inline bool is_asn1() const
+      { return is_primitive() || is_constructed() || is_object_identifier(); }
+      
+      inline bool is_choice() const
+      { return m_type_id() == type::ASN1_CHOICE ; };
+      
+      inline bool is_reference() const
+      { return m_type_id() == type::ASN1_REFERENCE ; };
+      
+      inline bool is_extensible() const
+      { return m_type_id() == type::ASN1_EXTENSIBLE ; };
+
+      virtual bool equals(const node &_n ) const { return false; };
+      // str Type, type_id 
+      inline void type_node(node *t) { m_type = t; }
+      
+      inline node *type_node() const { return m_type; }
+
+      // parameter stuff does not apply to all nodes
+      // see if this can be moved to another place
+      asn1::parameters *parameters() const;
+
+      inline void  parameters(asn1::constructed *n)
+      { m_parameters = n; };
+      
+      asn1::act_parameters *act_parameters() const;
+
+      inline void  act_parameters(asn1::constructed *n)
+      { m_parameters = n; };
+
+
+      // str Identifier
+      inline void identifier(node *t) { m_identifier = t; }
+      
+      inline node *identifier() const { return m_identifier; }
+      
+      const std::string identifier_name( ) ;
+
+      const std::string identifier_cpp_name( ) ;
+
+      inline std::string uid(void) {return m_uid;};
+
+      // Type_id stuff 
+      inline void type_id(asn1::type::id t) { m_type_id = t; }
+
+      inline type type_id() const {return m_type_id;};
+      
+      inline asn1::value *value() const { return m_value;};
+
+      inline void value(asn1::value *v) {m_value =v;};      
+      // Meta stuff
+      inline void meta_id(asn1::meta::id m) {m_meta = m;}
+      
+      inline meta  meta_id() const {return m_meta ;}
+
+      inline bool operator >(const node &n) {return m_meta > n.m_meta;};
+      /**
+       * two nodes are equal if, they are of the same type,
+       * have the same tagging,
+       * have the same contraints
+       * have the same elements
+       *
+       */ 
+      bool operator ==(const node &_n) { return equals(_n) ;};
+      static bool op_sort(asn1::node *n1,asn1::node *n2)
+      {
+#if 0
+        std::cout<<"Compare : "<<n1->meta_id()<<" "<<n2->meta_id()<<std::endl;
+#endif
+        return (n1->meta_id()) > (n2->meta_id());
+      }
+      
+      /// Tag stuff
+      struct tag_type {
+        //inline tag_type() : m_class(TC_NOCLASS),m_mode(TM_DEFAULT) {};
+        enum {
+          TC_NOCLASS ,  
+          TC_UNIVERSAL          = 0,
+          TC_APPLICATION        = 1,
+          TC_CONTEXT_SPECIFIC   = 2,
+          TC_PRIVATE            = 3
+        } m_class;
+
+        enum {
+          TM_DEFAULT,
+          TM_IMPLICIT,
+          TM_EXPLICIT,
+          TM_AUTOMATIC
+        } m_mode;
+        inline  long byte() const { return m_class<<6 | m_value; };
+        inline  long get_tag() const { return m_value<<2 | m_class; };
+        long    m_value;
+        bool    m_set;
+      };
+      // Do not set -1 tags
+      inline void tag(tag_type &t)
+      { if (t.m_value != -1 ) {m_tag = t; m_tag.m_set = true;} };
+
+      inline tag_type  tag() const {return m_tag;};
+      inline tag_type &tag()       {return m_tag;};
+      inline bool tagged() const
+      { return m_tag.m_set && m_tag.m_value>=0 && m_tag.m_class>= 0; };
+      // Marker flags 
+      struct marker_type 
+      {
+        inline bool is_omitable() const
+        { return (m_flags & FL_OMITABLE) == FL_OMITABLE; };
+       
+        inline bool is_optional() const
+        { return (m_flags & FL_OPTIONAL) == FL_OPTIONAL; };
+
+        inline bool is_default() const
+        { return m_flags == FL_DEFAULT; };
+        
+        enum eFlag {
+          FL_NONE = 0,
+          FL_OMITABLE = 0x02, /* 00010  can be absente in encoding */
+          FL_OPTIONAL = 0x07, /* 00111 default value */
+          FL_DEFAULT  = 0x0F  /* 01111*/
+        } m_flags;
+        
+        marker_type(eFlag t = FL_NONE) : m_flags(t), m_value1(NULL)
+        {};
+
+        marker_type(const marker_type &m)
+            : m_flags(m.m_flags) ,m_value1(m.m_value1)
+        {};
+        marker_type & operator = (const marker_type &m) 
+        { 
+          m_value1 = m.m_value1; 
+          m_flags = m.m_flags; 
+          m_value = m.m_value; return *this;
+        };
+        //TODO Should also check value BUG
+        bool operator ==(const marker_type &m) const
+        {
+          return m_flags == m.m_flags;
+        };
+        int m_value; /* When default value 
+                        I would like it to be of type asn1::value::ptr */
+        asn1::value::ptr    m_value1;
+      };
+      
+      marker_type flags() const {
+      //        std::cout<<"node::flags() "<<m_marker.m_flags<<std::endl;
+       return m_marker;
+      };
+      
+      inline void flags(marker_type *f)  {if (f) m_marker = *f;};
+      // Traversal of nodes
+      inline void set_parent(node *p)      { m_parent = p ;    } 
+      inline node * get_parent () const    { return m_parent ; };
+
+      // This function computes the nodes between module and node
+      //  example : SEQUENCE { e1 SEQUENCE { e2 SET OF SEQUENCE { } } }
+      void path2module(std::list<asn1::node *> &l) const;
+      asn1::module *from_module() const;
+      bool   is_private()  const;
+
+    protected:
+      node          *m_parent; 
+      asn1::meta     m_meta;
+      asn1::type     m_type_id;
+      std::string    m_name;
+      node          *m_next;
+      
+      node              *m_type;   // 2011/05/03 must be deprecated
+      asn1::value       *m_value;  // Should become part of valuetype
+      node              *m_identifier;
+      asn1::constructed *m_parameters;
+      asn1::constraint  m_constraints;
+      tag_type      m_tag;
+      marker_type         m_marker;
+      union {
+        long long          m_value_long;
+        double             m_value_double;
+      } ;
+      color          m_is_generated;
+      std::string  m_uid;
+  };
+  // Helper function for code generation
+  const std::string
+  cpp_name(const std::string &lname);
+
+  inline bool find_node::operator ()(asn1::node *n) 
+     {
+      if (n == NULL) return false;
+      //std::cout<<" mds as:"<<n->name()<<std::endl;
+      return !m_s.compare(n->name());
+    };
+  inline bool find_type::operator ()(asn1::node *type) 
+     {
+      if (type == NULL) return false;
+      //std::cout<<" mds as:"<<n->name()<<std::endl;
+      return !m_s.compare(type->identifier_name());
+    };
+  
+  inline bool find_value::operator ()(asn1::node *type) 
+     {
+      if (type == NULL) return false;
+      //std::cout<<" mds as:"<<n->name()<<std::endl;
+      return !(type->meta_id()() == asn1::meta::VALUE) && !m_s.compare(type->name());
+    };
+
+/* Add a container class here */
+
+/* ALL asn1 Datatypes that can be  instantiated */
+#include "asn1_node_typenode.h"
+#include "asn1_node_constructed.h"
+#include "asn1_node_imports.h"
+#include "asn1_node_exports.h"
+#include "asn1_node_parameters.h"
+#include "asn1_node_typeref.h"
+#include "asn1_node_selection.h"
+#include "asn1_node_field.h"
+#include "asn1_node_alternative_choice.h"
+#include "asn1_node_primitive.h"
+#include "asn1_node_choice.h"
+#include "asn1_node_sequence.h"
+#include "asn1_node_sequence_of.h"
+#include "asn1_node_set.h"
+#include "asn1_node_set_of.h"
+#include "asn1_node_classdef.h"
+#include "asn1_node_valuetype.h"
+#include "asn1_node_object.h"
+#include "asn1_node_assignment.h"
+
+}
+#include "asn1_reference.h"
+/*
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/adt/asn1_node_alternative_choice.h b/adt/asn1_node_alternative_choice.h
new file mode 100644 (file)
index 0000000..649f64e
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef ASN1_NODE_ALTERNATIVE_CHOICE_H
+#define ASN1_NODE_ALTERNATIVE_CHOICE_H
+
+
+class alternative_choice : public node
+{
+  public:
+    
+    alternative_choice() ;  
+    ~alternative_choice() ;
+
+  protected:  
+};
+
+
+#endif
diff --git a/adt/asn1_node_assignment.cpp b/adt/asn1_node_assignment.cpp
new file mode 100644 (file)
index 0000000..7911d2a
--- /dev/null
@@ -0,0 +1,69 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+assignment::assignment(const std::string &s)
+  : node(s,type::INVALID,meta::INVALID)
+{
+}
+
+assignment::assignment(const std::string &s,asn1::type t,asn1::meta m)
+  : node(s,t,m)
+{
+}
+
+void assignment::set_type(asn1::node *type)
+{
+  type_node(type);  
+}
+
+typenode *
+assignment::get_type() const
+{
+  return reinterpret_cast<typenode *>(type_node());
+}
+
+objectset *
+assignment::get_objectset() const
+{
+  return reinterpret_cast<objectset *>(type_node());
+}
+
+parameter *
+assignment::have_parameter(asn1::node *actp,long &idx)
+{
+  idx = 0;
+  if (actp && m_parameters)
+  {
+    for (asn1::node::iterator pit = parameters()->begin();
+         pit != parameters()->end();
+         ++pit,++idx)
+    {
+      asn1::parameter *p = (*pit)->as_parameter();
+      if (p && p->get_typeref()->name() == actp->name())
+        return p;
+    }
+
+  }
+  return NULL;
+}
+}
+
+/**
+ * vim: et sw=2 ts=2:
+ */ 
diff --git a/adt/asn1_node_assignment.h b/adt/asn1_node_assignment.h
new file mode 100644 (file)
index 0000000..6d07141
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef ASN1_NODE_ASSIGNMENT_H
+#define ASN1_NODE_ASSIGNMENT_H
+
+
+/**
+ * This class represents an
+ * asn1 assignment examples :
+ *   Type ::=  SEQUENCE ...
+ *   OBJECTSET ::= {} and so on
+ *
+ */ 
+class assignment : public node
+{
+  public:
+    assignment(const std::string &s) ;
+    assignment(const assignment &a)
+     : node(a)
+    {}
+
+    assignment(const std::string &s,asn1::type t,asn1::meta m) ;
+
+    assignment *clone() { return new assignment (*this); }
+    // Should replace node with typenode
+    void set_type(asn1::node *n);
+
+    typenode  *get_type() const;
+    objectset *get_objectset() const;
+    /**
+     * node is an act_parameter ...
+     */ 
+    parameter *have_parameter(asn1::node *,long &idx);
+  protected:
+};
+
+#define ASSIGNMENT(tp,cls,parent) \
+    class cls ## _assignment : public parent \
+    {\
+      public:\
+       cls ## _assignment (const std::string &s) \
+          : parent( s,asn1::type::INVALID,asn1::meta::tp) {} ; \
+       cls ## _assignment (const cls ## _assignment &a) \
+        : parent(a)   \
+        {}; \
+       ~cls ## _assignment () {}; \
+       cls ## _assignment *clone() { return new cls ## _assignment(*this);}; \
+    };
+
+#include "asn1_meta.inc"
+
+#endif /*ASN1_NODE_ASSIGNMENT_H*/
+/**
+ * vim: et sw=2 ts=2:
+ */ 
diff --git a/adt/asn1_node_choice.cpp b/adt/asn1_node_choice.cpp
new file mode 100644 (file)
index 0000000..ed75c5e
--- /dev/null
@@ -0,0 +1,129 @@
+#include <iostream>
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_resolver.h"
+
+
+namespace asn1 
+{
+
+choice::choice() :  constructed("CHOICE",type::ASN1_CHOICE)
+{
+} 
+
+choice::choice(const choice &c) :  constructed(c.name(),type::ASN1_CHOICE)
+{
+  std::cerr<<"choice::choice copy "<<c.size()<<" "<<name()<<" "<<c.name()<<std::endl;
+  if (this != &c)
+  {
+    // duplicate elements in vector
+    for ( asn1::node::const_iterator it = c.begin()
+        ; it != c.end()
+        ;  ++it)
+    {
+      asn1::field *f = dynamic_cast<asn1::field *>(*it);
+      std::cerr<<"choice::choice"<<name()<<" clone "<<(*it)->name()<<std::endl;
+      asn1::field *nn = f->clone();
+      nn->set_parent(this); 
+      nn->get_type()->set_parent(this);
+      append(nn);
+      std::cerr<<"choice::choice end  "<<name()<<" clone "<<(*it)->name()<<std::endl;
+    }
+    std::cerr<<"choice::choice clone identidier "<<size()<<" "<<name()<<"\n"<<std::endl;
+    set_parent(c.identifier()->get_parent());
+  }
+  std::cerr<<"choice::choice copy end "<<size()<<" "<<name()<<"\n"<<std::endl; 
+} 
+
+/**
+ *
+ */
+asn1::node::tag_type 
+choice::get_tag(asn1::resolver &r) const
+{
+  asn1::node *ftype = dynamic_cast<asn1::field *>(*begin()) -> get_type();
+
+  // std::cerr<<"choice::"<<__FUNCTION__<<" Begin type "<<name()<<" \n";
+loopref:
+  if (ftype->tagged())
+  {
+    //std::cerr<<"choice::"<<__FUNCTION__<<" tagged type "<<ftype->name()<<" \n";
+    return ftype->tag();
+  }
+  // Untagged reference,
+  //  Check realtype
+  if (asn1::typeref *ref = ftype->as_typeref())
+  {
+    std::cerr<<"choice::"<<__FUNCTION__<<" type "<<name()<<" ";
+    std::cerr<<" got ref :"<<ref->name()<<std::endl;
+    if (asn1::node *rtype = ref->get_real_type())
+    {
+      // tagged realtype
+      if (rtype->tagged())
+      {
+        std::cerr<<"choice::"<<__FUNCTION__<<" tagged type "<<rtype->name()<<" \n";
+        assert(rtype->tag().m_value != -1);
+        return rtype->tag();
+      }
+      if (asn1::choice *c = dynamic_cast<asn1::choice *>(rtype))
+      {
+        return c->get_tag(r);
+      }
+      // Not a tagged type , Not Choice
+      if (rtype->tag().m_value != -1)
+        return rtype->tag();
+      // Still a reference, dig deeper,
+      if (rtype->as_typeref()) 
+      {
+        ftype = rtype;
+        goto loopref;
+      }
+      // tag is -1 assert an error I don't know what to do
+      std::cerr<<"choice::"<<__FUNCTION__<<" type "<<name()<<" ";
+      std::cerr<<" Can't find valid tag for choice init :"<<rtype->name()<<std::endl;
+      assert(0 && "Could not find valid tag for choice");
+      
+    }
+    asn1::module *m = ref->from_module();
+    std::cerr<<"choice::"<<__FUNCTION__<<" type "<<m->name()<<"::"<<name()<<" ";
+    std::cerr<<" no real type Aieee :"<<ref->name()<<std::endl;
+    ftype = r.resolve(*ref);
+    std::cerr<<"  new:"<<ftype->name()<<std::endl;
+    assert((ftype != NULL) && "Still tag not found");
+    goto loopref;
+  }
+
+  // Not a tagged, Not Choice
+  if (ftype->tag().m_value != -1)
+    return ftype->tag();
+  if (asn1::choice *nc = dynamic_cast<asn1::choice *>(ftype))
+  {
+    return nc->get_tag(r);
+  }
+  std::cerr<<"choice::"<<__FUNCTION__<<" type "<<name()<<" ";
+  std::cerr<<" Can't find valid tag for choice init :"<<ftype->name()<<std::endl;
+  assert(0 && "Still tag not found");
+}
+
+void
+choice::add_alternative(asn1::node *c)
+{
+  append(c); 
+}
+
+}
+/**
+ *  vim: et sw=2 ts=2 list:
+ */ 
diff --git a/adt/asn1_node_choice.h b/adt/asn1_node_choice.h
new file mode 100644 (file)
index 0000000..26ecda5
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef ASN1_NODE_CHOICE_H
+#define ASN1_NODE_CHOICE_H
+
+
+class choice : public constructed
+{
+  protected:  
+    choice(const choice &c) ; 
+  public:
+    
+    //choice() : constructed("CHOICE",asn1::type::ASN1_CHOICE) { } ;  
+    choice() ;  
+
+    virtual ~choice() {};
+    
+    virtual choice *clone() { return new choice(*this); };
+    /**
+     * @brief retrieve the appropriate tag for
+     * first node. if it's a choice, lookup further 
+     * until I get a valide tag.
+     *   Example: PDU ::= CHOICE {
+     *     aarq Arq
+     *     rl   Rrq
+     *   }
+     *   Arq ::= CHOICE {
+     *     invoke [ 1 ] IMPLICIT Invoke
+     *   }
+     */ 
+    asn1::node::tag_type get_tag(asn1::resolver &r) const;
+    // alternative_choice_iterator 
+    void add_alternative(asn1::node *);
+  protected:
+    int test;
+};
+
+
+#endif
+/*
+ * vim: et sw=2 ts=2 :
+ */ 
diff --git a/adt/asn1_node_classdef.cpp b/adt/asn1_node_classdef.cpp
new file mode 100644 (file)
index 0000000..c810c40
--- /dev/null
@@ -0,0 +1,452 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1 
+{
+namespace internal
+{
+
+/**
+ * Abstract state ...
+ */  
+state::state()
+{
+}
+
+void state::visit(visitor *v) const
+{
+  ;
+}
+/**
+ * transition state 
+ */  
+transition::transition(transition_type t) : m_type(t),m_next(NULL)
+{
+}
+
+void transition::visit(visitor *v) const
+{
+  v->visit_transition(dynamic_cast<const transition &>(*this));
+}
+
+/**
+ * split state 
+ */  
+split::split(state *start,state *end)
+  : m_first(start),m_second(end)
+{
+}
+
+void split::visit(visitor *v) const
+{
+  ;
+  v->visit_split(dynamic_cast<const split &>(*this));
+}
+
+/**
+ * match state 
+ */  
+match::match()
+{
+}
+
+void match::visit(visitor *v) const
+{
+  v->visit_match(dynamic_cast<const match &>(*this));
+}
+
+} /* end namespace internal */ 
+
+/**
+ * CLASS classdef_nfa
+ */ 
+classdef_nfa::classdef_nfa(state *start,state *end,std::shared_ptr<state_pool> pool)
+  : m_start(start),m_end(end), m_pool(pool) 
+{
+}
+
+
+void 
+classdef_nfa::visit(visitor *v) const
+{
+  v->visit(*m_start,*m_end);
+}
+
+/**
+ * CLASS syntax_parser
+ */ 
+
+syntax_parser::fragment::fragment(std::shared_ptr<state_pool> pool)
+  : m_pool(pool),m_start(NULL) 
+{
+}
+
+syntax_parser::fragment::fragment(  asn1::node *n
+                                  , std::shared_ptr<state_pool> pool)
+  : m_pool(pool)
+{
+
+    transition *trans = NULL;
+    if (n->type_id()() == asn1::type::INVALID)
+    { 
+      trans = m_pool->make_transition(transition::eToken);
+    } else
+      trans = m_pool->make_transition(transition::eType);
+    trans->m_node_type = n;
+    m_out_edges.push_back(&(trans->m_next));
+    m_start = trans;
+}
+
+std::string
+syntax_parser::fragment::name() const
+{
+  if (m_start)
+  {
+    if (transition *t = dynamic_cast<transition *>(m_start))
+    {
+      std::string s("<transition frag ");
+      s = s + t->m_node_type->name() +">";
+      return s;
+    }
+    if (dynamic_cast<split *>(m_start))
+    {
+      return std::string("<split fragment>");
+    }
+    if (dynamic_cast<match *>(m_start))
+    {
+      return std::string("<match fragment>");
+    }
+  }
+  return std::string("<empty fragment>");
+}
+
+/**
+ *
+ *       .-------.    .-------.
+ *   --->| frag1 |--->| frag2 |---> 
+ *       '-------'    '-------' 
+ */ 
+void 
+syntax_parser::fragment::concat(const fragment &frag)
+{
+  for (size_t i = 0 ; i < m_out_edges.size() ; i++)
+  {
+    *m_out_edges[i] = frag.m_start;  
+  }
+  m_out_edges = frag.m_out_edges;
+}
+
+
+/**
+ *
+ *
+ *                   .-------.
+ *          .------->| frag2 |--->
+ *          |        '-------' 
+ *      .-------.
+ *  --->| split |
+ *      '-------'
+ *          |        .-------.
+ *          '--------| frag1 |--->
+ *                   '-------'
+ */ 
+void 
+syntax_parser::fragment::_split(const fragment &frag)
+{
+  m_start = m_pool->make_split(m_start,frag.m_start);
+  // Append outgoing edges from frag
+  for ( size_t i = 0 ; i < frag.m_out_edges.size() ; i++)
+  {
+    m_out_edges.push_back(frag.m_out_edges[i]);  
+  }
+}
+
+/**
+ *
+ *
+ *                   .------.
+ *          .------->| frag |--->
+ *          |        '------' 
+ *      .-------.
+ *  --->| split |
+ *      '-------'
+ *          |
+ *          '------------------->
+ */ 
+void 
+syntax_parser::fragment::zero_or_one()
+{
+  split *s = m_pool->make_split(m_start,NULL);
+  // Append outgoing edges from frag
+  m_out_edges.push_back(&(s->m_second));
+  m_start = s;
+}
+
+
+/**
+ *
+ */ 
+std::shared_ptr<classdef_nfa > 
+syntax_parser::fragment::to_nfa()
+{
+  match *m = m_pool->make_match();
+  
+  for ( size_t i = 0 ; i < m_out_edges.size() ; i++)
+  {
+    *m_out_edges[i] = m ;
+  }
+  return std::shared_ptr<classdef_nfa>(
+          new classdef_nfa(m_start,m,m_pool) );
+}
+
+
+
+
+
+/**
+ * CLASS thomson_algorithm 
+ */ 
+
+thomson_algorithm::thomson_algorithm()
+    : m_matched(false)
+      , m_object(NULL)
+      , m_start(NULL), m_end(NULL)
+      , m_current() , m_next()
+{
+}
+
+
+bool
+thomson_algorithm::accept(object *o,const std::shared_ptr<classdef_nfa> nfa)
+{
+  m_object     = o;
+  m_current_it = o->begin();
+  nfa->visit(this);
+#if 0  
+  std::cerr<<"thomson_algorithm::accept( matched "<<m_matched;
+  std::cerr<<" or end == end = "<<(m_current.find(m_end) != m_current.end());
+  std::cerr<<") and end="<<(m_current_it == o->end());
+  if (m_current_it != o->end())
+    std::cerr<<" cur_it="<<(*m_current_it)->name(); 
+  std::cerr<<std::endl;
+#endif
+  return (m_matched || m_current.find(m_end) != m_current.end()) && m_current_it == o->end();
+}
+  
+    
+void
+thomson_algorithm::visit(const state &start,const state &end)
+{
+    m_start = &start;
+    m_end   = &end;
+    m_current.clear();
+    m_current.insert(m_start);
+  
+    asn1::node *field = *m_current_it;
+    //std::cerr<<"visite_nfa "<<field->name()<<std::endl;
+
+    while ( (m_current_it != m_object->end()) && (m_current.size() != 0))
+    {
+      m_matched = false;
+#if 0
+      std::cerr<<"\nSTART NODE "<<" matched: "<<m_matched;
+      std::cerr<<" current.size "<<m_current.size()<<std::endl;
+#endif
+      // visit all states
+      for (state_const_iterator i = m_current.begin() ;
+           i != m_current.end(); ++i)
+      {
+        (*i)->visit(this);  
+      }
+      ++m_current_it; // advance
+      m_current.swap(m_next);
+      m_next.clear();
+#if 0      
+      if (m_current_it == m_object->end())
+      {
+        std::cerr<<"NEXT NODE "<<" previous matched: "<<m_matched<<std::endl;
+      } else
+        std::cerr<<"NEXT NODE "<<(*m_current_it)->name()<<" previous matched: "<<m_matched<<std::endl;
+#endif
+    } 
+   // May be it's a match. If next is a split and second contains end.
+   const split *_next = dynamic_cast<const split *>(*(m_current.begin()));
+   if (_next)
+   {
+     _next->visit(this);
+   }
+}
+
+
+void
+thomson_algorithm::visit_transition(const transition &trans)
+{
+  asn1::node *field = *m_current_it;
+  // Check if there is a match
+  if (m_current_it != m_object->end())
+  {
+    if ( trans.is_token() 
+          && !field->name().compare(trans.m_node_type->name()) )
+    {  
+      // Ok, got expected token
+      m_next.insert(trans.m_next); 
+    } else if (trans.is_type() )
+    { // Check type
+      //std::cerr<<"visite_transition MATCH "<<field->name();
+      //std::cerr<<" nd:"<<trans.m_node_type->name()<<std::endl;
+      m_object->parsed_field(trans.m_node_type->name(),field);
+      m_next.insert(trans.m_next); 
+    } else
+    {
+      //std::cerr<<"visite_transition no match "<<field->name();
+      //std::cerr<<" nd:"<<trans.m_node_type->name()<<std::endl;
+    }
+  }
+
+}
+
+      
+void
+thomson_algorithm::visit_split(const split &s)
+{
+  asn1::node *field = *m_current_it;
+#if 0
+  if (m_current_it != m_object->end())
+    std::cerr<<"visite_split "<<field->name()<<std::endl;
+#endif
+  s.m_first->visit(this);
+  s.m_second->visit(this);
+}
+
+      
+void
+thomson_algorithm::visit_match(const match &trans)
+{
+  asn1::node *field = *m_current_it;
+#if 0
+  if (m_current_it != m_object->end())
+    std::cerr<<"visite_match "<<field->name()<<std::endl;
+#endif
+  m_matched = true;  
+}
+
+
+/**
+ * CLASS classdef
+ */ 
+classdef::classdef() 
+  : constructed("OBJECT_CLASS",type::ASN1_CLASSDEF,meta::OBJECTCLASS)
+{
+} 
+
+void
+classdef::start_syntax()
+{
+  m_pool = std::make_shared<state_pool>();    
+} 
+
+//
+classdef::~classdef()
+{
+}
+
+//
+bool
+classdef::check_object_syntax(object *_o)
+{
+  thomson_algorithm algo; 
+  bool result = algo.accept(_o,m_nfa); 
+  return result;
+}
+
+//
+classdef::fragment *
+classdef::parse_token(asn1::node *t)
+{
+  fragment *frag = new fragment(t,m_pool);
+  return frag;
+}
+    
+//
+classdef::fragment * 
+classdef::parse_optional(fragment *frag)
+{
+  assert(frag != NULL);
+  frag->zero_or_one();
+  return frag;
+}
+//
+classdef::fragment *
+classdef::parse_append(fragment *f1,fragment *f2)
+{
+  assert(f1 != NULL && f2!=NULL);
+  f1->concat(*f2);
+  return f1;
+}
+//
+classdef::fragment *
+classdef::parse_new()
+{
+  fragment *frag = new fragment(m_pool);
+  return frag;
+}
+//
+void 
+classdef::set_nfa(fragment *f)
+{
+   assert(f != NULL);
+   m_nfa = f->to_nfa();
+}
+
+// 
+void 
+classdef::add_field(asn1::classfield *c)
+{
+  append(c); 
+  if (c->type_node() && c->type_node()->flags().is_optional())
+  {
+    m_optionals.push_back(c); 
+  }
+}
+
+asn1::classfield *
+classdef::get_classfield(const std::string &name)
+{
+  asn1::node::iterator found = std::find_if( begin()
+                                             , end()
+                                             , asn1::find_node(name));
+  if (found != end() )
+    return dynamic_cast<asn1::classfield *>(*found);
+
+  return NULL;
+}
+
+struct fieldcmp
+{
+  bool operator()(asn1::node *a,asn1::node *b)
+  {
+    return a->type_id()() < b->type_id()();
+  }
+};
+// 
+void 
+classdef::sort_fields()
+{
+  //std::sort(begin(),end(),fieldcmp());
+  m_nodes.sort(fieldcmp());
+}
+
+} /* end namespace asn1     */
diff --git a/adt/asn1_node_classdef.h b/adt/asn1_node_classdef.h
new file mode 100644 (file)
index 0000000..0106416
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef ASN1_NODE_CLASSDEF_H
+#define ASN1_NODE_CLASSDEF_H
+#if defined(_WIN32)
+/* MSDN Visual Studion 14 exception handling ... */
+#pragma warning(disable : 4290)
+#endif
+
+class object;
+namespace internal {
+  struct state;
+  struct transition;
+  struct split;
+  struct match;
+
+  class visitor
+  {
+    public:
+      virtual void visit(const state &start,const state &end) = 0;
+
+      virtual void visit_transition(const transition &trans) = 0;
+      
+      virtual void visit_split(const split &trans) = 0;
+      
+      virtual void visit_match(const match &trans) = 0;
+  };
+
+  /**
+   *
+   */ 
+  struct state 
+  {
+    state();
+
+    virtual void visit(visitor *) const;
+  };
+
+  /**
+   *
+   */ 
+  struct transition : public state 
+  {
+    typedef enum { eToken,eType} transition_type;
+    transition(transition_type);
+    
+    inline bool is_token() const { return m_type == eToken; };
+    inline bool is_type() const { return m_type == eType; };
+    
+    virtual void visit(visitor *) const;
+   
+    transition_type m_type;
+    node           *m_node_type;
+    state          *m_next;
+  };
+
+  /**
+   * 
+   */ 
+  struct split : public state 
+  {
+    split(state *first,state*second);
+
+    virtual void visit(visitor *) const;
+    state          *m_first;
+    state          *m_second;
+  };
+  /**
+   *
+   */ 
+  struct match : public state 
+  {
+    match();
+
+    virtual void visit(visitor *) const;
+  };
+
+  /**
+   *  StatePool stack
+   */ 
+class state_pool {
+
+    //! \brief state_pool memory representation.
+    //!
+    //! No data alignement is performed when a Chunk
+    //! allocates memory, i.e. it can't be used in a
+    //! general case.
+    template <unsigned int chunk_size>
+    struct Chunk {
+    public:
+        //! \brief Default constructor.
+        //! \post The next pointer is NULL
+        //! \post The data_index is set to 0.
+        Chunk(): next(NULL), data_index(0) {}
+
+        //! \brief Reserve N bytes in this chunk.
+        //! \param nbytes Number of bytes to allocate/reserve.
+        //! \pre The requested number of bytes (nbytes) must be
+        //!      smaller or equal (<=) to the chunk_size.
+        //! \return A raw pointer to the begining of the reserved
+        //!         memory space.
+        void* reserve(size_t nbytes) throw(std::logic_error) {
+
+            // Make sure that a Chunk can really
+            // serve a request of this size.
+            if (nbytes > chunk_size)
+                throw std::logic_error("state_pool::Chunk::reserve(): the "
+                                       "requested number of bytes is bigger "
+                                       "than a chunk_size.");
+
+            // Make sure that we have enough room serve
+            // the request. If not return NULL. The pool
+            // will handle this by allocating a new chunk.
+            if (chunk_size - data_index >= nbytes) {
+                void* dptr = &data[data_index];
+                data_index += nbytes;
+                return dptr;
+            }
+
+            return NULL;
+        }
+
+        Chunk* next;             /**< A pointer to the next chunk. */
+        unsigned int data_index; /**< Current position in the data array. */
+        char data[chunk_size];   /**< Allocation array containing chunk_size bytes. */
+    };
+
+    typedef Chunk<64> MemoryChunk;
+
+public:
+
+    //! \brief Default constructor.
+    state_pool() {
+        root_chunk = last_chunk = new MemoryChunk;
+    }
+
+    //! \brief Destructor.
+    //!
+    //! Free all memory associated to the states allocated from
+    //! this pool. Beware that it won't call the destructor on
+    //! those objects.
+    ~state_pool() {
+        while (root_chunk) {
+            MemoryChunk* temp_chunk = root_chunk;
+            root_chunk = root_chunk->next;
+            delete temp_chunk;
+        }
+    }
+
+    //! \brief Construct a split state from the pool.
+    //! \param[in] first The first neighbor State.
+    //! \param[in] second The second neighbor State.
+    //! \return A pointer to the newly constructed split state.
+    split* make_split(state* first, state* second) {
+        void* _split = reserve(sizeof(split));
+        new (static_cast<void*>(_split)) split(first, second);
+        return reinterpret_cast<split*>(_split);
+    }
+
+    //! \brief Construct a transition state from the pool.
+    //! \param label The transition label.
+    //! \return A pointer to the newly constructed transition state.
+    transition* make_transition(transition::transition_type label) {
+        void* trans = reserve(sizeof(transition));
+        new (static_cast<void*>(trans)) transition(label);
+        return reinterpret_cast<transition*>(trans);
+    }
+
+    //! \brief Construct a match state from the pool.
+    //! \return A pointer to the newly constructed match state.
+    match* make_match() {
+        void* _match = reserve(sizeof(match));
+        new (static_cast<void*>(_match)) match();
+        return reinterpret_cast<match*>(_match);
+    }
+
+protected:
+
+    //! \brief Reserve N bytes from this pool.
+    //! \param nbytes Number of bytes to allocate/reserve.
+    //! \return A raw pointer to the begining of the reserved
+    //!         memory space.
+    void* reserve(size_t nbytes) {
+        // Try to reserve N bytes from the last
+        // allocated memory chunk.
+        void* data = last_chunk->reserve(nbytes);
+
+        // Check if it's a miss. If so, we'll
+        // need to allocate a new chunk.
+        if (!data) {
+            last_chunk->next = new MemoryChunk;
+            last_chunk = last_chunk->next;
+            data = last_chunk->reserve(nbytes);
+        }
+
+        return data;
+    }
+
+    state_pool(const state_pool&) {}
+    void operator=(const state_pool&) {}
+
+    MemoryChunk* root_chunk; /**< First allocated chunk. */
+    MemoryChunk* last_chunk; /**< Last allocated chunk. */
+};
+
+} /* end namespace internal */
+
+class syntax_parser;
+class classdef_nfa
+{
+  protected:
+    friend class syntax_parser; 
+    typedef internal::state state;
+    typedef internal::state_pool state_pool;
+    typedef internal::visitor visitor;
+    classdef_nfa(state *start,state *end,std::shared_ptr<state_pool> pool);
+  public:
+
+    void visit(visitor *v) const;
+  protected:
+    state                      *m_start;
+    state                      *m_end;
+    std::shared_ptr<state_pool> m_pool;
+};
+
+/**
+ * fragments must be visible to the asn1 parser
+ * as it is the one the builds the parsing tree 
+ */ 
+class syntax_parser
+{
+  public:
+    typedef internal::state      state;
+    typedef internal::transition transition;
+    typedef internal::split      split;
+    typedef internal::match      match;
+    typedef internal::state_pool state_pool;
+    /**
+     * \brief Class representing a partial fragment of the nfa
+     */ 
+    class fragment
+    {
+      public:
+        /**
+         * Build an empty fragment
+         */ 
+        fragment(std::shared_ptr<state_pool> pool);
+        /**
+         * Build an transition framgent
+         */ 
+        fragment(asn1::node *,std::shared_ptr<state_pool> pool);
+
+        void concat(const fragment &frag);
+
+        void _split(const fragment &frag);
+
+        std::string name() const;
+
+        void zero_or_one();
+        
+        std::shared_ptr<classdef_nfa > to_nfa();
+      protected:
+        state                      *m_start;
+        std::vector<state **>       m_out_edges;
+        std::shared_ptr<state_pool> m_pool;
+    };
+
+  protected:
+    std::shared_ptr<state_pool> m_pool;
+
+};
+
+
+/**
+ *
+ */
+class thomson_algorithm : public internal::visitor
+{
+  typedef internal::state      state; 
+  typedef internal::transition transition; 
+  typedef internal::split      split; 
+  typedef internal::match      match; 
+  protected:
+
+  public:
+    typedef std::set<const state *>::const_iterator state_const_iterator;
+    thomson_algorithm() ;
+
+    bool accept(object *o,const std::shared_ptr<classdef_nfa> nfa);  
+    
+    void visit(const state &start,const state &end);
+
+    void visit_transition(const transition &trans);
+      
+    void visit_split(const split &trans);
+      
+    void visit_match(const match &trans);
+  protected:
+    bool m_matched;
+    node::iterator m_current_it;
+    object         *m_object; // token to go through are in object
+    const state   *m_start;
+    const state   *m_end;
+    std::set<const state *>  m_current;
+    std::set<const state *>  m_next;
+};
+
+/**
+ * class definition. This object can be followed with syntax
+ *   it should have code to build the parser for the defined syntax
+ *   and check if the object defined respects the defined syntax
+ *
+ * in order to parser the tokens properly, I should passe the object as
+ * reference. The object contains the token, the parser will set
+ * the appropriate fields according to the tokens and the defined parser
+ */ 
+class classdef : public constructed
+{
+  public:
+    typedef syntax_parser::fragment   fragment;   
+    typedef syntax_parser::state_pool state_pool;   
+    
+    typedef std::vector<asn1::node *>   OptionalArrayType;
+    typedef OptionalArrayType::iterator OptionalIterator;
+    
+    classdef() ;
+    ~classdef() ;
+    /**
+     * At a given time, the with syntax must have been used.
+     *  parse all token and build a simple automaton. 
+     *
+     */ 
+    fragment *parse_token(asn1::node *t);
+    //
+    fragment *parse_optional(fragment *f);
+    //
+    fragment *parse_append(fragment *f1,fragment *f2);
+    //
+    fragment *parse_new();
+    //
+    void set_nfa(fragment *f);
+    //
+    void start_syntax();
+    
+    bool check_object_syntax(object *_o);
+    // 
+    void add_field(asn1::classfield *);
+
+    asn1::classfield *get_classfield(const std::string &name) ;
+    // Order fields
+    void sort_fields();
+    
+    OptionalIterator  opt_begin() { return m_optionals.begin() ; }
+    OptionalIterator  opt_end()   { return m_optionals.end() ; }
+    size_t opt_size( ) const { return m_optionals.size(); }
+
+  protected:
+    OptionalArrayType             m_optionals;
+    std::shared_ptr<state_pool>   m_pool;
+    std::shared_ptr<classdef_nfa> m_nfa;
+    // Should own a list of tokens
+};
+
+
+#endif
diff --git a/adt/asn1_node_constructed.cpp b/adt/asn1_node_constructed.cpp
new file mode 100644 (file)
index 0000000..e422c98
--- /dev/null
@@ -0,0 +1,84 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+/**
+ *
+ */    
+constructed::constructed(const constructed &c)
+  : typenode(c)
+{
+
+} 
+
+asn1::constructed *
+constructed::clone()
+{
+  asn1::constructed *nc = new constructed(*this);
+  std::cerr<<"constructed::clone "<<name()<<std::endl;
+  return nc;
+}
+
+
+bool 
+constructed::equals(const node &_nn) const
+{
+  const  asn1::constructed &_n = dynamic_cast<const asn1::constructed &>(_nn);
+  bool eq = (type_id()() == _n.type_id()());
+  if ( ! is_empty() && eq)
+  {
+    const_iterator field_it,nfield_it;
+    for (field_it = begin() ,  nfield_it =_n.begin()
+             ; field_it != end()  &&  nfield_it != end()
+             ; ++field_it, ++nfield_it ) 
+    {
+      asn1::field *f  = dynamic_cast<asn1::field *>(*field_it); 
+      asn1::field *nf = dynamic_cast<asn1::field *>(*nfield_it); 
+         if ( f->get_type() != NULL 
+              &&  nf->get_type() != NULL)
+         {
+             asn1::node *t  = f->get_type();
+             asn1::node *nt = nf->get_type();
+             eq = eq && (*t == *nt) ;
+             if (! eq )
+                 return false; // Don't continue looking 
+         }
+    }
+    if ( (field_it == end() )  &&  (nfield_it == _n.end()) )
+    {
+        return flags() == _n.flags();
+    }
+    return false;
+  } else
+   return ( eq );   
+}
+
+// Lookup for field name in node list 
+asn1::field *
+constructed::get_field(const std::string &name)
+{
+  asn1::node::iterator found = std::find_if( begin()
+                                             , end()
+                                             , asn1::find_node(name));
+  if (found != end() )
+    return dynamic_cast<asn1::field *>(*found);
+
+  return NULL;
+}
+
+}
diff --git a/adt/asn1_node_constructed.h b/adt/asn1_node_constructed.h
new file mode 100644 (file)
index 0000000..7cbf525
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef ASN1_NODE_CONSTRUCTED_H
+#define ASN1_NODE_CONSTRUCTED_H
+
+/**
+ *
+ * Container class. All types that contain elements must
+ * ibherit from this class. Example: 
+ *   bit_string, enumerate,integer
+ *   sequence,set,choice,object,objectclass
+ *   imports,exports,paramters,act_parameters
+ */ 
+class constructed : public typenode
+{
+  public:
+    typedef node::iterator       field_iterator;
+    typedef node::const_iterator const_field_iterator;
+
+    // constructed(const std::string s,type _t) : node(s,_t) { } ;  
+      
+    constructed(const std::string name, type  t = type::INVALID,meta m = meta::TYPE)
+        : typenode(name,t,m) {};
+    
+    constructed(const constructed &c) ;
+
+    constructed *clone() ;
+
+    virtual ~constructed() {};
+
+    virtual bool equals(const node &_n) const ;
+    
+    node::iterator begin() {return m_nodes.begin();}
+    node::const_iterator begin() const {return m_nodes.begin();}
+    
+    node::iterator end() {return m_nodes.end();}
+    node::const_iterator end() const {return m_nodes.end();}
+    
+    size_t size() const {return m_nodes.size();}
+    
+    bool is_empty() const { return m_nodes.begin() == m_nodes.end(); };
+    // alternative_constructed_iterator 
+    node::node_list &nodes() { return m_nodes; }
+    // Lookup for field name in node list 
+    asn1::field *get_field(const std::string &name);
+    inline void sort_childs() 
+    {
+      m_nodes.sort(node::op_sort);
+    };
+    
+    void append(node *n)
+    { 
+      if (n) 
+      { 
+        m_nodes.push_back(n); 
+        if (n->get_parent() == NULL ) n->set_parent(this);
+      } else 
+      {
+          std::cerr<<"node::append NULL node is wierd"<<std::endl;
+        }
+    }
+  protected:
+    node::node_list      m_nodes;
+};
+
+
+#endif
diff --git a/adt/asn1_node_exports.h b/adt/asn1_node_exports.h
new file mode 100644 (file)
index 0000000..c66fbb4
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef ASN1_NODE_EXPORTS_H
+#define ASN1_NODE_EXPORTS_H
+
+/**
+ * List items exported by module.
+ */ 
+class exports : public constructed
+{
+  public:
+    
+    exports(const std::string &n = std::string("exports"))   
+     : m_all(false), constructed(n,type::INVALID) { } ;
+
+    ~exports() {} ;
+    
+    typeref *get_item( const std::string &item) ;
+
+    bool all() const { return m_all; } ;
+    void all(bool a) { m_all = a;    } ;
+  protected:
+    bool m_all;
+};
+
+
+#endif
diff --git a/adt/asn1_node_field.cpp b/adt/asn1_node_field.cpp
new file mode 100644 (file)
index 0000000..5cc49ea
--- /dev/null
@@ -0,0 +1,153 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+/**
+ *
+ */ 
+field::field(const field &f)
+  : node(f)
+{
+  std::cerr<<"field::field copy - "<<name()<<" "<<f.name()<< std::endl;        
+  if (&f != this)
+  {
+      asn1::typenode *nt = f.get_type()->clone();
+      nt->identifier(this);
+      type_node(nt);
+#if 0
+      if (nt->type_id()() != asn1::type::ASN1_REFERENCE)
+      {
+        nt->name(name()+"_t");
+      }
+#endif
+  }
+}
+    
+/**
+ *
+ */ 
+field::field(const std::string _s,asn1::node *_type)
+  : node(_s,asn1::type::INVALID)
+{ 
+  type_node(_type);
+  if (_type != NULL)
+    _type->identifier(this);
+};  
+
+typenode *
+field::get_type() const
+{
+  return reinterpret_cast<typenode *>(type_node());
+}
+
+void 
+field::set_type(asn1::typenode *t)
+{
+  type_node(t);
+}
+
+/**
+ *
+ */ 
+field *
+field::clone()
+{
+  return new field(*this);
+}
+
+/**
+ * extension field class
+ */ 
+extension_field::extension_field(const extension_field &ef)
+  : field("...",NULL)
+{
+}
+
+extension_field *
+extension_field::clone()
+{
+  return new extension_field(*this);  
+}
+
+extension_field::extension_field()
+  : field("...",NULL)
+{
+  type_id(asn1::type::ASN1_EXTENSIBLE);
+}
+
+/**
+ *
+ */ 
+classfield::classfield(const std::string &_s,type t) 
+       : node(_s,t,meta::OBJECTFIELD)
+       , m_reference(NULL)
+{
+}
+typenode *
+classfield::get_type() const
+{
+  assert( 0 && "Should not be called");
+  return NULL;
+}
+
+/**
+ * CLASSFIELD FTVSF
+ */ 
+classfield_ftvf::classfield_ftvf( const std::string &n,asn1::typenode *t,type _t)
+       : classfield(n,_t)
+{
+  type_node(t);
+}
+typenode *
+classfield_ftvf::get_type() const
+{
+  return reinterpret_cast<typenode *>(type_node());
+}
+
+classfield_ftvsf::classfield_ftvsf( const std::string &n,asn1::typenode *t,type _t)
+       : classfield(n,_t)
+{
+  type_node(t);
+}
+typenode *
+classfield_ftvsf::get_type() const
+{
+  return reinterpret_cast<typenode *>(type_node());
+}
+/**
+ * CLASSFIELD OSF
+ */ 
+classfield_osf::classfield_osf( const std::string &n,asn1::typeref *t,type _t)
+       : classfield(n,_t)
+{
+  type_node(t);
+}
+typeref *
+classfield_osf::get_typeref() const
+{
+  return reinterpret_cast<typeref *>(type_node());
+}
+
+typenode *
+classfield_osf::get_type() const
+{
+  return reinterpret_cast<typenode *>(type_node());
+}
+
+
+}
diff --git a/adt/asn1_node_field.h b/adt/asn1_node_field.h
new file mode 100644 (file)
index 0000000..6519713
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef ASN1_NODE_FIELD_H
+#define ASN1_NODE_FIELD_H
+
+/**
+ * This class represents the componentType in ASN1 definition
+ *   -> It's most lickely that "components of" will also be handled
+ *      by this class.
+ *   -> SEQUENCE AND SET contained elements are fields
+ */ 
+class field : public node
+{
+    field(const field &f);
+  public:
+    field *clone();
+
+    field(const std::string _s,asn1::node *_type) ;
+    ~field() {};
+
+    typenode *get_type() const;
+    void set_type(asn1::typenode *t);
+    // a field in set or sequence, use same type for choice as well  
+  protected:  
+};
+
+/**
+ * @brief represents the ... in ASN1 specification
+ *  still missing the possible exception value.
+ */ 
+class extension_field : public field
+{
+  protected:
+    extension_field(const extension_field &ef);
+  public:
+    extension_field *clone();
+    extension_field();
+  protected:
+    // Exception should be added here
+};
+
+
+/**
+ *
+ * It would have been good to have function like get 
+ *   components this would return the list of components
+ */ 
+class components_of : public field
+{
+  public:
+    components_of(asn1::node *_typeref)
+      : field("components_of",_typeref)
+    {
+      type_node(_typeref);
+      _typeref->identifier(this);
+      type_id(asn1::type::ASN1_COMPONENTS_OF);
+    }
+    asn1::typeref *get_typeref() 
+    {
+      return dynamic_cast<asn1::typeref *>(type_node()); 
+    }
+  protected:  
+};
+
+/**
+ * Classfield classes
+ */ 
+/**
+ *
+ */ 
+class classfield : public node
+{
+  public:
+    
+    classfield(const std::string &_s,type t); 
+      
+    ~classfield() {};
+
+    // a field in set or sequence 
+    // 2017/05/17 does not work yet !!!  15 errors in hpp
+    inline  reference *get_reference() const { return m_reference;};
+    inline  void set_reference(reference *r) {m_reference =r;};
+    virtual typenode *get_type() const;
+  protected:  
+    asn1::reference    *m_reference;
+};
+
+
+#define ASN1_CLASSFIELD_GEN(cls,parent,tp) \
+    class cls : public parent \
+    {\
+      public:\
+       cls(const std::string &s) : parent( s,tp) {} ; \
+       ~cls() {}; \
+    
+
+#define ASN1_CLASSFIELD_ADD_classfield_tf ;       
+#define ASN1_CLASSFIELD_ADD_classfield_ftvf  \
+  classfield_ftvf( const std::string &n      \
+                 , asn1::typenode *t         \
+                 , type _t = asn1::type::ASN1_CLASSFIELD_FTVF) ; \
+    typenode *get_type() const;
+#define ASN1_CLASSFIELD_ADD_classfield_vtvf ;   
+#define ASN1_CLASSFIELD_ADD_classfield_ftvsf  \
+  classfield_ftvsf( const std::string &n      \
+                 , asn1::typenode *t         \
+                 , type _t = asn1::type::ASN1_CLASSFIELD_FTVSF) ; \
+    typenode *get_type() const;
+#define ASN1_CLASSFIELD_ADD_classfield_vtvsf ; 
+#define ASN1_CLASSFIELD_ADD_classfield_of ;       
+#define ASN1_CLASSFIELD_ADD_classfield_osf     \
+  classfield_osf( const std::string &n         \
+                 , asn1::typeref *t            \
+                 , type _t = asn1::type::ASN1_CLASSFIELD_OSF) ; \
+    typeref *get_typeref() const; \
+    typenode *get_type() const;
+
+#define ASN1_CLASSFIELD_TYPE(cls,parent,tp) \
+          ASN1_CLASSFIELD_GEN(cls,parent,asn1::type::ASN1_##tp) ASN1_CLASSFIELD_ADD_##cls };
+
+#endif
diff --git a/adt/asn1_node_imports.cpp b/adt/asn1_node_imports.cpp
new file mode 100644 (file)
index 0000000..809681f
--- /dev/null
@@ -0,0 +1,59 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+bool 
+import_list::get_item(const std::string &type_name,import *&imp,typeref *&ref)
+{
+  bool ret = false;
+  
+  asn1::node::iterator it = begin();
+//  GEN_LOG_DEBUG("lookup for type %s\n",type.c_str());
+  for (; it != end() ;it++)
+  {
+    asn1::import *import = dynamic_cast<asn1::import *>(*it);
+
+    if (asn1::typeref *_ref = import->get_item(type_name)) 
+    {
+
+//      GEN_LOG_DEBUG("found %s in %s\n",type_name.c_str(),import->identifier()->name().c_str());
+      imp = import;
+      ref = _ref;
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+}
+
+asn1::typeref *
+import::get_item(const std::string &item)
+{
+  
+  asn1::node::iterator found = std::find_if( begin()
+                                             , end()
+                                             , asn1::find_node(item));
+  if (found != end() )
+    return (*found)->as_typeref();
+  return NULL;
+}
+
+}
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/adt/asn1_node_imports.h b/adt/asn1_node_imports.h
new file mode 100644 (file)
index 0000000..1eb7813
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef ASN1_NODE_IMPORTS_H
+#define ASN1_NODE_IMPORTS_H
+
+class import;
+/**
+ * import_list class contains a list
+ *  of import. 
+ *
+ */
+class import_list : public constructed
+{
+  public:
+    
+    import_list()
+      : constructed("IMPORTS",type::INVALID) {};  
+    ~import_list() {};
+
+    /**
+     * @brief find type_name in import_list of current module.
+     *  if found return true. ref and imp will be initialized
+     *  if not found ref and imp are unchanged.
+     */
+    bool get_item(const std::string &type_name,import *&imp,typeref *&ref);
+    // alternative_imports_iterator 
+  protected:  
+};
+
+/**
+ * import class contains the elements imported.
+ *
+ */ 
+class import :public constructed
+{
+  public:
+    import(const std::string &n)
+     : constructed(n,type::INVALID) { } ;
+    ~import() { };
+    /**
+     * lookup for item in this import
+     */
+    typeref *get_item( const std::string &item) ;
+};
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */ 
+#endif
diff --git a/adt/asn1_node_object.cpp b/adt/asn1_node_object.cpp
new file mode 100644 (file)
index 0000000..11f8000
--- /dev/null
@@ -0,0 +1,66 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+/**
+ *
+ */ 
+object::object() 
+  : constructed("OBJECT",type::INVALID)
+    , m_classdef(NULL)
+{
+} 
+
+/**
+ */ 
+object::~object()
+{
+}
+
+void 
+object::parsed_field(const std::string &fname,asn1::node *t)
+{
+  m_fields[fname] = t;
+}
+
+void object::update_field(const std::string &fname,asn1::node *t) 
+{
+  m_fields[fname] = t;
+}
+
+// defined fields 
+asn1::node *
+object::get_field(const std::string &fname)
+{
+  iterator it = m_fields.find(fname);
+  if (it != m_fields.end())
+  {
+     return it->second;
+  } else
+  {
+    return NULL;
+  } 
+}
+asn1::objectset *
+object::get_objectset(const std::string &fname)
+{
+  return dynamic_cast<asn1::objectset *>(get_field(fname));
+}
+
+}
diff --git a/adt/asn1_node_object.h b/adt/asn1_node_object.h
new file mode 100644 (file)
index 0000000..e1f8eae
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef ASN1_NODE_OBJECT_H
+#define ASN1_NODE_OBJECT_H
+
+class classdef;
+class valuetype;
+/**
+ * object that containes  
+ */ 
+class object : public constructed
+{
+    typedef std::map<std::string,asn1::node * > fieldmap_type;
+    typedef fieldmap_type::iterator             iterator; 
+    typedef fieldmap_type::const_iterator       const_iterator; 
+  public:
+    
+    object()  ;  
+    ~object() ;
+
+    void parsed_field(const std::string &fname,asn1::node *t);
+    // defined fields 
+    asn1::node      *get_field(const std::string &fname);
+    asn1::valuetype *get_ftvf(const std::string &fname)
+    { return dynamic_cast<asn1::valuetype *>(get_field(fname)); }
+    asn1::objectset *get_objectset(const std::string &fname); 
+   
+    void     update_field(const std::string &fname,asn1::node *t); 
+    // Once parsed, keep a pointer to the classdef. We will need
+    // it for each processing This avoids calls to resolver
+    inline classdef *get_classdef() const       { return m_classdef; } 
+    inline void      set_classdef(classdef *cd) { m_classdef = cd;   } 
+  protected:
+    classdef      *m_classdef;
+    fieldmap_type  m_fields; 
+};
+
+
+#endif
diff --git a/adt/asn1_node_parameters.cpp b/adt/asn1_node_parameters.cpp
new file mode 100644 (file)
index 0000000..2c1cbc3
--- /dev/null
@@ -0,0 +1,133 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+parameters::parameters(const parameters &p)
+  : constructed(p)
+{
+  if (this != &p)
+  {
+    // duplicate elements in vector
+    for ( asn1::node::const_iterator it = p.begin()
+        ; it != p.end()
+        ;  ++it)
+    {
+      asn1::parameter *param = dynamic_cast<asn1::parameter *>(*it);
+      asn1::parameter *nn = param->clone();
+      nn->set_parent(this); 
+      if (nn->type_node())
+        nn->type_node()->set_parent(this);     
+      append(nn);       
+    }
+    identifier(p.identifier());
+  }
+}
+
+parameters*
+parameters::clone()
+{
+  return new parameters(*this);
+}
+
+bool 
+parameters::have_reference(const std::string &name,node::iterator &it)
+{
+  it = std::find_if(begin(),end(),find_node(name));
+  return it != end();
+}
+
+void
+parameters::add_parameter(parameter *p)
+{
+  append(p);  
+}
+
+asn1::parameter *
+parameters::operator [](int l)
+{
+  asn1::node *result = *(begin());
+  int         i      = 0; 
+  for (asn1::node::const_iterator it = begin();
+       (it !=end() ) && (i != l + 1)
+     ; ++it,++i)
+  {
+      result  = *it;
+  }  
+  return dynamic_cast<parameter *>(result);
+}
+
+
+/**
+ *
+ */ 
+
+act_parameters::act_parameters(const act_parameters &p)
+  : constructed(p)
+{
+  if (this != &p)
+  {
+    // duplicate elements in vector
+    for ( asn1::node::const_iterator it = p.begin()
+        ; it != p.end()
+        ;  ++it)
+    {
+      asn1::node *nn = (*it)->clone();
+      nn->set_parent(this); 
+      if (nn->type_node())
+        nn->type_node()->set_parent(this);     
+      append(nn);       
+    }
+    identifier(p.identifier());
+  }
+}
+
+act_parameters*
+act_parameters::clone()
+{
+  return new act_parameters(*this);
+}
+
+asn1::node *
+act_parameters::operator [](int l)
+{
+  asn1::node *result = *(begin());
+  int         i      = 0; 
+  for (asn1::node::const_iterator it = begin();
+       (it !=end() ) && (i != l + 1)
+     ; ++it,++i)
+  {
+      result  = *it;
+  }  
+  return result;
+}
+
+/*
+ * parameter class implementation
+ */ 
+parameter::parameter(asn1::node *_gov,asn1::typeref *_ref)
+  : node(_ref->name(),_ref->type_id()(),_ref->meta_id())
+  , m_param_ref(_ref)
+  , m_governor(_gov)
+{ 
+  type_node(_gov);
+  //set_reference(_ref->get_reference());
+  // To stay compatible with the existing code     
+}
+
+
+}
diff --git a/adt/asn1_node_parameters.h b/adt/asn1_node_parameters.h
new file mode 100644 (file)
index 0000000..df75d8d
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef ASN1_NODE_PARAMETERS_H
+#define ASN1_NODE_PARAMETERS_H
+
+class typeref ;
+class parameter;
+/**
+ * Instead of creating nodes in the parser,
+ * It's better to build specialized classes with better
+ * services.
+ *   - parmeters class is a container of parameters
+ *   SHOULD inherit from something like node_container or container 
+ */ 
+class parameters : public constructed
+{
+    parameters(const parameters &p);
+  public:
+    parameters()
+      : constructed("",type::INVALID) {}
+    ~parameters()  {}
+    parameters *clone();
+    // Provide some function to find reference according to name
+    // will return the appropriate parameter
+    bool have_reference(const std::string &name,node::iterator &it) ;
+
+    void add_parameter(asn1::parameter *n);
+    
+    asn1::parameter *operator [](int l);
+  protected:  
+};
+
+/**
+ * Instead of creating nodes in the parser,
+ * It's better to build specialized classes with better
+ * services.
+ *   this class contains the actual parameters of a type.
+ *   not to mix with parameters.
+ *     typeref {parameters} ::= SEQ {
+ *        toto Toto {act_parameters}
+ *     }
+ */ 
+class act_parameters : public constructed
+{
+    act_parameters(const act_parameters &ap);  
+  public:
+    act_parameters()
+      : constructed("",type::INVALID) {}
+    ~act_parameters()  {}
+    
+    act_parameters *clone();
+    // Provide some function to find reference according to name
+    // will return the appropriate parameter
+    bool have_reference(const std::string &name,node::iterator &it)
+    {
+      it = std::find_if(begin(),end(),find_node(name));
+      return it != end();
+    } 
+
+    void add_parameter(asn1::node *n)
+    {
+      append(n);
+    }
+
+    asn1::node *operator [](int l);
+  protected:
+};
+
+
+/**
+ * A parameter is contained in parameters
+ *  a parameter is either a dummyReference -> reference
+ *  or governor : dummyReference 
+ *   governor
+ *   reference  
+ *  a parameter can be a typeref, a value or valueSet or even ObjectSet   
+ */ 
+class parameter : public node
+{
+    parameter(const parameter &p)
+      : node(p) , m_param_ref(p.m_param_ref),m_governor(p.m_governor)
+    { 
+    }
+  public:
+    parameter(asn1::node *_gov,asn1::typeref *_ref) ;
+    
+    ~parameter()  {};
+
+    parameter *clone() { return new parameter(*this); };
+
+    asn1::node *get_governor() const { return m_governor; } ;
+
+    asn1::typeref * get_typeref() const { return m_param_ref; }
+  protected:
+    // Shall own two nodes.
+    asn1::typeref    *m_param_ref;
+    // governor and reference.
+    asn1::node       *m_governor;
+};
+
+/*
+ * vim:et:sw=2
+ */ 
+#endif
diff --git a/adt/asn1_node_primitive.cpp b/adt/asn1_node_primitive.cpp
new file mode 100644 (file)
index 0000000..1d83320
--- /dev/null
@@ -0,0 +1,218 @@
+#include <iostream>
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1 
+{
+#undef DEBUG
+
+
+/*********************************************
+ * integer type specific methods for generator
+ */
+bool integer::is_unsigned() const
+{
+  long min,max;
+  if (get_range(min,max) && (min >= 0))
+  {
+      return true;
+  }
+  return false;
+}
+
+/**
+ * @brief asn1 integers most often have range
+ * constraints.
+ * @return false if no constraint or no real MAX
+ *
+ */
+bool integer::get_range(long &_min,long &_max) const
+{
+  if (has_constraints())
+  {
+    asn1::constraint_range *cr =( *constraint_begin())->as_constraint_range() ;
+    if (cr)
+    {
+       return cr->get_min_max(_min,_max);
+    } else
+    {
+      //GEN_LOG_ERROR("integer::%s not a range constraint",__FUNCTION__);
+      std::cerr<<"integer::"<<__FUNCTION__<<" not a range constraint"<<std::endl;
+    }
+  }
+  return false;
+}
+
+
+/**
+ * This is only valid for OID where we use 7 bits for each octet.
+ * OUTPUT:
+ *    v will contain the result. A 7 bit encoded array
+ */
+void object_identifier::encode_integer( long value
+                                      , arcsType &v)
+{
+  long integer = value;
+  long intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer %ld %lx",value,value);
+#endif
+  while ( (((integer & mask) == 0) || ((integer & mask) == mask)) 
+          && (intsize > 1)) {
+      intsize--;
+      integer <<=8;
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer step 1  %lx",integer);
+#endif
+  }
+  mask = (0x7f << ((intsize-1)*7));
+  long decal = (intsize -1)*7;
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer step 1  intsize=%ld mask=0x%lx decal=%ld",intsize,mask,decal);
+#endif
+  while ((value & mask  ) != 0) 
+  {
+      long treat = ((value & mask)>>decal);
+      v.push_back (( treat   & 0x7F) |0x80 );
+#ifdef DEBUG
+      std::cout<<"\tpushed :";
+      std::cout<<std::hex<<(int)v.back()<<" integer was:"<<value;
+      std::cout<<" Mask=0x"<<mask<<" treat="<<treat;
+      std::cout<<std::dec<<std::endl;
+#endif
+      value<<=7;
+  }
+  v.back() = v.back() & 0x7F;
+}
+
+
+
+void
+object_identifier::oid_value(long *pos,arcsType *v)
+{
+  int first2 = 0;
+#ifdef DEBUG
+  GEN_LOG_DEBUG( "object_identifier::oid_value type_name=%s pos=%d v.size=%ld"
+               , name().c_str(),*pos,v->size());
+#endif 
+  if (type_id()() != asn1::type::ASN1_OBJECT_IDENTIFIER)
+  {
+    std::cerr<<__FUNCTION__<<" BAD TYPE SHOULD be OBJECT IDENTIFIER\n";
+    assert(0);
+  }
+  for (asn1::node::iterator lit = begin(); lit != end() ; lit++)
+  {
+//#ifdef DEBUG
+#if 0
+    std::cout<<"object_identifier::"<<__FUNCTION__<<" "<<(*lit)->name()<<" pos="<<*pos;
+    std::cout<<" v.size="<<v->size()<<std::endl;
+#endif
+    if ((*lit)->type_id() == asn1::type::ASN1_INTEGER)
+    {
+      asn1::valuetype *vt = (*lit)->as_value_type();
+      long long l = vt->value_long();
+      if (*pos == 0) {
+            first2 = 40 * vt->value_long();
+      } else if (*pos == 1){
+            first2 = first2 + vt->value_long();
+            v->push_back(first2);
+      } else
+        encode_integer(l,*v);
+      (*pos)++;
+    } else
+    {
+      asn1::node *id = from_module()->lookup((*lit));
+      if (id )
+      {
+        if (asn1::object_identifier *roid = id->type_node()
+                                             ->as_object_identifier())
+          roid->oid_value(pos,v);
+      } else
+      {
+         // Probaly I have value
+         asn1::valuetype *vt = (*lit)->as_value_type();
+         if (*pos == 0 && vt) {
+            first2 = 40 * vt->value_long();
+         } else if (*pos == 1 && vt) {
+            first2 = first2 + vt->value_long();
+            v->push_back(first2);
+         } else if (vt) {
+           encode_integer(vt->value_long(),*v);
+         } else {
+           std::cerr<<"object_identifier::oid_value vt==NULL";
+           std::cerr<<" tyeid="<<(*lit)->type_id()();
+           std::cerr<<" cpp_name="<<(*lit)->cpp_name()<<std::endl;
+           assert(0);
+         }
+           (*pos)++;
+
+      }
+    }
+
+  }
+#if 0
+  std::cout<<"object_identifier::"<<__FUNCTION__<<" end "<<name()<<" pos="<<*pos;
+  std::cout<<" v.size="<<v->size()<<std::endl;
+#endif 
+}
+
+void object_identifier::arcs(arcsType &v)
+{
+  long pos = 0;
+  oid_value(&pos,&v);
+}
+
+void object_identifier::print_strhex( std::ostream &os,const arcsType &v)
+{
+  os<<"\"";
+  for (arcsConstIterator it = v.begin(); it!=v.end() ; it++)
+  {
+    os<<"\\x"<<std::hex<<(int)(*it);
+  }
+  os<<"\"";
+  os<<std::dec;
+}
+
+void object_identifier::print_strhex( std::ostream &os)
+{
+  arcsType v;
+  long pos = 0;
+  oid_value(&pos,&v);
+  //
+  print_strhex(os,v);
+}
+
+long object_identifier::hash()
+{
+  arcsType v;
+  long size = 0;
+  oid_value(&size,&v);
+  size = 0;  
+  for (arcsIterator it = v.begin()
+          ; it!=v.end() 
+          ; it++)
+  {
+    size += (*it);
+  }
+  return size;
+}
+
+
+};
+/**
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/adt/asn1_node_primitive.h b/adt/asn1_node_primitive.h
new file mode 100644 (file)
index 0000000..6a15468
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef ASN1_NODE_PRIMITIVE_H
+#define ASN1_NODE_PRIMITIVE_H
+
+
+class primitive : public typenode
+{
+  public:
+    
+    primitive(const std::string s, type _t) 
+      : typenode(s,_t,meta::TYPE) , m_primitive_tag(m_tag.m_value)  
+    { } ;
+
+    primitive(const primitive &p)
+      : m_primitive_tag(p.m_primitive_tag), typenode(p)  {}
+    virtual ~primitive() {};
+
+    primitive *clone() { return new primitive(*this);}
+    int primitive_tag() const 
+    { return m_primitive_tag; }
+    virtual bool equals(const node&_n) const
+    {
+       return ( type_id()() == _n.type_id()() );   
+    }
+    // alternative_primitive_iterator 
+  protected:
+    int m_primitive_tag;
+};
+#ifdef NULL
+#ifndef _MSC_VER
+#pragma warn "NULL defined" 
+#endif
+#endif
+
+#define ASN1_PRIMITIVE_GEN(cls,parent,stp,tp) \
+    class cls : public parent \
+    {\
+      public:\
+       cls() : parent( stp,tp) {} ; \
+       cls(const cls &c) : parent( c ) {} ; \
+       cls *clone() { return new cls(*this);}          \
+       ~cls() {};
+
+
+#define ASN1_PRIMITIVE_ADD_any ;
+#define ASN1_PRIMITIVE_ADD_boolean ;
+#define ASN1_PRIMITIVE_ADD_integer                       \
+      bool is_unsigned() const;                          \
+      bool get_range(long &_min,long &_max) const;       \
+
+#define ASN1_PRIMITIVE_ADD_bit_string ;
+#define ASN1_PRIMITIVE_ADD_octet_string ;
+#define ASN1_PRIMITIVE_ADD_null ;
+#define ASN1_PRIMITIVE_ADD_object_identifier                   \
+  int primitive_tag() const { return m_primitive_tag; } ;      \
+        typedef std::vector<unsigned char>  arcsType;          \
+        typedef arcsType::iterator          arcsIterator;      \
+        typedef arcsType::const_iterator    arcsConstIterator; \
+        void    arcs(arcsType &v ); \
+        long    hash( ); \
+        void    encode_integer( long value , arcsType &v); \
+        void    print_strhex( std::ostream &os); \
+        void    print_strhex( std::ostream &os,const arcsType &v); \
+     protected: \
+        void oid_value(long *pos,arcsType *v);\
+        int m_primitive_tag;
+#define ASN1_PRIMITIVE_ADD_object_descriptor ;
+#define ASN1_PRIMITIVE_ADD_real ;
+#define ASN1_PRIMITIVE_ADD_enumerated ;
+#define ASN1_PRIMITIVE_ADD_relative_oid ;
+#define ASN1_PRIMITIVE_ADD_external ;
+#define ASN1_PRIMITIVE_ADD_embedded_pdv ;
+#define ASN1_PRIMITIVE_ADD_character_string ;
+#define ASN1_PRIMITIVE_ADD_utctime ;
+#define ASN1_PRIMITIVE_ADD_generalizedtime ;
+
+
+#define ASN1_PRIMITIVE_TYPE(cls,parent,tp) \
+          ASN1_PRIMITIVE_GEN(cls,parent,#tp,asn1::type::ASN1_##tp) ASN1_PRIMITIVE_ADD_##cls };
+
+#define ASN1_STRING_TYPE(cls,parent,tp) \
+    class cls : public parent \
+    {\
+      public:\
+       cls() : parent( #tp,asn1::type::ASN1_STRING_##tp) {} ; \
+       cls(const cls &c) : parent( c ) {} ;                   \
+       cls *clone() { return new cls(*this); }                \
+       ~cls() {}; \
+    };
+
+#include "adt/asn1_type.inc"
+
+class extensible : public node
+{
+  public:
+    extensible()
+      : node("...",type::ASN1_EXTENSIBLE) {}
+};
+
+class exportvar : public node
+{
+  public:
+    exportvar()
+      : node("...",type::ASN1_EXPORTVAR) {}
+};
+
+#endif
diff --git a/adt/asn1_node_selection.h b/adt/asn1_node_selection.h
new file mode 100644 (file)
index 0000000..fc8ccb3
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef ASN1_NODE_SELECTION_H
+#define ASN1_NODE_SELECTION_H
+
+/**
+ * selection type object is a typeref where get_reference
+ * will return  NULL !!!!!
+ *
+ * -> Solver might have a problem with this.
+ */ 
+class selection : public typeref 
+{
+  protected:
+    selection(const selection &s)
+      : typeref(s)
+    {};
+  public:
+    
+    selection(const std::string &s,asn1::node *_n = NULL) 
+        : typeref(s,NULL,meta::TYPEREF)
+    {
+      type_id(asn1::type::ASN1_SELECTION);
+      meta_id(asn1::meta::TYPEREF);
+      type_node(_n);
+    }; 
+
+    selection *clone() { return new selection(*this);};
+    ~selection() {};
+    
+  protected:  
+};
+
+
+#endif
diff --git a/adt/asn1_node_sequence.cpp b/adt/asn1_node_sequence.cpp
new file mode 100644 (file)
index 0000000..c46691c
--- /dev/null
@@ -0,0 +1,59 @@
+#include <iostream>
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1 
+{
+
+sequence::sequence() :  constructed("SEQUENCE",type::ASN1_SEQUENCE)
+{
+} 
+
+sequence::sequence(const sequence &s) 
+    :  constructed("SEQUENCE",type::ASN1_SEQUENCE)
+{
+  std::cerr<<"sequence::sequence copy "<<s.size()<<std::endl;
+  if (this != &s)
+  {
+    // duplicate elements in vector
+    for ( asn1::node::const_iterator it = s.begin()
+        ; it != s.end()
+        ;  ++it)
+    {
+      asn1::field *f = dynamic_cast<asn1::field *>(*it);
+      asn1::field *nn = f->clone();
+      nn->set_parent(this);
+      nn->get_type()->set_parent(this);     
+      nn->get_type()->identifier(nn);     
+      add_component(nn);
+    }
+    set_parent(s.get_parent());
+    //identifier(s.identifier());
+  }
+} 
+
+void
+sequence::add_component(asn1::node *c)
+{
+  append(c); 
+  if (c && c->flags().is_optional())
+  {
+    m_optionals.push_back(c); 
+  }
+}
+
+}
+
diff --git a/adt/asn1_node_sequence.h b/adt/asn1_node_sequence.h
new file mode 100644 (file)
index 0000000..533c59f
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef ASN1_NODE_SEQUENCE_H
+#define ASN1_NODE_SEQUENCE_H
+
+/**
+ * adt sequence type. contains the fields in the sequence.
+ * add methodes to collect optional fields. This will help
+ * in code generation.
+ * component items should also be added through an API from
+ * this class. The goal is to remove  container from node class.
+ */ 
+class sequence : public constructed
+{
+  protected: 
+    sequence(const sequence &s);   
+  public:
+    typedef std::vector<asn1::node *>   OptionalArrayType;
+    typedef OptionalArrayType::iterator OptionalIterator;
+    sequence();  
+    ~sequence()  {};
+
+    sequence *clone() {return new sequence(*this); }
+    
+    OptionalIterator  opt_begin() { return m_optionals.begin() ; }
+    OptionalIterator  opt_end()   { return m_optionals.end() ; }
+    size_t opt_size( ) const { return m_optionals.size(); }
+
+    /**
+     * Add a component. the type should be more specific
+     */ 
+    void add_component(asn1::node *);
+  protected:
+    std::vector<asn1::node *> m_optionals;
+};
+
+
+#endif
diff --git a/adt/asn1_node_sequence_of.h b/adt/asn1_node_sequence_of.h
new file mode 100644 (file)
index 0000000..9bcc9a1
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef ASN1_NODE_SEQUENCE_OF_H
+#define ASN1_NODE_SEQUENCE_OF_H
+
+
+class sequence_of : public typenode
+{
+  public:
+    
+    sequence_of(asn1::node *_type) 
+      : typenode("SEQUENCE_OF",type::ASN1_SEQUENCE_OF) 
+    {
+      type_node(_type);
+      _type->set_parent(this);  
+    };  
+    ~sequence_of() {};
+
+  protected:  
+};
+
+
+#endif
diff --git a/adt/asn1_node_set.h b/adt/asn1_node_set.h
new file mode 100644 (file)
index 0000000..a976b30
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef ASN1_NODE_SET_H
+#define ASN1_NODE_SET_H
+
+
+class set : public constructed
+{
+  public:
+    
+    set() : constructed("SET",type::ASN1_SET) {};  
+    ~set() {};
+
+    // alternative_set_iterator 
+  protected:  
+};
+
+
+#endif
diff --git a/adt/asn1_node_set_of.h b/adt/asn1_node_set_of.h
new file mode 100644 (file)
index 0000000..a157beb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef ASN1_NODE_SET_OF_H
+#define ASN1_NODE_SET_OF_H
+
+
+class set_of : public typenode
+{
+  public:
+    
+    set_of(asn1::node *_type) 
+     : typenode("SET_OF",type::ASN1_SET_OF) { type_node(_type); };  
+    ~set_of() {};
+
+    // alternative_set_iterator 
+  protected:  
+};
+
+
+#endif
diff --git a/adt/asn1_node_typenode.cpp b/adt/asn1_node_typenode.cpp
new file mode 100644 (file)
index 0000000..d7a17da
--- /dev/null
@@ -0,0 +1,77 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_reference.h"
+#include "asn1_module.h"
+#include "asn1_node_assignment.h"
+#include "asn1_node_typenode.h"
+
+
+namespace asn1 {
+
+
+
+// copy constructor  
+typenode::typenode(const typenode &t)
+  : node (t)
+{
+}
+typenode::typenode(const std::string name
+          , type _t 
+          , meta _m )
+  : node(name,_t,_m)
+{
+}
+
+typenode *
+typenode::clone()
+{
+  return new typenode(*this);
+}
+
+// Return the assignment the type is part of
+asn1::assignment * 
+typenode::get_assignment( ) const
+{
+  assert(0 && "typenode::get_assignment TODO");
+  return NULL;
+}
+
+// Return the field the is type is part of
+asn1::field      * 
+typenode::get_field( ) const
+{
+  assert(0 && "typenode::get_field TODO");
+  return NULL;
+}
+
+asn1::typenode   *
+typenode::get_eltype( ) const
+{
+  //assert(0 && "typenode::get_eltype TODO");
+  return dynamic_cast<asn1::typenode *>(type_node());
+}
+
+// Need to solve mess with objectset / valueset before
+// Constraints on a node type 
+bool typenode::has_constraints() const
+{
+  return m_constraints.begin() != m_constraints.end();
+}
+
+
+}
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/adt/asn1_node_typenode.h b/adt/asn1_node_typenode.h
new file mode 100644 (file)
index 0000000..9116a99
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef _TYPENODE_H__
+#define _TYPENODE_H__
+
+class field;
+class assignment;
+class resolver;
+/**
+ * Base class for types. It is own by an assignment or field
+ * in constructed type.
+ * This class should be the parent class for all types (primitive
+ * and contructed).
+ * The idea is to move some features from node to type node.
+ *  A type does not have a name.
+ */ 
+class typenode : public node
+{
+  public:
+    typenode(const std::string s, type _t) 
+      : node(s,_t,meta::TYPE)
+    { } ;
+
+    typenode(const std::string name
+            , type _t 
+            , meta _m );
+    // copy constructor  
+    typenode(const typenode &t);
+
+    typenode *clone();
+    // Return the assignment the type is part of
+    asn1::assignment * get_assignment( ) const;
+    // Return the field the is type is part of
+    asn1::field      * get_field( ) const;
+    // For set_of and sequence_of ...
+    asn1::typenode   * get_eltype( ) const;
+
+    inline void constraint(asn1::constraint *c)
+    { m_constraints.append(c); };
+    // Constraints on a node type 
+    bool has_constraints() const;
+    // iterators
+    inline asn1::constraint::iterator constraint_begin()
+    { return m_constraints.begin(); };
+      
+    //
+    inline asn1::constraint::const_iterator constraint_begin() const
+    { return m_constraints.begin(); };
+
+    //
+    inline asn1::constraint::iterator constraint_end()
+    { return m_constraints.end();};
+      
+    //
+    inline asn1::constraint::const_iterator constraint_end() const
+    { return m_constraints.end();};
+    /**
+     * For recursive typeref resolution
+     */
+    virtual void resolve(asn1::resolver &r) {};
+  protected:
+};
+
+#endif
diff --git a/adt/asn1_node_typeref.cpp b/adt/asn1_node_typeref.cpp
new file mode 100644 (file)
index 0000000..647eebd
--- /dev/null
@@ -0,0 +1,301 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_resolver.h"
+
+
+namespace asn1
+{
+
+/**
+ * May ben  
+ */ 
+typeref::typeref(const typeref &r)     
+  : typenode(r)
+  , m_real_type(r.m_real_type)
+  , m_reference(r.m_reference)
+{
+  //set_reference(r.get_reference());
+  if (r.parameters())
+  {
+    std::cerr<<"typeref::typeref copy "<<r.name()<<std::endl;    
+    parameters(r.parameters()->clone());
+  }
+}
+
+typeref * 
+typeref::clone()
+{
+  return new typeref(*this);   
+}
+
+bool typeref::is_complex() const
+{
+  return (get_reference()->size() >1);
+}
+
+bool typeref::is_simple() const
+{
+  return dynamic_cast<simple_reference *>(get_reference()) != NULL;
+}
+//
+bool typeref::is_external() const
+{
+  return dynamic_cast<external_type_reference *>(get_reference()) != NULL;
+}
+//
+bool typeref::is_objectclass() const
+{ 
+  return dynamic_cast<objectclass_reference *>(get_reference()) != NULL;
+}
+
+bool typeref::is_type_identifier() const
+{
+  try
+  {
+    objectclass_reference &_ref = get_objectclass();
+    return ! std::string("TYPE-IDENTIFIER::&Type").compare(_ref.name());
+  } catch (std::exception &e)
+  {
+    return false;
+  }  
+}
+
+objectclass_reference &
+typeref::get_objectclass() const 
+{ 
+  return dynamic_cast<objectclass_reference &>(*get_reference());
+}
+
+simple_reference &
+typeref::get_simple() const 
+{ 
+return dynamic_cast<simple_reference &>(*get_reference());
+}
+
+/**
+ *
+ */ 
+bool 
+typeref::is_imported(std::string &m) const
+{
+  asn1::module *_module = from_module();
+  bool ret = false;
+  asn1::import_list *imports = _module->imports();
+  if (imports == NULL)
+  {
+#if 0
+    GEN_LOG_ERROR("%s type %s not in imports no imports\n"
+                 , __FUNCTION__
+                 , name().c_str());
+#endif
+    return ret;
+  }
+  asn1::node::iterator it = imports->begin();
+#if 0
+  GEN_LOG_DEBUG("%s lookup for type %s\n"
+               , __FUNCTION__
+               , name().c_str());
+#endif
+  for (; it != imports->end();it++)
+  {
+    asn1::import *import = dynamic_cast<asn1::import *>(*it);
+    asn1::node::iterator found = std::find_if( import->begin()
+                                             , import->end()
+                                             , asn1::find_node(name()));
+    if (found != import->end() )
+    {
+#if 0
+      GEN_LOG_DEBUG("%s found %s in %s\n"
+                   , __FUNCTION__
+                   , name().c_str()
+                   , import->identifier()->name().c_str());
+#endif
+      m = import->identifier()->name();
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+
+}
+
+/**
+ *
+ */ 
+bool 
+typeref::equals(const node &_n ) const 
+{ 
+  if (asn1::typeref *tref = const_cast<node &>(_n).as_typeref())
+  {
+  return ! get_reference()->name().compare(tref->get_reference()->name());
+  } else
+    return false;
+};
+
+
+asn1::node::tag_type 
+typeref::otag(asn1::resolver &resolver) const
+{
+  asn1::node *t = m_real_type;
+  if (!t)
+  {
+    std::cerr<<"typeref::"<<__FUNCTION__<<" START ";
+    std::cerr<<"have real type: "<<((t != NULL)?1:0);
+    std::cerr<<" "<<from_module()->name()<<"::"<<name()<<std::endl;
+    assert(0 && "typeref::otag must have m_real_type");
+  }
+  if ( tagged())
+    return  tag();
+  if ( ! t )
+        t = resolver.resolve(*this);
+  while (t && !t->tagged() && t->as_typeref())
+  {
+    if (t->as_typeref() )
+    {
+      asn1::node *nt = t->as_typeref()->get_real_type();
+      if (! nt)
+      {
+        std::cerr<<"typeref::"<<__FUNCTION__<<" should have real type ";
+        std::cerr<<t->from_module()->name()<<"::"<<t->name()<<std::endl;
+        // if (is_complex())
+        nt = resolver.resolve(*t->as_typeref());
+        if (nt)
+        {
+          std::cerr<<__FUNCTION__<<" got "<<nt->from_module()->name();
+          std::cerr<<"::"<<nt->name()<<std::endl;
+        }
+      }
+      t = nt;
+    } else
+      break;
+  }
+#if 0
+  /* Debug traces */
+  std::cerr<<"typeref::"<<__FUNCTION__<<" END LOOP"<<std::endl;
+#endif
+  if ( t && t->tagged())
+    return t->tag();
+
+  if (asn1::choice *c = dynamic_cast<asn1::choice *>(t))
+  {
+    std::cerr<<"typeref::"<<__FUNCTION__<<" "<<name()<<" t is choice"<<std::endl;
+    return c->get_tag(resolver);
+  }
+  /* What does this mean ? */
+  std::cerr<<"typeref::"<<__FUNCTION__<<" ERROR "<<from_module()->name();
+  std::cerr<<"::"<<name()<<" no tag!";
+  std::cerr<<std::endl;
+  if (is_complex())
+  {
+    return t->tag();
+  }
+  assert((t != NULL) && "otag no tag in reference chaine !");
+  if (t->tag().m_value == -1)
+    std::cerr<<"typeref::"<<__FUNCTION__<<" "<<t->name()<<std::endl; 
+  if (t->name().compare("ANY"))
+    assert((t->tag().m_value != -1) && "Tag must have a value");
+  return t->tag();
+}
+
+void 
+typeref::resolve(asn1::resolver &_resolver)
+{
+  asn1::node  *pi     = NULL;
+  asn1::assignment *p = NULL;
+  
+  if ( get_parent() )
+  {
+    if (asn1::module *m = dynamic_cast<asn1::module *>(get_parent()))
+    {
+      //std::cerr<<" typeref="<<name()<<" Parent is module identi="<<identifier()->cpp_name()<<std::endl;
+      p = identifier()->as_assignment();
+    } else
+    {
+      pi  = get_parent()->identifier();
+      p   = pi->as_assignment();
+    }
+  } else {
+    std::cerr<<"typeref::"<<__FUNCTION__<<"pi is NULL not good ";
+    std::cerr<<" parent= NULL";
+    std::cerr<<" typeref="<<name()<<std::endl;
+  }
+  assert(get_parent() != NULL && "Parent is NULL not good");
+  assert(p != NULL && "p is NULL type is ");
+  
+ // std::cerr<<"typeref::"<<__FUNCTION__<<" Typeref nore ref "<<name();
+ // std::cerr<<" parent="<<p->name()<<std::endl;
+  if (p && p->parameters()) 
+  {
+    long pos;
+    m_real_type = p->have_parameter(this,pos);
+  }
+  if (m_real_type == NULL)
+  {
+    //std::cerr<<"typeref::"<<__FUNCTION__<<" call resolve on this "<<name()<<"\n";
+    m_real_type = _resolver.resolve(*this);
+#if 0
+    std::cerr<<"typeref::"<<__FUNCTION__<<" "<<name();
+    std::cerr<<" rt_name "<<m_real_type->cpp_name();
+    std::cerr<<" m_real_type= "<<m_real_type<<"\n";
+#endif
+  }
+#if 0
+  // Leave for debug 02/04/2017
+  std::cerr<<"Before resolve reference "<<name();
+  std::cerr<<" meta="<<meta_id()();
+  std::cerr<<" Is objectclass= "<<is_objectclass()<<std::endl;
+#endif
+  if (m_real_type == NULL)
+  {
+    std::cerr<<"Unable to resolve reference "<<name()<<std::endl;
+    assert(0 && "typeref::resolve should always resolve!!!");
+    return;
+  }
+  assert((m_real_type != NULL) && "typeref::resolve real type not found ");
+  if ( (  m_real_type->is_primitive()
+        || m_real_type->is_constructed()) 
+        && (is_objectclass() && ! is_complex()))
+  {
+    asn1::reference *ref = get_reference();
+    set_reference( new asn1::simple_reference(ref->name()));
+
+    std::cerr<<"typeref::"<<__FUNCTION__<<" Issue with "<<name();
+    std::cerr<<" Fixed"<<std::endl;
+    delete ref;
+  }
+  // If real_type is reference, I should resolve it too !! or not !
+  asn1::typeref *oref = m_real_type->as_typeref();
+  if (oref)
+  {
+    // std::cerr<<"typeref::"<<__FUNCTION__<<" !! recursif call resolve real_type "<<oref->name()<<std::endl;
+    oref->resolve(_resolver);
+  }
+}
+//
+asn1::typenode *
+typeref::get_canonical_typenode() const
+{
+  assert( (m_real_type != NULL) && "typeref::get_canonical_typenode must have m_real_type");
+  if (asn1::typeref *lr = m_real_type->as_typeref() )
+  {
+    while ( lr && lr->get_real_type()->as_typeref())
+         lr = lr->get_real_type()->as_typeref();
+    assert((lr != NULL) && "typeref::get_canonical_typenode should not have NULL for lr");
+    return lr->as_typenode();
+  } else
+    return m_real_type->as_typenode();
+}
+
+}
diff --git a/adt/asn1_node_typeref.h b/adt/asn1_node_typeref.h
new file mode 100644 (file)
index 0000000..532c5ce
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef ASN1_NODE_TYPEREF_H
+#define ASN1_NODE_TYPEREF_H
+
+/**
+ * Helper node that deals with all kind of references.
+ *  value reference, typerefence, objectclass and
+ *  so one. 
+ * This class will be used by resolver to find the 
+ * primary type
+ *
+ */ 
+class resolver;
+class typeref : public typenode 
+{
+  protected:
+    typeref(const typeref &r);         
+  public:
+    
+    typeref(asn1::reference *_ref,meta _m = meta::TYPE) 
+         : typenode("TYPEREF",type::ASN1_REFERENCE,_m) 
+         , m_real_type(NULL)
+         , m_reference(_ref)
+    {
+      set_reference(_ref);
+    };
+
+    typeref(const std::string &name,asn1::reference *_ref,meta _m = meta::TYPE) 
+         : typenode(name,type::ASN1_REFERENCE,_m) 
+         , m_real_type(NULL)
+         , m_reference(_ref)
+    {
+    } ;
+
+    typeref *clone();
+    
+    ~typeref() {};
+    // from node
+    inline  reference *get_reference() const { return m_reference;};
+    inline  void set_reference(reference *r) {m_reference =r;};
+    // get_canonical_typenode() return the primitive asn1::typenode
+    // in case of multiple typereference lists
+    // Str3 ::= [ 1] Str2  Str2 ::= [4] IMPLICIT Str1 Str1 ::= VisibleString
+    // canonical typenode will be VisibleString Typenode
+    asn1::typenode *get_canonical_typenode() const;
+
+    // Yes for references like OPERATION.&Id
+    bool is_complex() const;
+    //
+    bool is_simple() const;
+    //
+    bool is_external() const;
+    //
+    bool is_objectclass() const;
+    
+    bool is_type_identifier() const;
+
+    objectclass_reference &get_objectclass() const ;
+    
+    simple_reference &get_simple() const ;
+    /**
+     * Check if reference is imported. If so
+     * return the module it's imported from.
+     */
+    bool is_imported(std::string &m) const;
+    //
+    virtual bool equals(const node &_n ) const ;
+    // alternative_typeref_iterator 
+
+    // The idea here is to save the real type
+    // and fix objectclass that are pointing
+    // to primitive types. Example H323 TBCD-STRING
+    // Which is a IA5String
+    // 
+    void resolve(asn1::resolver &_resolver);
+    // Return real type. Null if resolve has
+    // not been called.
+    asn1::node *get_real_type() const
+    { return m_real_type; }
+    /// Return outer most tag
+    asn1::node::tag_type otag(asn1::resolver &r) const;
+  protected:
+    asn1::reference    *m_reference;
+    asn1::node *m_real_type;  
+};
+
+
+#endif
diff --git a/adt/asn1_node_valuetype.cpp b/adt/asn1_node_valuetype.cpp
new file mode 100644 (file)
index 0000000..165f332
--- /dev/null
@@ -0,0 +1,97 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_node.h"
+#include "asn1_module.h"
+
+
+namespace asn1
+{
+
+valuetype::valuetype(asn1::value *_val,meta _m ) 
+     : node("VALUE",type::INVALID,_m)
+{
+  value(_val);   
+}
+
+valuetype::valuetype( const std::string &name
+          , asn1::value *_ref
+          , meta _m )
+     : node(name,type::INVALID,_m)
+{
+  value(_ref);   
+}
+
+valuetype::~valuetype() {};
+
+//TODO Macro to debug an work on value_long that needs to be changed
+//#define WVAL
+//
+// Value ...
+void 
+valuetype::value_long(long long l) 
+{
+#ifdef WVAL
+ std::cerr<<"ERR valuetype::value_long called with value_long "<<l<<std::endl;
+#endif
+  type_id(type::ASN1_INTEGER);
+  m_value_long = l;
+}
+
+long long 
+valuetype::value_long() const
+{
+  if (m_value)
+  {
+      return m_value->m_integer;
+  }
+#ifdef WVAL
+//  std::cerr<<"ERROR value_type  called with value_long "<<std::endl;
+#endif
+  return m_value_long;
+}
+
+
+
+asn1::typeref *
+valueset::get_typeref()
+{
+  if (m_constraints.size() >= 1)
+  {
+    if (asn1::celt_type *ct = dynamic_cast<asn1::celt_type *>(*m_constraints.begin()))
+    {
+      if (ct->value())
+        return ct->value()->as_typeref();
+    }
+  }
+  return NULL;
+}
+
+/**
+ * objectset  
+ */ 
+objectset_assignment *
+objectset::get_assignment() const
+{
+  return dynamic_cast<objectset_assignment *>(identifier());
+}
+
+void 
+objectset::set_classref(asn1::typeref *ref)
+{
+  //TODO needs to be removed 
+  type_node(ref);
+  // Final place
+  m_classref = ref;
+}
+
+}
diff --git a/adt/asn1_node_valuetype.h b/adt/asn1_node_valuetype.h
new file mode 100644 (file)
index 0000000..d0ba83e
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef ASN1_NODE_VALUETYPE_H
+#define ASN1_NODE_VALUETYPE_H
+
+class objectset_assignment;
+/**
+ * Helper node that deals with all kind of value.
+ * Possible meta 
+ *  -> VALUE
+ *  -> VALUESET
+ *  -> OBJECTSET 
+ *   details about the value are given in asn1_value structure
+ *     VT_MIN, VT_MAX, VT_TRUE, VT_FALSE 
+ *   if VT is CT_COLON, type should be CHOICE
+ *   if VT is TRUE or FALSE, type should be BOOLEAN
+ *   if VT is MIN,MAX,NUMBER it should be INTEGER
+ *   if VT is string, OCTET_STRING
+ *   this could allow better correlation between type and
+ *   value at the first place      
+ *   if VT REFERENCED, type could be OBJECT, OBJECTSET,VALUESET
+ */ 
+class valuetype : public node 
+{
+  public:
+    
+    valuetype(asn1::value *_val,meta _m = meta::VALUE); 
+    
+    valuetype( const std::string &name
+              , asn1::value *_ref
+              , meta _m = meta::VALUE) ;
+    
+    ~valuetype();
+    //
+    // Value ...
+    void value_long(long long l) ;
+
+    long long value_long() const ;
+  protected:  
+};
+
+/**
+ *
+ */
+class valueset : public typenode
+{
+  public:
+    valueset(asn1::constraint *_val) :
+        typenode("valueset",type::ASN1_VALUESET,meta::VALUE)
+    {
+      type_id(type::ASN1_VALUESET);
+      constraint(_val);
+    }
+    ~valueset() {};
+    /*
+     * Specific for Rose .... 
+     */   
+    asn1::typeref *get_typeref();
+  protected:
+
+};
+
+/**
+ *
+ */
+class objectset : public typenode
+{
+  public:
+    objectset(asn1::constraint *_val) :
+        typenode("objectset",type::ASN1_OBJECTSET,meta::VALUE)
+    {
+      type_id(type::ASN1_VALUESET);
+      constraint(_val);
+    }
+    ~objectset() {};
+
+    objectset_assignment *get_assignment() const;
+
+    void set_classref(asn1::typeref *);
+
+    asn1::typeref *get_classref() const 
+    { return m_classref; }
+  protected:
+    asn1::typeref *m_classref;
+
+};
+
+
+#endif
diff --git a/adt/asn1_recursive_visitor.h b/adt/asn1_recursive_visitor.h
new file mode 100644 (file)
index 0000000..ad562c6
--- /dev/null
@@ -0,0 +1,640 @@
+#ifndef ASN1_RECURSIVE_VISITOR_H__
+#define ASN1_RECURSIVE_VISITOR_H__
+
+namespace asn1
+{
+
+
+//std::cout<<"TRY_TO FAILED calling "<< #f<<std::endl;  
+
+#define TRY_TO(f) do {                                          \
+        if (! getDerived().f ) {                                \
+          return false;                                         \
+        }                                                       \
+  } while(0)
+
+template <typename Derived >
+class recursive_visitor
+{
+  public:
+  Derived &getDerived() {
+        return *static_cast<Derived *>(this);
+  };
+
+    bool traverse_module(asn1::module *);
+    bool traverse_assignment(asn1::node *);
+    // Assignment traversal   
+#define ASSIGNMENT(tp,CLASS,PARENT) bool traverse_assign_##CLASS(CLASS##_assignment *S);
+#include "asn1_meta.inc"
+
+    bool walkup_from_assignment(asn1::node *s)
+    { return getDerived().visit_assignment(s);}
+
+    bool visit_assignment(asn1::node *s) {return true;}
+
+#define ASSIGNMENT(tp,CLASS,PARENT)                       \
+    bool walkup_from_assign_##CLASS(CLASS##_assignment *S) {           \
+        TRY_TO(walkup_from_##PARENT(S));           \
+        TRY_TO(visit_assign_##CLASS(S));                 \
+        return true;                             \
+    }                                            \
+    bool visit_assign_##CLASS(CLASS##_assignment *S) {return true; } 
+
+#include "asn1_meta.inc"
+
+   // Type traversal 
+   bool traverse_type(asn1::node *);
+#if 0
+#define ASN1_TYPE(CLASS,PARENT,ID)             \
+   bool traverse_##CLASS(asn1::node *S);
+#define ASN1_CONSTRUCTED_TYPE(CLASS,PARENT,ID)  \
+   bool traverse_##CLASS(asn1::node *S);
+#define ASN1_PRIMITIVE_TYPE(CLASS,PARENT,ID)  \
+   bool traverse_##CLASS(asn1::node *S);
+#else
+#define ASN1_TYPE(CLASS,PARENT,ID)             \
+   bool traverse_##CLASS(CLASS *S);
+#define ASN1_CONSTRUCTED_TYPE(CLASS,PARENT,ID)  \
+   bool traverse_##CLASS(CLASS *S);
+#define ASN1_PRIMITIVE_TYPE(CLASS,PARENT,ID)  \
+   bool traverse_##CLASS(CLASS *S);
+#endif
+
+#define ASN1_CLASSFIELD_TYPE(CLASS,PARENT,ID)  \
+   bool traverse_##CLASS(CLASS *S);                             \
+   bool traverse_object_##CLASS(CLASS *S,asn1::node *field );   \
+
+   bool traverse_object_field(asn1::classfield *S,asn1::node *field);
+
+
+#include "adt/asn1_type.inc"
+    bool walkup_from_node(asn1::node *s)
+    { return getDerived().visit_node(s);}
+
+    bool visit_node(asn1::node *s) {return true;}
+    //
+    bool walkup_from_typenode(asn1::node *s)
+    { return getDerived().visit_typenode(s);}
+
+    bool visit_typenode(asn1::node *s) {return true;}
+    //
+    bool walkup_from_typeref(asn1::node *s)
+    { return getDerived().visit_typeref(s);}
+
+    bool visit_typeref(asn1::node *s) {return true;}
+    //
+    bool walkup_from_primitive(asn1::node *s)
+    { return getDerived().visit_primitive(s);}
+
+    bool visit_primitive(asn1::node *s) {return true;}
+    //
+    bool walkup_from_constructed(asn1::node *s)
+    { return getDerived().visit_constructed(s);}
+
+    bool visit_constructed(asn1::node *s) {return true;}
+    //
+    bool walkup_from_object_classfield(asn1::classfield *s,asn1::node *f)
+    { return getDerived().visit_object_classfield(s,f);}
+
+    bool visit_object_classfield(asn1::classfield *s,asn1::node *f)
+    {return true;}
+#if 0
+#define ASN1_TYPE(CLASS,PARENT,ID) \
+    bool walkup_from_##CLASS(asn1::node *S) {           \
+        TRY_TO(walkup_from_##PARENT(S));           \
+        TRY_TO(visit_##CLASS(S));                 \
+        return true;                             \
+    }                                            \
+    bool visit_##CLASS(asn1::node *S) {return true; } 
+#else
+#define ASN1_TYPE(CLASS,PARENT,ID) \
+    bool walkup_from_##CLASS(CLASS *S) {           \
+        TRY_TO(walkup_from_##PARENT(S));           \
+        TRY_TO(visit_##CLASS(S));                 \
+        return true;                             \
+    }                                            \
+    bool visit_##CLASS(CLASS *S) {return true; } 
+
+#endif
+#define ASN1_CLASSFIELD_TYPE(CLASS,PARENT,ID)           \
+    bool walkup_from_##CLASS(asn1::node *S) {           \
+        TRY_TO(walkup_from_##PARENT(S));                \
+        TRY_TO(visit_##CLASS(S));                       \
+        return true;                                    \
+    }                                                   \
+    bool visit_##CLASS(asn1::node *S) {return true; }   \
+                                                        \
+    bool walkup_from_object_##CLASS(CLASS *S,asn1::node *f) {        \
+        TRY_TO(walkup_from_##PARENT(S));                              \
+        TRY_TO(visit_object_##CLASS(S,f));                            \
+        return true;                                                  \
+    }                                                                 \
+    bool visit_object_##CLASS(CLASS *S,asn1::node *f) {return true; } 
+
+
+
+#include "adt/asn1_type.inc"
+    // CONSTRAINT traversal   
+    //
+    bool traverse_constraint(constraint *S) ;
+    bool traverse_constraint_element(constraint_element *S) ;
+    bool traverse_constraint_type(constraint_type *S) ;
+    bool traverse_constraint_array(constraint_array *S) ;
+#define ELEMENT_CONSTRAINT(tp,CLASS,PARENT) bool traverse_##CLASS(CLASS *S);
+#include "asn1_constraint.inc"
+    // constraint
+    bool walkup_from_constraint(asn1::constraint *s)
+    { return getDerived().visit_constraint(s);}
+
+    bool visit_constraint(asn1::constraint *s) {return true;}
+    // constraint_array
+    
+    // constraint_element
+    bool walkup_from_constraint_element(asn1::constraint_element *s)
+    { 
+      TRY_TO(walkup_from_constraint(s));
+      return getDerived().visit_constraint_element(s);
+    }
+
+    bool visit_constraint_element(asn1::constraint_element *s) {return true;}
+
+    // constraint_range
+    bool walkup_from_constraint_range(asn1::constraint_range *s)
+    { 
+      TRY_TO(walkup_from_constraint(s));
+      return getDerived().visit_constraint_range(s);
+    }
+
+    bool visit_constraint_range(asn1::constraint_range *s) {return true;}
+
+    // constraint_type
+    bool walkup_from_constraint_type(asn1::constraint_type *s)
+    { 
+      TRY_TO(walkup_from_constraint(s));
+      return getDerived().visit_constraint_type(s);
+    }
+
+    bool visit_constraint_type(asn1::constraint_type *s) {return true;}
+    // constraint_array
+    bool walkup_from_constraint_array(asn1::constraint_array *s)
+    {
+      TRY_TO(walkup_from_constraint(s));
+      return getDerived().visit_constraint_array(s);
+    }
+
+    bool visit_constraint_array(asn1::constraint_array *s) {return true;}
+
+
+
+#define ELEMENT_CONSTRAINT(tp,CLASS,PARENT)                       \
+    bool walkup_from_##CLASS(CLASS *S) {           \
+        TRY_TO(walkup_from_##PARENT(S));           \
+        TRY_TO(visit_##CLASS(S));                 \
+        return true;                             \
+    }                                            \
+    bool visit_##CLASS(CLASS *S) {return true; } 
+
+#include "asn1_constraint.inc"
+
+
+    // Actual_choice
+    bool traverse_alternative_choice(asn1::field *);
+
+    bool walkup_from_alternative_choice(asn1::field *s)
+    { return getDerived().visit_alternative_choice(s);}
+
+    bool visit_alternative_choice(asn1::field *s) {return true;}
+    // Component type
+    bool traverse_component_type(asn1::field *);
+
+    bool walkup_from_component_type(asn1::field *s)
+    { return getDerived().visit_component_type(s);}
+
+    bool visit_component_type(asn1::field *s) {return true;}
+
+  protected:
+    asn1::module::iterator m_module_iterator;
+};
+
+/**
+ * Implementation part
+ */
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_module(asn1::module *S) {
+    if (! S)
+        return true;
+    for ( m_module_iterator = S->begin()
+        ; m_module_iterator != S->end()
+        ; ++m_module_iterator)
+    {
+      // I should probably stop if traverse return false 
+      //  std::cerr<<"recursive_visitor traverse "<<(*m_module_iterator)->name()<<std::endl; 
+      traverse_assignment((*m_module_iterator));
+      //  std::cerr<<"recursive_visitor traverse end "<<(*m_module_iterator)->name()<<std::endl; 
+    }
+    return true;
+}
+
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_alternative_choice(asn1::field *S)
+{
+  TRY_TO(walkup_from_alternative_choice(S));
+  return traverse_type(S->get_type());
+}
+
+
+
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_component_type(asn1::field *S)
+{
+  TRY_TO(walkup_from_component_type(S));
+  return traverse_type(S->get_type());
+}
+// -- Assignment Traversal
+
+#define DEF_TRAVERSE_ASSIGN(STAMT,CODE)                           \
+    template <typename Derived>                                   \
+    bool recursive_visitor<Derived>::traverse_assign_##STAMT(STAMT##_assignment *S) { \
+        TRY_TO(walkup_from_assign_##STAMT(S));                            \
+        { CODE ; }                                                \
+        /* Traverse Children to be done*/                         \
+        return   traverse_type(S->get_type());                    \
+        /*return true; */                                         \
+    }                                                             \
+
+#if 0
+#define DISPATCH(NAME,CLASS,VAR)                                    \
+    return getDerived().traverse_##NAME(static_cast<asn1::node *>(VAR))
+#else
+#define DISPATCH(NAME,CLASS,VAR)                                    \
+    return getDerived().traverse_##NAME(static_cast<CLASS *>(VAR))
+#endif
+
+#define DISPATCH_CLS(NAME,CLASS,VAR)                                    \
+    return getDerived().traverse_##NAME(static_cast<CLASS *>(VAR))
+
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_assignment(asn1::node *S)
+{
+#define DISPATCH_ASSIGN(NAME,CLASS,VAR) \
+    return getDerived().traverse_assign_##NAME(static_cast<CLASS##_assignment *>(VAR))
+    if (! S)
+      return true;
+    // Dispatch according to statement
+    switch (S->meta_id()()) {
+        case asn1::meta::MAX:
+        case asn1::meta::INVALID:
+        break;
+#define ASSIGNMENT(TP,CLASS,PARENT)                      \
+        case asn1::meta::TP :                         \
+             DISPATCH_ASSIGN(CLASS,CLASS,S);
+#include "asn1_meta.inc"
+    }
+    return true;
+}
+
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_type(asn1::node *S)
+{
+    if (! S)
+        return true;
+#define DISPATCH_TYPE(NAME,CLASS,VAR) DISPATCH(NAME,CLASS,VAR)
+    // Dispatch according to statement
+    switch (S->type_id()()) {
+        case asn1::type::INVALID:
+        break;
+#define ASN1_TYPE(CLASS,PARENT,TP)                        \
+        case asn1::type::ASN1_##TP :                      \
+             DISPATCH_TYPE(CLASS,CLASS,S);
+
+#define ASN1_CLASSFIELD_TYPE(CLASS,PARENT,TP)                        \
+        case asn1::type::ASN1_##TP :                      \
+             DISPATCH_CLS(CLASS,CLASS,S);
+
+#define ASN1_STRING_TYPE(CLASS,PARENT,TP)                        \
+        case asn1::type::ASN1_STRING_##TP :                      \
+             DISPATCH_TYPE(CLASS,CLASS,S);
+
+
+#include "adt/asn1_type.inc"
+        default:
+        ;
+    }
+    return true;
+}
+
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_object_field(asn1::classfield *S
+                                                      ,asn1::node *field)
+{
+    if (! S)
+        return true;
+#define DISPATCH_OBJF(NAME,CLASS,VAR)                                    \
+    return getDerived().traverse_object_##NAME(static_cast<CLASS *>(VAR),field)
+    // Dispatch according to statement
+    switch (S->type_id()()) {
+        case asn1::type::INVALID:
+        break;
+#define ASN1_TYPE(CLASS,PARENT,TP)
+#define ASN1_PRIMITIVE_TYPE(CLASS,PARENT,TP)
+#define ASN1_CONSTRUCTED_TYPE(CLASS,PARENT,TP)
+#define ASN1_STRING_TYPE(CLASS,PARENT,TP)
+
+#define ASN1_CLASSFIELD_TYPE(CLASS,PARENT,TP)             \
+        case asn1::type::ASN1_##TP :                      \
+             DISPATCH_OBJF(CLASS,CLASS,S);
+
+
+#include "adt/asn1_type.inc"
+        default:
+        ;
+    }
+    return true;
+}
+
+/* Implementation Traverse assignment */
+DEF_TRAVERSE_ASSIGN(typeref,{})
+DEF_TRAVERSE_ASSIGN(type,{})
+DEF_TRAVERSE_ASSIGN(value,{})
+DEF_TRAVERSE_ASSIGN(valueset,{
+  if ( asn1::value *v = S->value())
+  {
+    traverse_constraint(v->m_constraint);
+  } 
+})
+DEF_TRAVERSE_ASSIGN(object,{
+  asn1::object   *obj  = dynamic_cast<asn1::object *>(S->type_node()->type_node()); 
+  // Now, Get classdef and visit the fields
+  if (asn1::classdef *cdef = obj->get_classdef())
+  {
+    for ( asn1::node::iterator it = cdef->begin()
+        ; it != cdef->end()
+        ; ++it)
+    {
+       if (asn1::node *field = obj->get_field((*it)->name()))
+       {
+         traverse_object_field(static_cast<asn1::classfield *>(*it),field);
+       }
+    }    
+  }  
+})
+DEF_TRAVERSE_ASSIGN(objectclass,{})
+DEF_TRAVERSE_ASSIGN(objectset,{
+})
+DEF_TRAVERSE_ASSIGN(objectfield,{})
+
+/* Implementation Traverse type */
+
+
+#define DEF_TRAVERSE_TYPE(STAMT,CODE)                        \
+    template <typename Derived>                                   \
+    bool recursive_visitor<Derived>::traverse_##STAMT(STAMT *S) { \
+        TRY_TO(walkup_from_##STAMT(S));                            \
+        { CODE ; }                                                \
+        /* Traverse Children to be done*/                         \
+        /*return   traverse_type(S->todo()); */                   \
+        return true;                                              \
+    }                                                             \
+
+
+DEF_TRAVERSE_TYPE(reference,{}) 
+DEF_TRAVERSE_TYPE(exportvar,{}) 
+//DEF_TRAVERSE_TYPE(universal,{}) 
+//DEF_TRAVERSE_TYPE(bitvector,{}) 
+DEF_TRAVERSE_TYPE(extensible,{}) 
+DEF_TRAVERSE_TYPE(components_of,{}) 
+DEF_TRAVERSE_TYPE(valueset,{
+  if ( asn1::value *v = S->value())
+  {
+    traverse_constraint(v->m_constraint);
+  } 
+})
+
+DEF_TRAVERSE_TYPE(objectset,{
+  if ( asn1::value *v = S->value())
+  {
+    traverse_constraint(v->m_constraint);
+  } 
+})
+
+DEF_TRAVERSE_TYPE(classdef,{
+  for (asn1::node::iterator it = S->begin()
+      ; it  != S->end()
+      ; ++it)
+      traverse_component_type(reinterpret_cast<asn1::field *>(*it));  
+}) 
+//DEF_TRAVERSE_TYPE(instance,{}) 
+DEF_TRAVERSE_TYPE(classfield,{})
+/**
+  * CLASS FIELD TYPE
+  */
+#define DEF_TRAVERSE_CLASSFIELD(STAMT,CODE,CODE1)                  \
+    template <typename Derived>                                    \
+    bool recursive_visitor<Derived>::traverse_##STAMT(STAMT *S) {  \
+        TRY_TO(walkup_from_classfield(S));                         \
+        TRY_TO(visit_##STAMT(S));                                  \
+        { CODE ; }                                                \
+        /* Traverse Children to be done*/                         \
+        /*return   traverse_type(S->todo()); */                   \
+        return true;                                              \
+    }                                                             \
+    template <typename Derived>                                   \
+    bool recursive_visitor<Derived>::traverse_object_##STAMT      \
+                                             (STAMT *S,asn1::node *f) {  \
+        TRY_TO(walkup_from_object_classfield(S,f));               \
+        TRY_TO(visit_object_##STAMT(S,f));                        \
+        { CODE1; }                                                \
+        /* Traverse Children to be done*/                         \
+        /*return   traverse_type(S->todo()); */                   \
+        return true;                                              \
+    }                                                             \
+
+DEF_TRAVERSE_CLASSFIELD(classfield_tf,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_ftvf,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_vtvf,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_ftvsf,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_vtvsf,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_of,{},{})
+DEF_TRAVERSE_CLASSFIELD(classfield_osf,{
+},
+{
+  if (f)
+  {
+    if ( asn1::value *v = f->value())
+    {
+      traverse_constraint(v->m_constraint);
+    }
+  }
+  }
+)
+
+/* 
+ * CONSTRUCTED TYPES
+ */
+#define DEF_TRAVERSE_CONSTRUCTED DEF_TRAVERSE_TYPE
+DEF_TRAVERSE_CONSTRUCTED(sequence,{
+  for (asn1::node::iterator it = S->begin()
+      ; it  != S->end()
+      ; ++it)
+      traverse_component_type(reinterpret_cast<asn1::field *>(*it));  
+})
+DEF_TRAVERSE_CONSTRUCTED(choice,{
+  for (asn1::node::iterator it = S->begin()
+      ; it  != S->end()
+      ; ++it)
+      traverse_alternative_choice(reinterpret_cast<asn1::field *>(*it));  
+})
+DEF_TRAVERSE_CONSTRUCTED(set,{
+  for (asn1::node::iterator it = S->begin()
+      ; it  != S->end()
+      ; ++it)
+      traverse_component_type(reinterpret_cast<asn1::field *>(*it));  
+})
+DEF_TRAVERSE_CONSTRUCTED(sequence_of,{
+      traverse_type(S->get_eltype());  
+})
+DEF_TRAVERSE_CONSTRUCTED(set_of,{
+      traverse_type(S->get_eltype());  
+})
+DEF_TRAVERSE_CONSTRUCTED(selection,{})
+/* 
+ * PRIMITIVE TYPES
+ */
+#define DEF_TRAVERSE_PRIMITIVE DEF_TRAVERSE_TYPE
+DEF_TRAVERSE_PRIMITIVE(any,{})
+DEF_TRAVERSE_PRIMITIVE(boolean,{})
+DEF_TRAVERSE_PRIMITIVE(integer,{})
+DEF_TRAVERSE_PRIMITIVE(bit_string,{})
+DEF_TRAVERSE_PRIMITIVE(octet_string,{})
+DEF_TRAVERSE_PRIMITIVE(null,{})
+DEF_TRAVERSE_PRIMITIVE(object_identifier,{})
+DEF_TRAVERSE_PRIMITIVE(object_descriptor,{})
+DEF_TRAVERSE_PRIMITIVE(real,{})
+DEF_TRAVERSE_PRIMITIVE(enumerated,{})
+DEF_TRAVERSE_PRIMITIVE(relative_oid,{})
+DEF_TRAVERSE_PRIMITIVE(external,{})
+DEF_TRAVERSE_PRIMITIVE(embedded_pdv,{})
+DEF_TRAVERSE_PRIMITIVE(character_string,{})
+DEF_TRAVERSE_PRIMITIVE(utctime,{})
+DEF_TRAVERSE_PRIMITIVE(generalizedtime,{})
+/*
+ * STRING TYPES
+ */
+/*
+ASN1_STRING_TYPE(string,primitive,STRING) 
+*/
+#define DEF_TRAVERSE_STRING DEF_TRAVERSE_TYPE
+DEF_TRAVERSE_STRING(ia5string,{})
+DEF_TRAVERSE_STRING(printablestring,{})
+DEF_TRAVERSE_STRING(visiblestring,{})
+DEF_TRAVERSE_STRING(iso646string,{})
+DEF_TRAVERSE_STRING(numericstring,{})
+DEF_TRAVERSE_STRING(universalstring,{})
+DEF_TRAVERSE_STRING(bmpstring,{})
+DEF_TRAVERSE_STRING(utf8string,{})
+DEF_TRAVERSE_STRING(generalstring,{})
+DEF_TRAVERSE_STRING(graphicstring,{})
+DEF_TRAVERSE_STRING(teletexstring,{})
+DEF_TRAVERSE_STRING(t61string,{})
+DEF_TRAVERSE_STRING(videotexstring,{})
+DEF_TRAVERSE_STRING(objectdescriptor_string,{})
+
+/**
+ * VISITE CONSTRAINTS 
+ */
+template <typename Derived>
+bool recursive_visitor<Derived>::traverse_constraint(asn1::constraint *S)
+{
+    if (! S)
+        return true;
+#define DISPATCH_CONSTRAINT(NAME,CLASS,VAR) DISPATCH_CLS(NAME,CLASS,VAR)
+    // Dispatch according to statement
+    switch (S->type()) {
+        case asn1::constraint::EL_INVALID:
+        break;
+#define ELEMENT_CONSTRAINT(TP,CLASS,PARENT)                        \
+        case asn1::constraint::TP :                              \
+             DISPATCH_CONSTRAINT(CLASS,CLASS,S);
+
+#include "asn1_constraint.inc"
+        default:
+          std::cout<<"UNKNOWN CONSTRAINT"<<std::endl;
+        ;
+    }
+    return true;
+}
+
+/* Implementation Traverse type */
+#define DEF_TRAVERSE_CONSTRAINT(STAMT,CODE)                        \
+    template <typename Derived>                                   \
+    bool recursive_visitor<Derived>::traverse_##STAMT(STAMT *S) { \
+        TRY_TO(walkup_from_##STAMT(S));                            \
+        { CODE ; }                                                \
+        /* Traverse Children to be done*/                         \
+        /*return   traverse_type(S->todo()); */                   \
+        return true;                                              \
+    }                                                             \
+
+DEF_TRAVERSE_CONSTRAINT(constraint_element,{})
+DEF_TRAVERSE_CONSTRAINT(constraint_type,{})
+DEF_TRAVERSE_CONSTRAINT(constraint_array,{})
+/* Element type */
+DEF_TRAVERSE_CONSTRAINT(celt_type,{})
+DEF_TRAVERSE_CONSTRAINT(celt_value,{})
+DEF_TRAVERSE_CONSTRAINT(celt_range,{})
+DEF_TRAVERSE_CONSTRAINT(celt_llrange,{})
+DEF_TRAVERSE_CONSTRAINT(celt_rlrange,{})
+DEF_TRAVERSE_CONSTRAINT(celt_ulrange,{})
+DEF_TRAVERSE_CONSTRAINT(celt_encodedby,{})
+DEF_TRAVERSE_CONSTRAINT(celt_ext,{})
+
+/*Constraint type */
+#define DEF_TRAVERSE_CONSTRAINT_TYPE(elt,code) DEF_TRAVERSE_CONSTRAINT(elt,code)
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_size,{})
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_from,{})
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_wcomp,{})
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_wcomps,{})
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_ctdby,{})
+DEF_TRAVERSE_CONSTRAINT_TYPE(ctype_ctng,{})
+
+/* Array Constraints */
+#define DEF_TRAVERSE_CONSTRAINT_ARRAY(elt,code) DEF_TRAVERSE_CONSTRAINT(elt,code)
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_set,{
+  for (asn1::constraint::iterator it = S->begin()
+      ; it != S->end()
+      ; ++it)
+  {
+    traverse_constraint(*it);
+  }  
+})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_crc,{})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_csv,{})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_uni,{
+  for (asn1::constraint::iterator it = S->begin()
+      ; it != S->end()
+      ; ++it)
+  {
+    traverse_constraint(*it);
+  }  
+
+})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_int,{})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_exc,{})
+DEF_TRAVERSE_CONSTRAINT_ARRAY(ca_aex,{})
+
+
+/**
+ * END
+ */ 
+#undef DEF_TRAVERSE_STRING
+#undef DEF_TRAVERSE_TYPE
+#undef DEF_TRAVERSE_CONSTRUCTED
+#undef DEF_TRAVERSE_PRIMITIVE
+#undef DEF_TRAVERSE_CLASSFIELD
+
+/* END NAMESPACE ASN1 */
+}
+
+#endif
diff --git a/adt/asn1_reference.cpp b/adt/asn1_reference.cpp
new file mode 100644 (file)
index 0000000..c54c209
--- /dev/null
@@ -0,0 +1,199 @@
+
+#include <iostream>
+#include <list>
+#include <algorithm>
+#if defined(_WIN32)
+#include <iterator>
+#endif
+#include "asn1_node.h"
+#include "asn1_reference.h"
+
+namespace asn1 {
+  
+static 
+char  lop_substitute(char c)
+{
+    return (c == '-')?'_':c;
+}
+
+reference::reference()
+  : node ("",type::ASN1_REFERENCE)
+{
+}
+
+reference::reference(const asn1::reference::component &c) 
+  : node("",type::ASN1_REFERENCE)
+{
+      add_component(c);   
+}
+
+reference::reference(const asn1::reference::component_list &c) 
+  : node("",type::ASN1_REFERENCE)
+{
+      add_components(c);   
+}
+
+reference::reference(const reference &ref)
+  : node(ref)
+{
+    std::copy( ref.m_components.begin()
+             , ref.m_components.end()
+             , std::back_inserter(m_components));  
+}
+
+reference::~reference()
+{
+}
+
+void
+reference::add_component(const struct component &c) 
+{
+  m_components.push_back(c);
+}
+
+void
+reference::add_components(const component_list &c) 
+{
+    std::copy(c.begin(),c.end(),std::back_inserter(m_components));  
+}
+
+
+std::string 
+reference::name() const
+{
+  std::string s;
+  if (m_components.size() > 0) 
+  {
+    for (component_const_iterator it = m_components.begin();
+          it != m_components.end();
+         ++it)
+    {
+       if (s.size() > 0)
+         s = s + "::"; 
+       s = s + (*it).m_identifier;
+    }
+  }
+  return s;
+}
+
+void 
+reference::replace_objectclass(const std::string &o)
+{
+  component n(o,component::CAPITALS);    
+  m_components.pop_front();
+  m_components.push_front(n);
+}
+
+std::string 
+reference::cpp_name() const
+{
+  std::string n = name();
+  std::string cppname;
+  cppname.resize(n.size());
+
+  std::transform(n.begin(),n.end(),cppname.begin(),asn1::lop_substitute);
+  return cppname;
+}
+
+
+
+reference::component::component(const std::string &n ,component::eType _t) : type(_t), m_identifier(n) {}
+
+bool  
+reference::component::operator ==(const struct component &c) 
+{
+return (!m_identifier.compare(c.m_identifier) && type == c.type);  
+}
+
+
+
+
+
+reference::component_iterator 
+reference::begin()             { return m_components.begin();};
+
+reference::component_iterator 
+reference::end()               { return m_components.end();};
+
+reference::component_const_iterator 
+reference::begin() const { return m_components.begin();};
+
+reference::component_const_iterator 
+reference::end() const   { return m_components.end();};
+
+reference::component 
+reference::back() { return m_components.back();};
+
+reference::component
+reference::front() const { return m_components.front();};
+
+size_t 
+reference::size() const  { return m_components.size();} ;
+
+reference::component_list &
+reference::get_components() { return m_components; };
+
+const 
+reference::component_list &
+reference::get_components() const { return m_components; };
+
+bool 
+reference::equals(const reference &) const { return false; } ;
+
+bool 
+reference::operator ==(const reference &r) const{ return equals(r); };
+
+
+
+/** **/
+bool simple_reference::equals(const reference &r) 
+{ 
+  return (size() == r.size()) 
+         && (front() == r.front());
+}
+/** **/ 
+external_type_reference::external_type_reference(const std::string &module,const std::string &tp) 
+  : reference(component(module,component::Uppercase)) 
+{
+  component c(tp,component::Uppercase);
+  add_component(c);    
+}
+
+external_type_reference::external_type_reference(const std::string &module,const reference::component_list &tp) 
+  : reference(component(module,component::Uppercase)) 
+{
+  add_components(tp);    
+}
+
+external_type_reference::external_type_reference(const std::string &module,const reference &tp) 
+  : reference(component(module,component::Uppercase)) 
+{
+  add_components(tp.get_components());
+}
+
+
+bool external_type_reference::equals(const reference &r) 
+{ 
+  return (size() == r.size()) 
+         && (front() == r.front());
+}
+
+/** **/
+
+external_value_reference::external_value_reference(const std::string &module,const std::string &val) 
+: reference(component(module,component::Uppercase)) 
+{
+  component c(val,component::Lowercase);
+  add_component(c);    
+}
+
+external_value_reference::~external_value_reference() {}
+
+bool external_value_reference::equals(const reference &r) 
+{ 
+  return (size() == r.size()) 
+         && (front() == r.front());
+}
+
+
+}
diff --git a/adt/asn1_reference.h b/adt/asn1_reference.h
new file mode 100644 (file)
index 0000000..21fb427
--- /dev/null
@@ -0,0 +1,197 @@
+#ifndef ASN1_REFERENCE_H
+#define ASN1_REFERENCE_H
+
+namespace asn1 {
+
+class node;
+
+class reference : public node {
+  public:
+    struct component;
+    
+    typedef std::list<component> component_list;
+    typedef std::list<component>::iterator component_iterator;
+    typedef std::list<component>::const_iterator component_const_iterator;
+    
+    reference();
+    
+    reference(const struct component &c) ;
+
+    reference(const reference &_r)  ;
+    
+    reference(const component_list &cl);
+    
+    ~reference();
+    
+    /**
+     *
+     */ 
+    struct component
+    {
+      enum eType {
+        UNKNOWN,
+        CAPITALS,
+        Uppercase,
+        Lowercase,
+        AmpUppercase,
+        AmpLowercase
+
+      } type;
+
+      std::string m_identifier;
+   
+      inline std::string name() const { return m_identifier;  };
+
+      component(const std::string &n = "" ,eType _t = UNKNOWN) ;
+
+      bool  operator ==(const struct component &c); 
+
+    };
+
+
+    void add_component(const struct component &c);
+    
+    void add_components(const component_list &cl);
+    
+    std::string name() const;
+    
+    std::string cpp_name() const;
+    
+    component_iterator begin() ;
+    
+    component_iterator end();
+    
+    component_const_iterator begin() const;
+    
+    component_const_iterator end() const;
+
+    component back();
+    component front() const ;
+    size_t size() const ;
+    
+    component_list &get_components() ;
+    
+    const component_list &get_components() const;
+    
+    virtual bool equals(const reference &) const;
+
+    bool operator ==(const reference &r) const ;
+
+    void replace_objectclass(const std::string &o);
+  protected:
+    component_list m_components;
+};
+
+/**
+ *
+ */ 
+class simple_reference : public reference
+{
+  public:
+    simple_reference(const struct component &c) : reference()
+    {
+    } 
+    
+    simple_reference(const std::string &n,component::eType _t = component::Uppercase) 
+        : reference(component(n,_t) )
+    {
+    } 
+
+    ~simple_reference() {}
+
+    virtual bool equals(const reference &r) ;
+  protected:
+};
+
+/**
+ *
+ */ 
+class external_type_reference : public reference
+{
+  public:
+    external_type_reference(const std::string &module,const std::string &tp) ;
+    
+    external_type_reference(const std::string &module,const reference::component_list &tp) ;
+    
+    external_type_reference(const std::string &module,const reference &tp); 
+
+    ~external_type_reference() {}
+
+    virtual bool equals(const reference &r) ;
+  protected:
+};
+
+
+/**
+ *
+ */ 
+class external_value_reference : public reference
+{
+  public:
+    external_value_reference(const std::string &module,const std::string &val) ;
+    ~external_value_reference() ;
+
+    virtual bool equals(const reference &r) ;
+  protected:
+};
+
+
+/**
+ * objectclass reference can contain 
+ *  typefield reference
+ *  valuefied reference
+ *  type      referece
+ *  I think that this is the only class that needs a list of fields
+ */ 
+class objectclass_reference : public reference
+{
+  public:
+    objectclass_reference(const std::string &n) 
+      : reference(component(n,component::CAPITALS)) 
+    {
+    } ;
+    ~objectclass_reference() {} ;
+
+    std::string objectclass()
+    {
+      return m_components.front().m_identifier;   
+    }
+
+    std::string field() const
+    { return m_components.back().m_identifier; }
+};
+
+
+/**
+ *
+ */ 
+class typefield_reference : public reference
+{
+  public:
+    typefield_reference(const std::string &n) 
+      : reference(component(n,component::AmpUppercase)) 
+    {
+    } ;
+    ~typefield_reference() {} ;
+};
+
+
+/**
+ *
+ */
+class valuefield_reference : public reference
+{
+  public:
+    valuefield_reference(const std::string &n) 
+      : reference(component(n,component::AmpLowercase)) 
+    {
+    } ;
+    ~valuefield_reference() {} ;
+};
+
+
+
+
+}
+#endif
+
diff --git a/adt/asn1_resolver.cpp b/adt/asn1_resolver.cpp
new file mode 100644 (file)
index 0000000..e865bfd
--- /dev/null
@@ -0,0 +1,494 @@
+#include <iostream>
+#include <list>
+#include <algorithm>
+#include <sstream>
+#include <string.h>     
+#include <assert.h>     
+
+#include "asn1_meta.h"
+#include "asn1_type.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+#include "aeb/pointer/intrusive_ptr.h"
+#include "asn1_module.h"  //includes nodes.
+
+#include "asn1_resolver.h"
+#if defined(_WIN32)
+#define GEN_LOG_DEBUG(fmt,...)
+#define GEN_LOG_INFO(fmt,...)
+#define GEN_LOG_ERROR(fmt,...)
+#define GEN_LOG_WARN(fmt,...)
+#else
+#define GEN_LOG_DEBUG(fmt,args...)
+#define GEN_LOG_INFO(fmt,args...)
+#define GEN_LOG_ERROR(fmt,args...) fprintf(stderr,fmt,args)
+#define GEN_LOG_WARN(fmt,args...)
+#endif
+namespace asn1 {
+
+/**
+ *
+ */ 
+resolver::resolver( const asn1::module               &_m
+                  , const asn1::module::modules_type &_mods)
+    : m_module(_m),m_module_list(_mods)
+{
+}
+
+/**
+ *
+ */ 
+resolver::~resolver()
+{
+}
+
+/**
+ * Resolve with reference
+ *   Simple references should be found in the current module 
+ */ 
+asn1::node * resolver::resolve(const typeref &_ref)
+{
+  asn1::node *nr = NULL;    
+  if ( _ref.is_simple())
+  {
+    asn1::node::const_iterator it = std::find_if(m_module.begin()
+                                      , m_module.end()
+                                      , asn1::find_node(_ref.name()));
+    if  (it != m_module.end())
+    {
+#if 0
+      // 2017/05/10 Issue with H323 and typeref resolve !! Fails with ClearToken
+      // Found Here null in caller. Looks like a stack overflow
+      std::cerr<<"resolver::resolve type "<<_ref.name()<<" Found in module\n";
+      std::cerr<<"resolver::resolve "<<(*it)->as_assignment()->get_type()->name()<<" Found in module ";
+      std::cerr<<(*it)->as_assignment()->get_type()<<"\n";
+#endif
+      return (*it)->as_assignment()->get_type();
+    }else
+    { 
+      // Node not found in module, try other modules from imports
+      asn1::node *ns;
+      if (type_in_imports(_ref.name(),&ns))
+      {
+        if ( !get_type_in_module(ns->name(),_ref.name(),&nr) )
+        {
+          std::cerr<<"resolver::resolve type <"<<_ref.name();
+          std::cerr<<"> Not Found in module "<<ns->name()<<std::endl;
+          std::cerr<<"modules size   : "<<m_module_list.size()<<std::endl;
+          assert(0);
+        } else
+        {
+#if 0
+         /* No console trace when OK */
+          std::cerr<<"resolver::resolve type in import "<<_ref.name();
+          std::cerr<<" in module "<<nr->from_module()->name()<<" Found\n";
+#endif
+          GEN_LOG_WARN("resolver::resolve tye %s found in imports %s\n"
+                     , _ref.name().c_str()
+                     , ns->name().c_str()
+                    );
+          nr = nr->as_assignment()->get_type();   
+        }
+      } else
+      {
+        std::string modname("");
+        if (! _ref.is_imported(modname))
+          modname = _ref.from_module()->name();
+       // Type not in imports.
+        std::cerr<<"resolver::resolve type <"<<_ref.name()<<" not in imports"<<std::endl;
+        GEN_LOG_WARN("resolver::resolve type %s not found in imports\n"
+                     , _ref.name().c_str()
+                    );
+        std::cerr<<"resolver::resolve try in module "<<modname<<std::endl;
+        if ( !get_type_in_module(modname,_ref.name(),&nr) )
+        {
+          std::cerr<<"resolver::resolve type "<<_ref.name()<<" not in module =";
+          std::cerr<<modname<<std::endl;
+        } else {
+          nr = nr->as_assignment()->get_type();   
+        }
+      }
+    }
+
+  } else if (_ref.is_objectclass())
+  {
+    asn1::objectclass_reference         & ocr = _ref.get_objectclass();
+    asn1::node::const_iterator it = std::find_if(m_module.begin()
+                                      , m_module.end()
+                                      , asn1::find_node(ocr.objectclass()));
+    if (it != m_module.end()
+       && (*it)->meta_id()() == asn1::meta::TYPEREF )
+    {
+      std::cerr<<"resolver::resolve warning object class reference "<<(*it)->name();
+      std::cerr<<" meta="<<(*it)->meta_id()()<<std::endl;
+      asn1::typenode *nt =     (*it)->as_assignment()->get_type();    
+      it = std::find_if(m_module.begin()
+                                      , m_module.end()
+                                      , asn1::find_node(nt->name()));
+      std::cerr<<"resolver::resolve warning object class reference "<<nt->name()<<std::endl;
+      if (it == m_module.end())
+      {
+      } else
+        std::cerr<<"resolver::resolve warning object class reference "<<(*it)->name()<<std::endl;
+      asn1::objectclass_reference rr(ocr);
+      rr.replace_objectclass(nt->name());
+      asn1::node *n = resolve_objcls(_ref,rr);
+      return n;    
+    } else
+    {
+      asn1::node *n = resolve_objcls(_ref,ocr);
+      if (! n)
+      {
+        std::cerr<<"resolver::resolve unable to resolve "<<_ref.name()<<std::endl;
+        //assert(0 && "resolver::resolve_objcls failed");
+      }
+      if (n &&  n->type_node())
+      {
+        std::cerr<<"resolver::resolve result from resolve_objcls "<<_ref.name()<<std::endl;
+       if (!n->as_typenode())
+          n = n->type_node();
+      }
+      return n;
+    }
+  } else if (_ref.is_external())
+  {
+    asn1::reference::component_const_iterator it = _ref.get_reference()->begin();
+    asn1::module *m = module((*it).name());
+    assert(0 && " external ref should never occur, it's transformed at parsing level");
+  } else
+  {
+    // Loop over components. 
+    asn1::reference::component_const_iterator it = _ref.get_reference()->begin();
+    std::cerr<<"resolver::resolve Not Yet Supported " <<_ref.name()<<"\n";  
+  }
+  return nr;    
+}
+
+/** Resolve with parameters
+ * parameter can be a typereference.
+ * typeref contains act_parameters,
+ *   lookup in _params, in module, in imports
+ */   
+
+bool resolver::resolve(typeref &_ref,parameters _params,asn1::node &type)
+{
+  return false;
+}
+
+/**
+ *
+ */ 
+asn1::node *
+resolver::resolve_objcls(const asn1::typeref &tref,asn1::objectclass_reference &ref)
+{
+  asn1::node *nr = NULL;    
+  if (ref.size() <= 1) 
+  {
+    asn1::node::const_iterator it = std::find_if(m_module.begin()
+                                      , m_module.end()
+                                      , asn1::find_node(ref.name()));
+    if  (it != m_module.end())
+    {
+      nr = (*it)->as_assignment()->get_type();    
+    } else
+    {
+      // Node not found in module, try other modules
+      asn1::node *ns;
+      if (type_in_imports(ref.name(),&ns))
+      {
+        if ( !get_type_in_module(ns->name(),ref.name(),&nr) )
+        {
+          std::cerr<<"Object "<<ns->name();
+          std::cerr<<" Not Found in module "<<ref.name()<<std::endl;
+        } else
+        {
+          nr = nr->as_assignment()->get_type();   
+        }
+      }
+    }
+    
+  } else if (std::string("TYPE-IDENTIFIER::&Type").compare(ref.name()) == 0)
+  {
+    asn1::constraint::const_iterator c = tref.constraint_begin();
+    if ((*c)->type() == asn1::constraint::EL_TYPE)
+    {
+      asn1::typeref *ctype = dynamic_cast<asn1::typeref *>((*c)->value());
+      assert(ctype != NULL);
+      std::cerr<<__FUNCTION__<<" GOT TYPE-IDENTIFIER&Type "<<ctype->name()<<std::endl;
+      nr = resolve(*ctype);
+      std::cerr<<__FUNCTION__<<" After resolve in resolve Issue here "<<nr->name()<<std::endl;
+      //nr = nr->type_node();   
+    }
+  } else 
+  {
+    asn1::classdef *current_cls = NULL;
+    asn1::reference::component_const_iterator it = ref.begin();
+    do
+    {
+      asn1::node *cident = NULL;
+      std::string cname = (*it).m_identifier;
+      if ( (cname[0] != '&') )
+      {
+        asn1::node *ns;
+        if (get_type_in_module(m_module.name(),cname,&cident))
+        {
+          current_cls = dynamic_cast<asn1::classdef *>(cident->as_assignment()->get_type());
+        } else if (type_in_imports(cname,&ns)
+                   && get_type_in_module(ns->name(),cname,&cident)
+                  )
+        {
+          current_cls = dynamic_cast<asn1::classdef *>(cident->as_assignment()->get_type());
+        } else
+        {
+          assert(0);
+        }
+      } else if (cname[0] == '&' && current_cls)
+      {
+        //asn1::node::iterator cls_attribute = std::find_if(current_cls->begin(),
+        //                            current_cls->end(),
+        //                            asn1::find_node((*it).m_identifier));
+        asn1::classfield *cls_attribute = current_cls->get_classfield((*it).m_identifier);
+        if (cls_attribute != NULL)
+        {
+          //std::cerr<<"Found "<<(*cls_attribute)->name()<<" In class\n";
+          // Wow attribute found in class Now I can decide what to do
+          switch( cls_attribute->type_id()())
+          {
+            case asn1::type::ASN1_CLASSFIELD_TF:
+              GEN_LOG_DEBUG("resolver::Found typefield %s in class %s\n"
+                           , (*it).m_identifier.c_str()
+                           , current_class->name().c_str());
+              
+              break;
+            case asn1::type::ASN1_CLASSFIELD_FTVF: 
+              {
+                GEN_LOG_DEBUG("resolver::Found typefield FTVF %s in class %s\n"
+                             , (*it).m_identifier.c_str()
+                             , current_class->name().c_str());
+              }
+              break;
+            case asn1::type::ASN1_CLASSFIELD_OSF:
+              { 
+                asn1::typeref *rnode = 
+                  dynamic_cast<asn1::typeref *>(cls_attribute->get_type());
+                std::cerr<<"PRBL "<<(*it).m_identifier<<" CLS:"<<rnode->name()<<"\n";
+                asn1::node *n = resolve(*rnode);
+                if (n)
+                { 
+                  std::cerr<<"Got N"<<" CLS:"<<n->name()<<"\n";
+                  current_cls = dynamic_cast<asn1::classdef *>(n);
+                }
+
+              }
+              break;
+            default:
+              GEN_LOG_ERROR("resolver::Found typefield %s in class %s NOT HANDLED\n"
+                           , (*it).m_identifier.c_str()
+                           , current_cls->name().c_str());
+              break;
+          } /* end switch */
+         //TODO not good, nr should not be classfield
+         std::cerr<<__FUNCTION__<<" nr should not be class field "<<cls_attribute->name()<<std::endl;
+          nr = cls_attribute;
+        } else
+        {
+          std::cerr<<"NOT Found "<<(*it).m_identifier<<" In current class ";
+          std::cerr<<current_cls->identifier()->name()<<"\n";
+          assert(0);
+        }
+      } else
+      {
+        std::cerr<<"NOT Found "<<cname<<" In module TODO check other modules\n";
+        assert(0);
+        break;
+      }
+      ++it;
+    } while (it != ref.end());
+
+  }
+  return nr;
+}
+
+
+
+
+
+
+
+
+
+bool resolver::type_in_imports( asn1::node *type
+                              , asn1::node **ns) const 
+{
+  return type_in_imports(type->name(),ns);
+}
+
+bool resolver::type_in_imports(const std::string &type
+                              , asn1::node **ns) const
+{
+  bool ret = false;
+  asn1::import_list *imports = m_module.imports();
+  if (imports == NULL)
+  {
+    GEN_LOG_ERROR("type %s not in imports no imports\n",type.c_str());
+    return ret;
+  }
+  asn1::node::iterator it = imports->begin();
+  GEN_LOG_DEBUG("lookup for type %s\n",type.c_str());
+  for (; it != imports->end();it++)
+  {
+    asn1::import *import = dynamic_cast<asn1::import *>(*it);
+    asn1::node::iterator found = std::find_if( import->begin()
+                                             , import->end()
+                                             , asn1::find_node(type));
+    if (found != import->end() )
+    {
+      GEN_LOG_DEBUG("found %s in %s\n",type.c_str(),import->identifier()->name().c_str());
+      *ns = import->identifier();
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+}
+
+/**
+ *
+ *
+ */ 
+asn1::module *
+resolver::module(const std::string &mod_name) const
+{
+  modules_const_iterator mit = std::find_if(m_module_list.begin()
+          , m_module_list.end()
+          , asn1::find_module(mod_name));
+  if (mit != m_module_list.end())
+  {
+    return *mit;  
+  } else
+    return NULL;  
+}
+
+/**
+ *
+ */ 
+bool 
+resolver::get_type_in_module( const std::string &mod_name
+                            , const std::string &typ_name
+                            , asn1::node **n) const
+{
+  GEN_LOG_INFO("resolver::get_type_in_module module=%s current_module=%s name=%s modules=%lu\n"
+               , mod_name.c_str()
+               , m_module->name().c_str()
+               , typ_name.c_str()
+               , m_modules.size());
+
+  modules_const_iterator mit = std::find_if(m_module_list.begin()
+          , m_module_list.end()
+          , asn1::find_module(mod_name));
+
+  if (mit != m_module_list.end()) 
+  {
+    asn1::node::iterator nit =
+        std::find_if(  (*mit)->begin()
+                     , (*mit)->end()
+                     , asn1::find_node(typ_name));
+    if (nit != (*mit)->end())
+    {
+      *n = (*nit);
+      return true;
+    } else 
+    {
+      std::cerr<<"resolver::get_type_in_module "<<mod_name;
+      std::cerr<<" real module name:"<<(*mit)->name()<<std::endl; 
+      std::cerr<<" tp:"<<typ_name<<" mod size="<<(*mit)->size()<<std::endl; 
+      GEN_LOG_ERROR("get_type_in_module type %s not in module %s M size=%d\n"
+                     , typ_name.c_str()
+                     , mod_name.c_str()
+                     , (*mit)->size()
+                     );
+      return false;
+    }
+  } else 
+  {
+    std::cerr<<"resolver::get_type_in_module did not find module "<<mod_name<<std::endl; 
+    GEN_LOG_ERROR("get_type_in_module did not find module %s\n",mod_name.c_str());
+    return false;
+  }
+}
+
+bool 
+resolver::get_type_in_module( asn1::module &mod
+                            , const std::string &typ_name
+                            , asn1::assignment **n) const
+{
+  asn1::node::iterator nit =
+    std::find_if(  mod.begin()
+         , mod.end()
+         , asn1::find_node(typ_name));
+  if (nit != mod.end())
+  {
+    *n = (*nit)->as_assignment();
+    return true;
+  } else 
+  {
+    std::cerr<<"resolver::get_type_in_module "<<mod.name();
+    std::cerr<<" real module name:"<<mod.name()<<std::endl; 
+    std::cerr<<" tp:"<<typ_name<<" mod size="<<mod.size()<<std::endl; 
+    GEN_LOG_ERROR("get_type_in_module type %s not in module %s M size=%d\n"
+            , typ_name.c_str()
+            , mod.name().c_str()
+            , mod.size()
+            );
+    return false;
+  }
+}
+
+/**
+* check if typename is in imports of module
+* if so, return module that contains the type.
+*/ 
+bool 
+resolver::get_type_in_module_import( const asn1::module &mod
+                                   , const std::string &typ_name
+                                   , asn1::module **in_module) const
+{
+  bool ret = false;
+  asn1::import_list *imports = mod.imports();
+  if (imports == NULL)
+  {
+    GEN_LOG_ERROR( "type %s not in imports no imports\n"
+                 , typ_name.c_str());
+    return ret;
+  }
+  asn1::node::iterator it = imports->begin();
+  GEN_LOG_DEBUG( "%s lookup for type %s\n"
+               , __FUNCTION__
+               , typ_name.c_str());
+  for (; it != imports->end();it++)
+  {
+    asn1::import *import = dynamic_cast<asn1::import *>(*it);
+    asn1::node::iterator found = std::find_if( import->begin()
+                                             , import->end()
+                                             , asn1::find_node(typ_name));
+    if (found != import->end() )
+    {
+      GEN_LOG_DEBUG( "%s found %s in %s\n"
+                   , __FUNCTION__
+                   , type.c_str()
+                   , import->identifier()->name().c_str());
+      *in_module = module(import->identifier()->name());
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+}
+
+
+
+
+
+
+
+}
diff --git a/adt/asn1_resolver.h b/adt/asn1_resolver.h
new file mode 100644 (file)
index 0000000..0b234fc
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef ASN1_RESOLVER_H
+#define ASN1_RESOLVER_H
+
+namespace asn1 {
+/**
+ * The purpose of the class is to resolve
+ * references. Example : given a reference,
+ * the resolver will find the correponding type.
+ *   T1 ::= SEQUENE {  }
+ *   T2 ::= CHOICE { t1 T1 }
+ *   resolve T1 returns type SEQUENCE T1.  
+ */ 
+class resolver
+{
+  public: 
+    typedef asn1::module::modules_type                 modules_type;
+    typedef asn1::module::modules_type::iterator       modules_iterator;
+    typedef asn1::module::modules_type::const_iterator modules_const_iterator;
+    typedef asn1::node::iterator                       node_iterator;
+
+    /// constructor
+    resolver( const asn1::module               &_m
+            , const asn1::module::modules_type &_mods);
+    /// copy constructor
+    resolver( const resolver &_r) 
+      : m_module(_r.m_module), m_module_list(_r.m_module_list) {}
+    ///
+    virtual ~resolver();
+    // Resolve with reference 
+    //  If found return type node of found reference
+    asn1::node *resolve(const typeref &_ref);
+    // Resolve with parameters
+    //  parameter can be a typereference.
+    //  typeref contains act_parameters,
+    //    lookup in _params, in module, in imports
+    bool resolve(typeref &_ref,parameters _params,asn1::node &type); 
+
+    asn1::module *module(const std::string &mn) const;
+  protected:
+    asn1::node *resolve_objcls(const typeref &tref, asn1::objectclass_reference &ref);
+    
+    bool get_type_in_module( const std::string &mod_name
+                           , const std::string &typ_name
+                           , asn1::node **n) const;
+    /**
+     * New way ...
+     */
+    bool get_type_in_module( asn1::module &mod
+                           , const std::string &typ_name
+                           , asn1::assignment **n) const;
+    /**
+     * check if typename is in imports of module
+     * if so, return module that contains the type.
+     */ 
+    bool get_type_in_module_import( const asn1::module &mod
+                           , const std::string &typ_name
+                           , asn1::module **in_module) const;
+
+    bool type_in_imports(asn1::node *type,asn1::node **ns) const;
+    
+    bool type_in_imports(const std::string &type,asn1::node **ns)const ;
+  protected:
+    const asn1::module               &m_module; // Current module
+    const asn1::module::modules_type &m_module_list;
+};
+
+}
+#endif /*ASN1_RESOLVER_H*/
diff --git a/adt/asn1_type.h b/adt/asn1_type.h
new file mode 100644 (file)
index 0000000..47167b6
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef ASN1_TYPE_H__
+#define ASN1_TYPE_H__
+
+
+namespace asn1
+{
+
+  class type
+  {
+    public:
+      typedef enum {
+        INVALID = 0 ,
+#if 1
+#define ASN1_TYPE(cls,parent,id)  ASN1_##id ,
+#define ASN1_STRING_TYPE(cls,parent,id)  ASN1_STRING_##id ,
+#define ASN1_ABSTRACT_STRING_TYPE(cls,parent,id)  ASN1_##id ,
+#include "adt/asn1_type.inc"
+#else
+        ASN1_REFERENCE,
+        ASN1_EXPORTVAR,
+        ASN1_UNIVERSAL,
+        ASN1_BITVECTOR,
+        ASN1_EXTENSIBLE,
+        ASN1_COMPONENTS_OF,
+        ASN1_VALUESET,
+        ASN1_CLASSDEF,
+        ASN1_INSTANCE,
+        
+        /**
+         * Class Field type
+         */
+        ASN1_CLASSFIELD,         /*  */
+        ASN1_CLASSFIELD_TF,      /* Type Field  10               */
+        ASN1_CLASSFIELD_FTVF,    /* Fixed Type Value Field       */
+        ASN1_CLASSFIELD_VTVF,    /* Variable Type Value Field    */
+        ASN1_CLASSFIELD_FTVSF,   /* Fixed Type Value Set Field   */
+        ASN1_CLASSFIELD_VTVSF,   /* Variable Type Value Set Field*/
+        ASN1_CLASSFIELD_OF,      /* Object Field                 */
+        ASN1_CLASSFIELD_OSF,     /* Object Set Field             */
+        /* Constructed Types
+         */
+        ASN1_SEQUENCE,           /* 18 */
+        ASN1_CHOICE,
+        ASN1_SET,
+        ASN1_SEQUENCE_OF,
+        ASN1_SET_OF,
+        ASN1_SELECTION,
+        /* Basic Types
+         */
+        ASN1_ANY,
+        ASN1_BOOLEAN,
+        ASN1_INTEGER,
+        ASN1_BIT_STRING,
+        ASN1_OCTET_STRING,
+        ASN1_NULL,
+        ASN1_OBJECT_IDENTIFIER,
+        ASN1_OBJECT_DESCRIPTOR,
+        ASN1_REAL,
+        ASN1_ENUMERATED,
+        ASN1_RELATIVE_OID,
+        ASN1_EXTERNAL,
+        ASN1_EMBEDDED_PDV,
+        ASN1_CHARACTER_STRING,
+        ASN1_UTCTime,
+        ASN1_GeneralizedTime,
+        /* String Types
+         */
+        ASN1_STRING,
+        ASN1_STRING_IA5String,
+        ASN1_STRING_PrintableString,
+        ASN1_STRING_VisibleString,
+        ASN1_STRING_ISO646String,    /* aka VisibleString */
+        ASN1_STRING_NumericString,
+        ASN1_STRING_UniversalString,
+        ASN1_STRING_BMPString,
+        ASN1_STRING_UTF8String  ,
+        ASN1_STRING_GeneralString,
+        ASN1_STRING_GraphicString,
+        ASN1_STRING_TeletexString,
+        ASN1_STRING_T61String,
+        ASN1_STRING_VideotexString,
+        ASN1_STRING_ObjectDescriptor,
+#endif
+        ASN1_TYPE_MAX
+      } id;
+
+      inline type(type::id id = INVALID) : m_id(id) {};
+      inline type(const type &m) : m_id(m.m_id) {};
+      inline type &operator =( const type &m) {m_id = m.m_id; return *this;};
+      inline type &operator =( const id i) {m_id = i; return *this;};
+      inline ~type()  {};
+      inline bool operator >(const type &a) {return m_id > a.m_id; };
+      inline bool operator >=(const type &a) {return m_id >= a.m_id; };
+      inline bool operator <=(const type &a) {return m_id <= a.m_id; };
+      inline bool operator <(const type &a) {return m_id < a.m_id; };
+      inline bool operator ==(const type &a) {return m_id == a.m_id; };
+      
+      inline id operator()() const
+      {
+          return m_id;
+      }
+       
+      const char *name() const ;
+      friend std::ostream & operator <<(std::ostream &os, const type &m)
+      {
+           os<<m.m_id;
+           return os;
+      }
+    protected:
+      id    m_id;
+  };
+}
+#endif
diff --git a/adt/asn1_type.inc b/adt/asn1_type.inc
new file mode 100644 (file)
index 0000000..1bacdc9
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef ASN1_TYPE
+#define ASN1_TYPE(cls,parent,id)
+#endif
+
+ASN1_TYPE(reference,node,REFERENCE) 
+ASN1_TYPE(exportvar,node,EXPORTVAR)    /* Exported definition in Exports            */ 
+//ASN1_TYPE(universal,node,UNIVERSAL)  /* Constants in Enum, Int, BitString and OID */
+//ASN1_TYPE(bitvector,node,BITVECTOR) 
+ASN1_TYPE(extensible,node,EXTENSIBLE) 
+ASN1_TYPE(components_of,node,COMPONENTS_OF) 
+ASN1_TYPE(valueset,typenode,VALUESET) 
+ASN1_TYPE(objectset,typenode,OBJECTSET) 
+ASN1_TYPE(classdef,node,CLASSDEF) 
+// Not yet used
+//ASN1_TYPE(instance,node,INSTANCE) 
+ASN1_TYPE(classfield,node,CLASSFIELD)
+/**
+  * CLASS FIELD TYPE
+  */
+#ifndef ASN1_CLASSFIELD_TYPE 
+#define ASN1_CLASSFIELD_TYPE ASN1_TYPE
+#endif
+ASN1_CLASSFIELD_TYPE(classfield_tf,classfield,CLASSFIELD_TF)       /* TYPE FIELD                   */
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,classfield,CLASSFIELD_FTVF)   /* FIXED TYPE VALUE FIELD       */
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,classfield,CLASSFIELD_VTVF)   /* VARIABLE TYPE VALUE FIELD    */
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,classfield,CLASSFIELD_FTVSF) /* FIXED TYPE VALUE SET FIELD   */
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,classfield,CLASSFIELD_VTVSF) /* VARIABLE TYPE VALUE SET FIELD*/
+ASN1_CLASSFIELD_TYPE(classfield_of,classfield,CLASSFIELD_OF)       /* OBJECT FIELD                 */
+ASN1_CLASSFIELD_TYPE(classfield_osf,classfield,CLASSFIELD_OSF)     /* OBJECT SET FIELD             */
+
+/* 
+ * CONSTRUCTED TYPES
+ */
+#ifndef ASN1_CONSTRUCTED_TYPE
+#define ASN1_CONSTRUCTED_TYPE ASN1_TYPE
+#endif
+ASN1_CONSTRUCTED_TYPE(sequence,constructed,SEQUENCE)            /* 17 */
+ASN1_CONSTRUCTED_TYPE(choice,constructed,CHOICE) 
+ASN1_CONSTRUCTED_TYPE(set,constructed,SET) 
+ASN1_CONSTRUCTED_TYPE(sequence_of,typenode,SEQUENCE_OF) 
+ASN1_CONSTRUCTED_TYPE(set_of,typenode,SET_OF) 
+ASN1_CONSTRUCTED_TYPE(selection,typeref,SELECTION) 
+/* 
+ * PRIMITIVE TYPES
+ */
+#ifndef ASN1_PRIMITIVE_TYPE
+#define ASN1_PRIMITIVE_TYPE ASN1_TYPE
+#endif
+ASN1_PRIMITIVE_TYPE(any,primitive,ANY) 
+ASN1_PRIMITIVE_TYPE(boolean,primitive,BOOLEAN) 
+ASN1_PRIMITIVE_TYPE(integer,constructed,INTEGER) 
+ASN1_PRIMITIVE_TYPE(bit_string,constructed,BIT_STRING) 
+ASN1_PRIMITIVE_TYPE(octet_string,primitive,OCTET_STRING) 
+ASN1_PRIMITIVE_TYPE(null,primitive,NULL) 
+ASN1_PRIMITIVE_TYPE(object_identifier,constructed,OBJECT_IDENTIFIER) 
+ASN1_PRIMITIVE_TYPE(object_descriptor,primitive,OBJECT_DESCRIPTOR) 
+ASN1_PRIMITIVE_TYPE(real,primitive,REAL) 
+ASN1_PRIMITIVE_TYPE(enumerated,constructed,ENUMERATED) 
+ASN1_PRIMITIVE_TYPE(relative_oid,primitive,RELATIVE_OID) 
+ASN1_PRIMITIVE_TYPE(external,primitive,EXTERNAL) 
+ASN1_PRIMITIVE_TYPE(embedded_pdv,primitive,EMBEDDED_PDV) 
+ASN1_PRIMITIVE_TYPE(character_string,primitive,CHARACTER_STRING) 
+ASN1_PRIMITIVE_TYPE(utctime,primitive,UTCTime) 
+ASN1_PRIMITIVE_TYPE(generalizedtime,primitive,GeneralizedTime) 
+/*
+ * STRING TYPES
+ */
+#ifndef ASN1_STRING_TYPE
+#  define ASN1_STRING_TYPE ASN1_TYPE
+#endif
+#ifndef ASN1_ABSTRACT_STRING_TYPE
+#  define ASN1_ABSTRACT_STRING_TYPE(cls,parent,id)
+#endif
+
+ASN1_ABSTRACT_STRING_TYPE(string,primitive,STRING) 
+
+ASN1_STRING_TYPE(ia5string,primitive,IA5String) 
+ASN1_STRING_TYPE(printablestring,primitive,PrintableString) 
+ASN1_STRING_TYPE(visiblestring,primitive,VisibleString) 
+ASN1_STRING_TYPE(iso646string,primitive,ISO646String)     /* AKA VISIBLESTRING */
+ASN1_STRING_TYPE(numericstring,primitive,NumericString) 
+ASN1_STRING_TYPE(universalstring,primitive,UniversalString) 
+ASN1_STRING_TYPE(bmpstring,primitive,BMPString) 
+ASN1_STRING_TYPE(utf8string,primitive,UTF8String)   
+ASN1_STRING_TYPE(generalstring,primitive,GeneralString) 
+ASN1_STRING_TYPE(graphicstring,primitive,GraphicString) 
+ASN1_STRING_TYPE(teletexstring,primitive,TeletexString) 
+ASN1_STRING_TYPE(t61string,primitive,T61String) 
+ASN1_STRING_TYPE(videotexstring,primitive,VideotexString) 
+ASN1_STRING_TYPE(objectdescriptor_string,primitive,ObjectDescriptor) 
+
+#undef ASN1_STRING_TYPE
+#undef ASN1_ABSTRACT_STRING_TYPE
+#undef ASN1_PRIMITIVE_TYPE
+#undef ASN1_CONSTRUCTED_TYPE
+#undef ASN1_TYPE
+#undef ASN1_CLASSFIELD_TYPE
diff --git a/adt/asn1_value.cpp b/adt/asn1_value.cpp
new file mode 100644 (file)
index 0000000..8fe27b6
--- /dev/null
@@ -0,0 +1,111 @@
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <list>
+#include "asn1_node.h"
+#include "asn1_reference.h"
+#include "asn1_value.h"
+#include "asn1_constraint.h"
+
+namespace asn1 {
+
+value::value(asn1::value::etype tp)
+  : type(tp) , m_ref(0) , m_constraint(NULL)
+{
+}
+
+value::value(const asn1::value &v)
+{
+}
+
+value::value( const std::string &_s)
+  : type(VT_STRING),m_string(_s),m_ref(0),m_constraint(NULL)
+{
+}
+value::value( const asn1::constraint *_c)
+ : m_ref(0),m_constraint(NULL)
+{
+  m_constraint = const_cast<asn1::constraint *>(_c);  
+}
+value::value( double _d)
+  : type(VT_REAL),m_real(_d) , m_ref(0), m_constraint(NULL)
+{
+}
+value::value( long _l)
+  : type(VT_INTEGER),m_integer(_l),m_ref(0),m_constraint(NULL)
+{
+}
+value::value( long long _l)
+  : type(VT_INTEGER),m_integer(_l),m_ref(0),m_constraint(NULL)
+{
+}
+
+value::~value()
+{
+}
+
+std::string 
+value::cpp_name() const
+{
+    switch (type)
+    {
+        case VT_TRUE:
+            return std::string("true");
+        case VT_FALSE:
+            return std::string("false");
+        case VT_MIN:
+            return std::string("MIN");
+        case VT_MAX:
+            return std::string("MAX");
+        case VT_STRING:
+            return m_string;
+        case VT_INTEGER:
+            {
+              std::ostringstream oss;
+              oss<<m_integer;
+              return oss.str();
+            }
+        case VT_REAL:
+            {
+              std::ostringstream oss;
+              oss<<m_real;
+              return oss.str();
+            }
+        case VT_COLON:
+            switch (m_node->type_id()())
+            {
+              case asn1::type::ASN1_OBJECT_IDENTIFIER:
+              {
+                std::ostringstream os;
+                asn1::object_identifier *oid = m_node->as_object_identifier();
+                os.str("");
+                os<<oid->hash();
+                return os.str();
+              }
+              case asn1::type::ASN1_INTEGER:
+                return m_node->cpp_name();
+              default:
+              {
+                std::ostringstream os;
+                os.str("");
+                os<<"<choice "<<m_node->cpp_name()<<" id="<<m_node->type_id()()<<">";
+                return os.str();
+              }
+            }
+        case VT_VALUESET:      /* {1 | 2 | 3 } */
+            // this shall be a constraint ....
+            if (m_constraint)
+            {
+                return m_constraint->name();
+            } else
+                return std::string("todo");
+        case VT_REFERENCED:    /* Reference a value elsewhere */
+            return m_reference->name();
+        default:
+            return std::string("unknown");
+            ;
+    };
+}
+
+};
diff --git a/adt/asn1_value.h b/adt/asn1_value.h
new file mode 100644 (file)
index 0000000..da7f5d6
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef ASN1_VALUE_H
+#define ASN1_VALUE_H
+#include "aeb/sys/log.h"
+#include "aeb/sys/log.h"
+#include "aeb/pointer/intrusive_ptr.h"
+
+namespace asn1 {
+// forward declaration
+  class constraint;
+  class reference; 
+  class node;
+struct value 
+{
+
+  public:
+    INTRUSIVE_DECLARATION(value)
+
+    enum etype {
+      VT_NOVALUE,
+      VT_TYPE,
+      VT_NULL,
+      VT_REAL,
+      VT_INTEGER,       /* an Integer */
+      VT_MIN,
+      VT_MAX,
+      VT_TRUE,
+      VT_FALSE,
+      VT_STRING,        /* "abcd" */
+      VT_BITVECTOR,     /* binary - hex string */
+      VT_COLON,         /* choice value ex local : value */
+      VT_VALUESET,      /* {1 | 2 | 3 } */
+      VT_SETVALUE,      /* { which list}  needs to be parser with the right type for assignement. Is Opaque */
+      VT_REFERENCED     /* Reference a value elsewhere */
+     
+    } type;
+    
+    value( asn1::value::etype tp = VT_NOVALUE);
+    value( const std::string &_s);
+    value( const asn1::constraint *_c);
+    value(const asn1::value &v);
+    value( double _d);
+    value( long _l);
+    value( long long _l);
+
+    ~value();
+    std::string cpp_name() const;
+    std::string     m_string;
+    long long       m_integer;
+    double          m_real;
+    asn1::reference  *m_reference;
+    asn1::constraint *m_constraint;
+    asn1::node       *m_node;
+};
+
+};
+
+/*
+  vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/adt/asn1_visitor.h b/adt/asn1_visitor.h
new file mode 100644 (file)
index 0000000..b0b4653
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef ASN1_VISITOR_H__
+#define ASN1_VISITOR_H__
+
+class node;
+class constraint;
+
+#ifdef DISPATCH
+#undef DISPATCH
+#endif
+template <typename Impl,typename RetTyp>
+class node_visitor_base
+{
+  public:
+    node_visitor_base() {};
+    virtual ~node_visitor_base() {};
+#define PTR(x) asn1::x *
+
+#define DISPATCH(NAME,CLASS,DEF) \
+  return static_cast<Impl *>(this)->visit_ ## NAME(static_cast<asn1::CLASS *>(n));    
+
+#define ASN1_TYPE(NAME,PARENT,DEF) \
+      case asn1::type::ASN1_##DEF  : DISPATCH(NAME,NAME,DEF) ;   
+
+#define ASN1_STRING_TYPE(NAME,PARENT,DEF) \
+      case asn1::type::ASN1_STRING_##DEF  : DISPATCH(NAME,NAME,DEF) ;   
+    
+    RetTyp visit(asn1::node *n)
+    {
+      switch (n->type_id()())
+      {
+#include "adt/asn1_type.inc"      
+        default:
+        ;
+      }
+    }
+    //  Default behavior is : If user does not implement a certain class
+    //  move to parent class
+#define ASN1_TYPE(NAME,PARENT,DEF) \
+    RetTyp visit_##NAME( PTR(NAME) n) \
+    {\
+      DISPATCH(PARENT,PARENT,DEF) ; \
+    }  
+
+#include "adt/asn1_type.inc"      
+    // Missing visitors
+    RetTyp visit_module(asn1::module *s) 
+    {
+      return RetTyp();
+    } 
+    RetTyp visit_typenode(asn1::typenode *s) 
+    {
+      return RetTyp();
+    } 
+    RetTyp visit_typeref(asn1::typeref *s) 
+    {
+      return RetTyp();
+    } 
+    //
+    RetTyp visit_primitive(asn1::primitive *s) 
+    {
+      return RetTyp();
+    } 
+    RetTyp visit_constructed(asn1::constructed *s) 
+    {
+      return RetTyp();
+    } 
+    RetTyp visit_node(asn1::node *s) 
+    {
+      return RetTyp();
+    } 
+};
+#undef DISPATCH
+template <typename Impl,typename RetTyp = void>
+class node_visitor : public node_visitor_base<Impl,RetTyp> {};
+
+/**
+ * Same for constraints
+ */ 
+template <typename Impl,typename RetTyp>
+class constraint_visitor_base
+{
+  public:
+    constraint_visitor_base() {};
+    virtual ~constraint_visitor_base() {};
+
+#define DISPATCH(DEF,NAME,CLASS) \
+  return static_cast<Impl *>(this)->visit_ ## NAME(static_cast<asn1::CLASS *>(n));    
+
+#define ELEMENT_CONSTRAINT(DEF,NAME,PARENT) \
+         case asn1::constraint::DEF  : DISPATCH(DEF,NAME,NAME) ;   
+    
+    RetTyp visit(asn1::constraint *n)
+    {
+      switch (n->type())
+      {
+#include "asn1_constraint.inc"      
+        default:
+        ;
+      }     
+    }
+    //  Default behavior is : If user does not implement a certain class
+    //  move to parent class
+#define ELEMENT_CONSTRAINT(DEF,NAME,PARENT) \
+    RetTyp visit_##NAME( PTR(NAME) n) \
+    {\
+      DISPATCH(DEF,PARENT,PARENT) ; \
+    }  
+
+#include "asn1_constraint.inc"      
+};
+
+template <typename Impl,typename RetTyp=void>
+class constraint_visitor : public constraint_visitor_base<Impl,RetTyp> {};
+
+
+/**
+ * And a Visitor for Assignments ...
+ */ 
+#undef DISPATCH
+template <typename Impl,typename RetTyp>
+class assignment_visitor_base
+{
+  public:
+    assignment_visitor_base() {};
+    virtual ~assignment_visitor_base() {};
+
+#define DISPATCH(DEF,NAME,CLASS) \
+  return static_cast<Impl *>(this)->visit_ ## NAME(static_cast<asn1::CLASS##_assignment *>(n));    
+
+#define DISPATCH1(DEF,NAME,CLASS) \
+  return static_cast<Impl *>(this)->visit_ ## NAME(static_cast<asn1::CLASS *>(n));    
+
+#define ASSIGNMENT(DEF,NAME,PARENT) \
+         case asn1::meta::DEF  : DISPATCH(DEF,NAME,NAME) ;   
+    
+    RetTyp visit(asn1::assignment *n)
+    {
+      switch (n->meta_id()())
+      {
+#include "asn1_meta.inc"      
+        default:
+        ;
+      }     
+    }
+    RetTyp visit_assignment(asn1::assignment *a)
+    {}
+    //  Default behavior is : If user does not implement a certain class
+    //  move to parent class
+#define ASSIGNMENT(DEF,NAME,PARENT) \
+    RetTyp visit_##NAME( PTR(NAME##_assignment) n) \
+    {\
+      DISPATCH1(DEF,PARENT,PARENT) ; \
+    }  
+
+#include "asn1_meta.inc"      
+};
+
+template <typename Impl,typename RetTyp=void>
+class assignment_visitor : public assignment_visitor_base<Impl,RetTyp> {};
+#undef DISPATCH
+#undef DISPATCH1
+
+
+#endif
diff --git a/cmip/CMIPActionListener.h b/cmip/CMIPActionListener.h
new file mode 100644 (file)
index 0000000..83efc63
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef CMIPACTIONLISTENER_H
+#define CMIPACTIONLISTENER_H
+
+class CMIPActionListener
+{
+};
+#endif /*CMIPACTIONLISTENER_H*/
diff --git a/cmip/CMIPAgent.cpp b/cmip/CMIPAgent.cpp
new file mode 100644 (file)
index 0000000..c6099ef
--- /dev/null
@@ -0,0 +1,151 @@
+#include <iostream>
+#include "Remote_Operations_Generic_ROS_PDUs.h"
+#include "CMIP_1.h"
+#include "CMIP_1.hpp"
+
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "CMIPListener.h"
+#include "CMIPActionListener.h"
+#include "CMIPEventReportListener.h"
+#include "CMIPStack.h"
+#include "CMIPAgent.h"
+
+using namespace CMIP_1;
+using namespace Remote_Operations_Generic_ROS_PDUs;
+using namespace Remote_Operations_Information_Objects;
+namespace rose_ie = Remote_Operations_Information_Objects;
+
+
+
+
+
+/**
+ *
+ */ 
+CMIPAgent::CMIPAgent(CMIPStack &cmip_stack)
+  : m_CMIPStack(cmip_stack)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  m_CMIPStack.registerListener(this);
+}
+
+/**
+ *
+ */ 
+CMIPAgent::~CMIPAgent()
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Create(CMIP_1::CreateArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Create(CMIP_1::CreateResult &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Delete(CMIP_1::DeleteArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Delete(CMIP_1::DeleteResult &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Get(CMIP_1::GetArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Get(CMIP_1::GetResult &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_CancelGet(CMIP_1::m_CancelGet &o) 
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Linked_Reply(CMIP_1::LinkedReplyArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Set(CMIP_1::SetArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Set_Confirmed(CMIP_1::SetArgument &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+/**
+ *
+ */ 
+void
+CMIPAgent::on_m_Set_Confirmed(CMIP_1::SetResult &o)
+{
+  std::cout<<"CMIPAgent::"<<__FUNCTION__<<std::endl;
+  o.printf(std::cout);
+}
+
+
diff --git a/cmip/CMIPAgent.h b/cmip/CMIPAgent.h
new file mode 100644 (file)
index 0000000..e3667c8
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef CMIP_AGENT_H__
+#define CMIP_AGENT_H__
+
+class CMIPStack;
+
+class CMIPAgent : public CMIPListener
+{
+  public:
+    CMIPAgent(CMIPStack &cmip_stack);
+
+    ~CMIPAgent();
+
+    virtual void on_m_Create(CMIP_1::CreateArgument &o)  ;
+    virtual void on_m_Create(CMIP_1::CreateResult &o)  ;
+    
+    virtual void on_m_Delete(CMIP_1::DeleteArgument &o)  ;
+    virtual void on_m_Delete(CMIP_1::DeleteResult &o)  ;
+    
+    virtual void on_m_Get(CMIP_1::GetArgument &o)  ;
+    virtual void on_m_Get(CMIP_1::GetResult &o)  ;
+    
+    virtual void on_m_CancelGet(CMIP_1::m_CancelGet &o)  ;
+    
+    virtual void on_m_Linked_Reply(CMIP_1::LinkedReplyArgument &o)  ;
+    
+    virtual void on_m_Set(CMIP_1::SetArgument &o)  ;
+    
+    virtual void on_m_Set_Confirmed(CMIP_1::SetArgument &o)  ;
+    virtual void on_m_Set_Confirmed(CMIP_1::SetResult &o)  ;
+   
+  protected:
+    CMIPStack &m_CMIPStack;
+};
+
+#endif
diff --git a/cmip/CMIPEventReportListener.h b/cmip/CMIPEventReportListener.h
new file mode 100644 (file)
index 0000000..3cb3200
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef CMIPEVENTREPORTLISTENER_H
+#define CMIPEVENTREPORTLISTENER_H
+
+/**
+ * @brief Interface that a class needs to implement in order
+ * to receive events from CMIP layer.
+ *
+ * Event Management might differ from current operation
+ *
+ */ 
+class CMIPEventReportListener
+{
+  public:  
+    CMIPEventReportListener();
+    
+    void on_m_EventReport(CMIP_1::m_EventReport &o);
+    
+    void on_m_EventReport_Confirmed(CMIP_1::m_EventReport_Confirmed &o);
+    
+
+  protected:
+};
+
+#endif /*CMIPEVENTREPORTLISTENER_H*/
diff --git a/cmip/CMIPListener.h b/cmip/CMIPListener.h
new file mode 100644 (file)
index 0000000..3953502
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef CMIPLISTENER_H
+#define CMIPLISTENER_H
+
+/**
+ *
+ */
+class CMIPListener
+{
+  public:  
+
+    CMIPListener() { } ;
+    
+    ~CMIPListener() { } ;
+
+
+    virtual void on_m_Create(CMIP_1::CreateArgument &o) { } ;
+    virtual void on_m_Create(CMIP_1::CreateResult &o) { } ;
+    
+    virtual void on_m_Delete(CMIP_1::DeleteArgument &o) { } ;
+    virtual void on_m_Delete(CMIP_1::DeleteResult &o) { } ;
+    
+    virtual void on_m_Get(CMIP_1::GetArgument &o) { } ;
+    virtual void on_m_Get(CMIP_1::GetResult &o) { } ;
+    
+    virtual void on_m_CancelGet(CMIP_1::m_CancelGet &o) { } ;
+    
+    virtual void on_m_Linked_Reply(CMIP_1::LinkedReplyArgument &o) { } ;
+    
+    virtual void on_m_Set(CMIP_1::SetArgument &o) { } ;
+    
+    virtual void on_m_Set_Confirmed(CMIP_1::SetArgument &o) { } ;
+    virtual void on_m_Set_Confirmed(CMIP_1::SetResult &o) { } ;
+  protected:
+
+};
+#endif /*CMIPLISTENER_H*/
diff --git a/cmip/CMIPStack.cpp b/cmip/CMIPStack.cpp
new file mode 100644 (file)
index 0000000..334a288
--- /dev/null
@@ -0,0 +1,374 @@
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+#include "Remote_Operations_Generic_ROS_PDUs.h"
+#include "CMIP_1.h"
+#include "CMIP_1.hpp"
+
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "CMIPListener.h"
+#include "CMIPActionListener.h"
+#include "CMIPEventReportListener.h"
+#include "CMIPStack.h"
+
+using namespace CMIP_1;
+using namespace Remote_Operations_Generic_ROS_PDUs;
+using namespace Remote_Operations_Information_Objects;
+namespace rose_ie = Remote_Operations_Information_Objects;
+
+
+
+CMIPStack::CMIPStack()
+{
+}
+
+/**
+ *
+ */ 
+void
+CMIPStack::registerListener(CMIPActionListener *a)
+{
+}
+
+/**
+ *
+ */ 
+void
+CMIPStack::registerListener(CMIPEventReportListener *a)
+{
+}
+
+/**
+ *
+ */ 
+void
+CMIPStack::registerListener(CMIPListener *a)
+{
+  m_Listeners.push_back(a);
+}
+
+
+/**
+ * Down stream methods
+ * {m-Action | m-Action-Confirmed | m-CancelGet | m-Create | m-Delete |
+ * m-EventReport | m-EventReport-Confirmed | m-Get | m-Linked-Reply | m-Set |
+ *  m-Set-Confirmed}
+ */
+void
+CMIPStack::send_m_Action(CMIP_1::m_Action &action)
+{
+  m_Ctx.reset();
+  ROS ros(ROS::typeof_invoke,asn1::tag(2,1));
+  // 
+  
+  Invoke &i = ros.get_invoke();
+  i.invokeId.get_present() = 8;
+  i.argument = &action;
+  i.opcode.set_tag(asn1::tag(0,2));  
+  i.opcode.get_local() = action.get_operationCode().get_local();  
+  std::cout<<std::setprecision(0);  
+  i.printf(std::cout);
+  ros.encode(m_Ctx); 
+  std::cout<<"\nSize  "<<m_Ctx.nb_read_bits()<<" bits"<<std::endl; 
+}
+
+
+void
+CMIPStack::send_m_Action_Confirmed(CMIP_1::m_Action_Confirmed &action)
+{
+}
+
+
+void
+CMIPStack::send_m_CancelGet(CMIP_1::m_CancelGet &o)
+{
+}
+
+
+void
+CMIPStack::send_m_Create(CMIP_1::m_Create &o)
+{
+}
+
+
+void
+CMIPStack::send_m_Delete(CMIP_1::m_Delete &o)
+{
+}
+
+
+void
+CMIPStack::send_m_EventReport(CMIP_1::m_EventReport &o)
+{
+}
+
+
+void
+CMIPStack::send_m_EventReport_Confirmed(CMIP_1::m_EventReport_Confirmed &o)
+{
+}
+
+
+void
+CMIPStack::send_m_Get(CMIP_1::m_Get &_get)
+{
+  m_Ctx.reset();
+  ROS ros(ROS::typeof_invoke,asn1::tag(2,1));
+  // 
+  
+  Invoke &i = ros.get_invoke();
+  i.invokeId.get_present() = 8;
+  i.argument = &_get;
+  i.opcode.set_local( _get.get_operationCode().get_local());  
+  std::cout<<std::setprecision(0);  
+  i.printf(std::cout);
+  ros.encode(m_Ctx); 
+  std::cout<<"\n"<<__FUNCTION__;
+  std::cout<<" Size  "<<m_Ctx.nb_read_bits()<<" bits"<<std::endl; 
+  // Trye decode
+  m_Ctx.reset();
+  onReceive(m_Ctx);
+}
+
+
+void
+CMIPStack::send_m_Linked_Reply(CMIP_1::m_Linked_Reply &o)
+{
+}
+
+
+void
+CMIPStack::send_m_Set(CMIP_1::m_Set &_set)
+{
+  ROS ros(ROS::typeof_invoke,asn1::tag(2,1));
+  // 
+  m_Ctx.reset();
+  Invoke &i = ros.get_invoke();
+  i.invokeId.get_present() = 8;
+  i.argument = &_set;
+  i.opcode.set_local( _set.get_operationCode().get_local());  
+  std::cout<<std::setprecision(0);  
+  i.printf(std::cout);
+  ros.encode(m_Ctx); 
+  std::cout<<"\n"<<__FUNCTION__;
+  std::cout<<" Size  "<<m_Ctx.nb_read_bits()<<" bits"<<std::endl; 
+}
+
+
+void
+CMIPStack::send_m_Set_Confirmed(CMIP_1::m_Set_Confirmed &_set)
+{
+  m_Ctx.reset();
+  ROS ros(ROS::typeof_invoke,asn1::tag(2,1));
+  // 
+  
+  Invoke &i = ros.get_invoke();
+  i.invokeId.get_present() = 8;
+  i.argument = &_set;
+  i.opcode.set_local( _set.get_operationCode().get_local());  
+  std::cout<<std::setprecision(0);  
+  i.printf(std::cout);
+  ros.encode(m_Ctx); 
+  std::cout<<"\n"<<__FUNCTION__;
+  std::cout<<" Size  "<<m_Ctx.nb_read_bits()<<" bits"<<std::endl; 
+}
+
+void
+CMIPStack::doInvoke(rose_pdu::Invoke &i)
+{
+  assert(i.opcode.get_kind() == Code::typeof_local);
+  std::cout<<"CMIPStack::"<<__FUNCTION__;
+  std::cout<<" got "<<i.opcode.get_local()<<"\n";
+  switch (i.opcode.get_local().get_sys_value())
+  {
+    case opEvent:
+    {
+      CMIP_1::m_EventReport *o 
+        = static_cast<CMIP_1::m_EventReport *>(*(i.argument));
+    }
+    break;
+    case opEventConfirm  :
+    break;
+    case opLinkedReply   :
+    break;
+    case opGet           :
+    {
+      struct doGet {
+        doGet(CMIP_1::GetArgument &a) : m_arg(a) {};
+        void operator ()(CMIPListener *l)
+        { l->on_m_Get(m_arg);}
+        CMIP_1::GetArgument &m_arg;
+      };
+      CMIP_1::m_Get *o 
+        = static_cast<CMIP_1::m_Get *>(*(i.argument));
+      std::cout<<"CMIPStack::"<<__FUNCTION__;
+      std::cout<<" process  GET"<<"\n";
+      std::for_each(m_Listeners.begin()
+                   , m_Listeners.end()
+                   , doGet(o->get_ArgumentType())
+                    );
+      std::cout<<" END process  GET"<<"\n";
+    }
+    break;
+    case opSet           :
+    {
+      CMIP_1::m_Set *o 
+        = static_cast<CMIP_1::m_Set *>(*(i.argument));
+    }
+    break;
+    case opSetConfirm    :
+    {
+      CMIP_1::m_Set_Confirmed *o 
+        = static_cast<CMIP_1::m_Set_Confirmed *>(*(i.argument));
+    }
+    break;
+    case opAction        :
+    {
+      CMIP_1::m_Action *o 
+        = static_cast<CMIP_1::m_Action *>(*(i.argument));
+    }
+    break;
+    case opActionConfirm :
+    break;
+    case opCreate        :
+    {
+      CMIP_1::m_Create *o 
+        = static_cast<CMIP_1::m_Create *>(*(i.argument));
+    }
+    break;
+    case opDelete        :
+    {
+      CMIP_1::m_Delete *o 
+        = static_cast<CMIP_1::m_Delete *>(*(i.argument));
+    }
+    break;
+    case opCancelGet     :
+    break;
+    default:
+    ;
+  }
+}
+
+void
+CMIPStack::doReturnResult(rose_pdu::ReturnResult &r)
+{
+  if (r.bit_mask.test(rose_pdu::ReturnResult::result_present))
+  {
+    assert(r.result->opcode.get_kind() == Code::typeof_local);
+    std::cout<<"CMIPStack::"<<__FUNCTION__;
+    std::cout<<" got "<<r.result->opcode.get_local()<<"\n";
+    rose_pdu::ReturnResult_result *result = *r.result;
+    switch (result->opcode.get_local().get_sys_value())
+    {
+      case opEvent:
+      {
+        CMIP_1::m_EventReport *o 
+          = static_cast<CMIP_1::m_EventReport *>(*(result->result));
+      }
+      break;
+      case opEventConfirm  :
+      break;
+      case opLinkedReply   :
+      break;
+      case opGet           :
+      {
+        CMIP_1::m_Get *o 
+          = static_cast<CMIP_1::m_Get *>(*(result->result));
+        std::cout<<"CMIPStack::"<<__FUNCTION__;
+        std::cout<<" process  GET"<<"\n";
+        o->printf(std::cout);
+        std::cout<<" END process  GET"<<"\n";
+
+      }
+      break;
+      case opSet           :
+      {
+        CMIP_1::m_Set *o 
+          = static_cast<CMIP_1::m_Set *>(*(result->result));
+      }
+      break;
+      case opSetConfirm    :
+      {
+        CMIP_1::m_Set_Confirmed *o 
+          = static_cast<CMIP_1::m_Set_Confirmed *>(*(result->result));
+      }
+      break;
+      case opAction        :
+      {
+        CMIP_1::m_Action *o 
+          = static_cast<CMIP_1::m_Action *>(*(result->result));
+      }
+      break;
+      case opActionConfirm :
+      break;
+      case opCreate        :
+      {
+        CMIP_1::m_Create *o 
+          = static_cast<CMIP_1::m_Create *>(*(result->result));
+      }
+      break;
+      case opDelete        :
+      {
+        CMIP_1::m_Delete *o 
+          = static_cast<CMIP_1::m_Delete *>(*result->result);
+      }
+      break;
+      case opCancelGet     :
+      break;
+      default:
+      ;
+    }
+  } else 
+  {
+    std::cout<<"CMIPStack::"<<__FUNCTION__;
+    std::cout<<" got "<<"no result"<<"\n";
+  }
+}
+
+void
+CMIPStack::doReturnError(rose_pdu::ReturnError &re)
+{
+  std::cout<<"CMIPStack::"<<__FUNCTION__;
+  std::cout<<" TODO "<<"no result"<<"\n";
+}
+
+void
+CMIPStack::doReject(rose_pdu::Reject &r)
+{
+  std::cout<<"CMIPStack::"<<__FUNCTION__;
+  std::cout<<" TODO "<<"no result"<<"\n";
+}
+
+namespace CMIP_1 {
+extern rose_ie::IOPERATION *CMIP_Operations[];
+}
+// Handle receive data from lower layer
+void
+CMIPStack::onReceive(asn1::streams::ber &ctx)
+{
+  //::asn1::types::debug_level = 8;  
+  ROS ros;
+  ros.Invokable = CMIP_1::CMIP_Operations;
+  int result = ros.decode(ctx);
+  switch (ros.get_kind())
+  {
+    case ROS::typeof_invoke:
+      doInvoke(ros.get_invoke());
+    break;
+    case ROS::typeof_returnResult:
+      doReturnResult(ros.get_returnResult());
+    break;
+    case ROS::typeof_returnError:
+      doReturnError(ros.get_returnError());
+    break;
+    case ROS::typeof_reject:
+      doReject(ros.get_reject());
+    break;
+    default:
+      std::cerr<<"CMIPStack::"<<__FUNCTION__<<" Big Issue\n";
+    ;
+  }
+}
+
diff --git a/cmip/CMIPStack.h b/cmip/CMIPStack.h
new file mode 100644 (file)
index 0000000..1e2049f
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef CMIPSTACK_H
+#define CMIPSTACK_H
+
+namespace rose_pdu = Remote_Operations_Generic_ROS_PDUs;
+/**
+ * @brief Public interface for the CMIP Stack
+ *  Basicallly, the class allows sending data to lower 
+ *  and receive data from the lower layer.
+ *   The layer below CMIP is ACSE / STASE The sub layer
+ *   is responsible for association and authentication and so on
+ *   Thus the stack should implement a Listener interface of 
+ *   the underneth Stack ACSE
+ */ 
+class CMIPStack
+{
+  public:
+    // Operations
+    enum {
+        opEvent         = 0
+      , opEventConfirm  = 1
+      , opLinkedReply   = 2
+      , opGet           = 3
+      , opSet           = 4
+      , opSetConfirm    = 5
+      , opAction        = 6
+      , opActionConfirm = 7
+      , opCreate        = 8
+      , opDelete        = 9
+      , opCancelGet     = 10
+    };
+
+  public:
+    typedef std::list<CMIPActionListener *>      ActionListenerList;
+    typedef std::list<CMIPEventReportListener *> EventReportListenerList;
+    typedef std::list<CMIPListener *>            ListenerList;
+    // Above Rose... And Stase
+    //
+    CMIPStack();
+    /**
+     *
+     */ 
+    void registerListener(CMIPActionListener *a);
+    /**
+     *
+     */ 
+    void registerListener(CMIPEventReportListener *a);
+    /**
+     *
+     */ 
+    void registerListener(CMIPListener *a);
+
+    /**
+     * Down stream methods
+     * {m-Action | m-Action-Confirmed | m-CancelGet | m-Create | m-Delete |
+     * m-EventReport | m-EventReport-Confirmed | m-Get | m-Linked-Reply | m-Set |
+     *  m-Set-Confirmed}
+     */
+    void send_m_Action(CMIP_1::m_Action &o);
+    
+    void send_m_Action_Confirmed(CMIP_1::m_Action_Confirmed &o);
+    
+    void send_m_CancelGet(CMIP_1::m_CancelGet &o);
+    
+    void send_m_Create(CMIP_1::m_Create &o);
+    
+    void send_m_Delete(CMIP_1::m_Delete &o);
+    
+    void send_m_EventReport(CMIP_1::m_EventReport &o);
+    
+    void send_m_EventReport_Confirmed(CMIP_1::m_EventReport_Confirmed &o);
+    
+    void send_m_Get(CMIP_1::m_Get &o);
+    
+    void send_m_Linked_Reply(CMIP_1::m_Linked_Reply &o);
+    
+    void send_m_Set(CMIP_1::m_Set &o);
+    
+    void send_m_Set_Confirmed(CMIP_1::m_Set_Confirmed &o);
+    // Handle receive data from lower layer
+    void onReceive(asn1::streams::ber &ctx);
+  protected:
+    asn1::streams::ber m_Ctx;
+    ListenerList      m_Listeners;
+
+    void doInvoke(rose_pdu::Invoke &i);
+    void doReturnResult(rose_pdu::ReturnResult &rr);
+    void doReturnError(rose_pdu::ReturnError &re);
+    void doReject(rose_pdu::Reject &r);
+};
+
+/*
+ * vi:et sw=2 ts=2:
+ */ 
+#endif
diff --git a/cmip/CMakeLists.txt b/cmip/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9b54d8f
--- /dev/null
@@ -0,0 +1,164 @@
+PROJECT(cmip-lib)
+
+
+ADD_DEFINITIONS(-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER)
+
+IF (WITH_CMIP)
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt CMIPMODULES)
+SET(CMIP_ASN1P ${CMAKE_CURRENT_BINARY_DIR}/../asn1p)
+SET(CMIP_ERULE "-e ber")
+FOREACH(ITEM ${CMIPMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+ SET(CMIPSRC ${CMIPSRC} ${ITEM}.cpp)
+ SET(CMIPHDR ${CMIPHDR} ${HITEM}.h)
+ENDFOREACH(ITEM)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMIPSRC} ${CMIPHDR}"
+    )
+
+SET(ROSE_PARSER_INC -n false -I ${asn1-data-models_SOURCE_DIR}/) 
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_INC} -fRemote-Operations-Generic-ROS-PDUs.asn1)
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_OPT} -fRemote-Operations-Information-Objects.asn1)
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_OPT}
+    -fRemote-Operations-Useful-Definitions.asn1)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+#
+#Remote-Operations-Generic-ROS-PDUs {joint-iso-itu-t remote-operations(4)
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Generic_ROS_PDUs.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp 
+    COMMAND ${CMIP_ASN1P}
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Generic-ROS-PDUs
+    DEPENDS ${CMIP_ASN1P}
+    COMMENT "Build Remote-Operations-Generic-ROS-PDUs .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Useful_Definitions.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.cpp 
+    COMMAND ${CMIP_ASN1P}
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Useful-Definitions
+    DEPENDS ${CMIP_ASN1P}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp
+    COMMENT "Build Remote-Operations-Usful-Definitions .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${CMIP_ASN1P}
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Information-Objects
+    DEPENDS ${CMIP_ASN1P}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.cpp
+    COMMENT "Build Remote-Operations-Informations-Objects .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h
+    GENERATED)
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CMIP_1.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/CMIP-1.cpp 
+    COMMAND ${CMIP_ASN1P}
+
+    ARGS ${ROSE_PARSER_OPT} -o CMIP-1
+      -f CMIP-1.asn1
+    DEPENDS ${CMIP_ASN1P}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMENT "Build CMIP-1 .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE-1.cpp 
+    COMMAND ${CMIP_ASN1P}
+
+    ARGS ${ROSE_PARSER_OPT} -o ACSE-1
+      -f cstav1/apdu_acse.asn1
+    DEPENDS ${CMIP_ASN1P}
+    COMMENT "Build ACSE-1 .h and .cpp"
+    )
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/ACSE-1.cpp
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/ACSE-1.cpp
+     COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+# Attribute-ASN1Module
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/Attribute_ASN1Module.h 
+    ${CMAKE_CURRENT_BINARY_DIR}/Attribute-ASN1Module.cpp 
+    COMMAND ${CMIP_ASN1P}
+
+    ARGS ${ROSE_PARSER_OPT} -o Attribute-ASN1Module
+      -f cstav1/apdu_acse.asn1
+      -f cmip/Attribute-ASN1Module.asn1
+      -f CMIP-1.asn1
+    DEPENDS ${CMIP_ASN1P}
+    COMMENT "Build Attribute-ASN1Module .h and .cpp"
+    )
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Attribute-ASN1Module.cpp
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Attribute-ASN1Module.cpp
+     COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/X721.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/X721.hpp 
+      ${CMAKE_CURRENT_BINARY_DIR}/X721.cpp 
+    COMMAND ${CMIP_ASN1P}
+
+    ARGS ${ROSE_PARSER_OPT} -o X721
+      -f cmip/x721-gdmo.asn1
+      -f cmip/Attribute-ASN1Module.asn1
+      -f CMIP-1.asn1
+      -f x227/ACSE-1.asn1
+    DEPENDS ${CMIP_ASN1P}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+      ${CMAKE_CURRENT_BINARY_DIR}/Attribute-ASN1Module.cpp 
+    COMMENT "Build X721 .h and .cpp from x721-gdmo.asn1"
+    )
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/X721.hpp
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/X721.cpp
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/X721.cpp
+     COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+
+ADD_LIBRARY(cmip
+      ${CMAKE_CURRENT_BINARY_DIR}/X721.hpp
+      ${CMIPSRC}
+    )
+
+ADD_EXECUTABLE( test_cmip
+    X721.cpp
+    Attribute-ASN1Module.cpp
+    ACSE-1.cpp
+    CMIPStack.cpp
+    CMIPAgent.cpp
+    main.cpp
+    )
+TARGET_LINK_LIBRARIES(test_cmip cmip asn1)
+ENDIF(WITH_CMIP)
diff --git a/cmip/main.cpp b/cmip/main.cpp
new file mode 100644 (file)
index 0000000..f3cc06e
--- /dev/null
@@ -0,0 +1,210 @@
+#include <iostream>
+
+#include "Remote_Operations_Generic_ROS_PDUs.h"
+#include "CMIP_1.h"
+#include "CMIP_1.hpp"
+
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "CMIPListener.h"
+#include "CMIPActionListener.h"
+#include "CMIPEventReportListener.h"
+#include "CMIPStack.h"
+#include "CMIPAgent.h"
+
+#include "Attribute_ASN1Module.h"
+#include "X721.h"
+#include "X721.hpp"
+using namespace CMIP_1;
+using namespace Remote_Operations_Generic_ROS_PDUs;
+using namespace Remote_Operations_Information_Objects;
+
+void test1()
+{
+  std::cerr<<"\n*\n* test CODE\n*"<<std::endl; 
+  Code c(Code::typeof_local);
+  c.get_local() = 1;
+  c.printf(std::cout);
+  std::cout<<"\n";
+}
+void test2()
+{
+  std::cerr<<"\n*\n* test Invoke\n*"<<std::endl;       
+  Invoke i;
+  i.invokeId.set_tag(asn1::tag(0,2));  
+  i.invokeId.get_present() = 4;
+  i.opcode.set_tag(asn1::tag(0,2));  
+  i.opcode.get_local() = 1;  
+  i.printf(std::cout);
+  std::cout<<std::endl;
+}
+
+void test3()
+{
+  asn1::streams::ber ctx;
+  std::cerr<<"\n*\n* test ROS\n*"<<std::endl;  
+  ActionArgument aaa;
+  ROS ros(ROS::typeof_invoke,asn1::tag(2,1));
+  m_Action *a = new m_Action();
+  // 
+  aaa.baseManagedObjectClass.set_tag(asn1::tag(2,0));
+  aaa.baseManagedObjectClass.get_globalForm() = OBJECT_IDENTIFIER(2,"\x2a\x32");
+  
+  a->set_ArgumentType(aaa);
+  Invoke &i = ros.get_invoke();
+  i.invokeId.get_present() = 8;
+  i.argument = a;
+  i.opcode.set_tag(asn1::tag(0,2));  
+  i.opcode.get_local() = 7;  
+  std::cout<<std::setprecision(0);  
+  i.printf(std::cout);
+  ros.encode(ctx); 
+  std::cout<<"\nSize  "<<ctx.nb_read_bits()<<" bits"<<std::endl; 
+}
+
+
+void test4()
+{
+  std::cerr<<"\n*\n* test ComplexityLimitation\n*"<<std::endl; 
+  ComplexityLimitation cl;
+  cl.scope = new Scope();
+  cl.filter = new CMISFilter();
+  // Set Filter to use
+  //cl.filter->set_tag(asn1::tag(2,CMISFilter::typeof_item));
+  cl.filter->set_tag(asn1::tag(2,8));
+  FilterItem &item = cl.filter->get_item();
+  item.set_tag(asn1::tag(2,FilterItem::typeof_equality));
+  
+  Attribute &attr = item.get_equality();
+  X721::systemId *sid = new X721::systemId();
+  attr.id.set_globalForm( sid->get_id().get_globalForm()); 
+  sid->get_Value().set_number(asn1::INTEGER(3));
+  attr.value = sid;
+  cl.scope->get_namedNumbers() = 403;
+
+  std::cout<<std::setprecision(0)<<cl<<std::endl;  
+}
+
+void test5()
+{
+  asn1::streams::ber ctx;
+  std::cout<<"\n*\n* test m-Get\n*"<<std::endl;        
+  GetArgument getArgument;
+  getArgument.baseManagedObjectClass.set_globalForm( OBJECT_IDENTIFIER(2,"\x2a\x32"));
+  //getArgument.baseManagedObjectInstance.set_nonSpecificForm(OCTET_STRING("test_obj"));
+  getArgument.baseManagedObjectInstance.set_nonSpecificForm("test_obj");
+  getArgument.attributeIdList = new GetArgument_attributeIdList();
+  AttributeId ai;
+  
+  ai.set_localForm(asn1::INTEGER(8));
+  getArgument.attributeIdList->push_back(ai);
+
+  ai.get_localForm() = 28;
+  getArgument.attributeIdList->push_back(ai);  
+  
+  ai.set_globalForm( OBJECT_IDENTIFIER(4,"\x2a\x14\x23\x41"));
+  getArgument.attributeIdList->push_back(ai);  
+  
+  m_Get *get = new m_Get();
+  // 
+  getArgument.baseManagedObjectClass.set_globalForm( 
+         OBJECT_IDENTIFIER(5,"\x2a\x32\x12\x35\x12"));
+  
+  get->set_ArgumentType(getArgument);
+  
+  CMIPStack stack;
+  CMIPAgent agent(stack);
+  stack.send_m_Get(*get);
+}
+
+void test6()
+{
+  std::cout<<"\n*\n* test CMIPStack "<<__FUNCTION__<<"\n*"<<std::endl;
+  ActionArgument aaa;
+  m_Action::ptr a = new m_Action();
+  // Both work 
+  aaa.baseManagedObjectClass.set_globalForm( OBJECT_IDENTIFIER(2,"\x2a\x32"));
+  aaa.scope = new Scope();
+  //aaa.filter = new CMISFilter(asn1::tag(2,CMISFilter::typeof_item));
+  aaa.filter = new CMISFilter(asn1::tag(2,8));
+  aaa.filter->set_tag(asn1::tag(2,8)); // Way is this required ?
+  FilterItem &item = aaa.filter->get_item();
+  //item.set_tag(asn1::tag(2,FilterItem::typeof_equality));
+  item.set_tag(asn1::tag(2,0));
+  Attribute &attr = item.get_equality();
+  attr.id.set_tag(asn1::tag(2,2));
+  X721::pdusSentCounter *pdusS  = new X721::pdusSentCounter();
+  pdusS->get_Value() = 23;
+  attr.id.set_globalForm( pdusS->get_id().get_globalForm()); 
+  attr.value = pdusS;
+
+  aaa.scope->get_namedNumbers() = 404;
+
+  a->set_ArgumentType(aaa);
+  CMIPStack stack;
+  stack.send_m_Action(**a);
+}
+
+void test7()
+{
+  std::cout<<"\n*\n* test CMIPStack "<<__FUNCTION__<<"\n*"<<std::endl; 
+  SetArgument setA;
+  m_Set::ptr a = new m_Set();
+  setA.baseManagedObjectInstance.set_nonSpecificForm(OCTET_STRING("test_obj"));
+  setA.baseManagedObjectClass.set_globalForm( OBJECT_IDENTIFIER(2,"\x2a\x32"));
+  setA.scope = new Scope();
+#define UF 0
+#if UF
+  // Attention witout bit_mask value is not encoded
+  setA.bit_mask.set(SetArgument::filter_present);
+  setA.filter = new CMISFilter(asn1::tag(2,8));
+  setA.filter->set_tag(asn1::tag(2,8)); // Why is this required ?
+  FilterItem &item = setA.filter->get_item();
+  item.set_tag(asn1::tag(2,0));
+
+  Attribute &attr = item.get_equality();
+  attr.id.set_tag(asn1::tag(2,2));
+#endif
+  X721::pdusSentCounter *pdusS  = new X721::pdusSentCounter();
+  pdusS->get_Value() = 25;
+#if UF
+  attr.id.set_globalForm( pdusS->get_id().get_globalForm()); 
+  attr.value = pdusS;
+#endif
+  setA.scope->get_namedNumbers() = 407;
+  // 
+#if 1
+  SetArgument_modificationList_type sa_mlt;
+  sa_mlt.attributeId.set_globalForm( pdusS->get_id().get_globalForm()); 
+  sa_mlt.attributeValue = pdusS;
+  setA.modificationList.push_back(sa_mlt);
+  // Add another attribute
+  X721::systemId *sid = new X721::systemId();
+  sid->get_Value().set_number(asn1::INTEGER(9));
+  sa_mlt.attributeId.set_globalForm( sid->get_id().get_globalForm()); 
+  sa_mlt.attributeValue = sid;
+  setA.modificationList.push_back(sa_mlt);
+#endif
+  a->set_ArgumentType(setA);
+  CMIPStack stack;
+  stack.send_m_Set(**a);
+}
+
+
+
+int main(int argc,char **argv)
+{
+  asn1::INTEGER op(1);
+  ::asn1::types::debug_level = 1;  
+  std::cout<<"main get_local"<<std::endl;  
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  test7();
+  std::cout<<"END"<<std::endl;  
+  std::cout<<std::endl;
+}
diff --git a/cmip/modules.txt b/cmip/modules.txt
new file mode 100644 (file)
index 0000000..6518df5
--- /dev/null
@@ -0,0 +1,4 @@
+CMIP-1
+Remote-Operations-Generic-ROS-PDUs
+Remote-Operations-Useful-Definitions
+Remote-Operations-Information-Objects
diff --git a/csta/CMakeLists.txt b/csta/CMakeLists.txt
new file mode 100644 (file)
index 0000000..744c8f8
--- /dev/null
@@ -0,0 +1,100 @@
+PROJECT(csta-lib)
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt CSTAMODULES)
+
+FOREACH(ITEM ${CSTAMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(CSTASRC ${CSTASRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(CSTAHDR ${CSTAHDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+
+  ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp
+    ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h
+    ${CMAKE_CURRENT_BINARY_DIR}
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS 
+    -I ${CMAKE_CURRENT_SOURCE_DIR}/../../data-models/
+    -f ecma-285.asn1
+    -f cstav2/ecma-218.asn1
+    -f cstav1/Remote-Operations-Information-Objects.asn1
+    -o ${ITEM} 
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+      COMMENT "Build ${ITEM} .h and .cpp"
+    )
+
+
+
+
+ENDFOREACH(ITEM)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CSTASRC} ${CSTAHDR}"
+    )
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+IF (WITH_CSTA)
+# ${CMAKE_CURRENT_SOURCE_DIR}/../../../data-models/asn1/Remote-Operations-Information-Objects.asn1
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Generic_ROS_PDUs.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp 
+    COMMAND cat
+      ${CMAKE_CURRENT_SOURCE_DIR}/../../../data-models/asn1/Remote-Operations-Information-Objects.asn1
+    ${CMAKE_CURRENT_SOURCE_DIR}/../../../data-models/asn1/Remote-Operations-Generic-ROS-PDUs.asn1
+    ARGS | ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build ROI .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Useful_Definitions.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.cpp 
+    COMMAND cat
+    ${CMAKE_CURRENT_SOURCE_DIR}/../../../data-models/asn1/Remote-Operations-Useful-Definitions.asn1
+    ARGS | ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build ROI .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS 
+      -I ${asn1-data-models_SOURCE_DIR}/
+      -f cstav1/Remote-Operations-Information-Objects.asn1
+      -o Remote-Operations-Information-Objects
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build ROI .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp
+    GENERATED)
+
+ADD_LIBRARY(csta
+      ${CSTASRC}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    )
+
+ADD_EXECUTABLE(test_csta
+    main.cpp
+    )
+
+TARGET_LINK_LIBRARIES(test_csta csta asn1)
+
+ENDIF(WITH_CSTA)
diff --git a/csta/main.cpp b/csta/main.cpp
new file mode 100644 (file)
index 0000000..624e681
--- /dev/null
@@ -0,0 +1,83 @@
+
+#include <iostream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "CSTA_event_report_definitions.h"
+#include "CSTA_event_report_definitions.hpp"
+
+/**
+CSTAEventReportArgument ::= SEQUENCE {
+  crossRefIdentifier MonitorCorssRefID
+  eventSpecificInfo  EventSpecificInfo
+}
+ *
+EventSpecificInfo ::= CHOICE {
+  callControlEvent [0] CallcontrolEvents,
+
+}
+ *
+ConnectionID ::= [APPLICATION 11] CHOICE {
+  callID [0] IMPLICIT CallID,
+  deviceID [1] LocalDeviceID,
+  both SEQUENCE {
+    callID [0] IMPLICIT CallID,
+    deviceID [1] LocalDeviceID
+  }
+}
+
+CallID ::= OCTET STRING
+LocalDeviceID ::= CHOICE [
+  staticID DeviceID
+  dynamicID [3] IMPLICIT OCTET STRING
+}
+
+DeviceID ::= SEQUENCE {
+  deviceIdentifier CHOICE {
+  }
+}
+ */
+
+int test_decode()
+{
+  /* This sequence is for Alcatel CSTA which is not compatible with the ecma
+   * 285 description. Just  forget it. Events are described diferently*/
+  const unsigned char d[] ={ 0x30,0x46,
+        0x55,0x04,0x00,0x00,0x00,0x04,
+        0x80,0x01,0x0d, // For alcated, this Event Type 13 
+        //Context Specific - Primitive - Id=0 tag. Len 1 - value 0d 13 what is this ?
+        0x30,0x1d, /* OriginatedEvent SEQUENCE len 0x1d  29*/
+                0x6b,0x0a, /* ConnectionID tag APPL 11 len 10 CHOICE*/
+                     0x82,0x02,0x00,0x76, /* This should be both of ConnectionID*/
+                     0x83,0x04,0x00, 0x03,0x00,0x00, /* supposed to be dynamic ID*/
+                     /**  
+                                                                    SubjectDeviceID is (APPLICATION 3 Choice)
+                                                                    CalledDeviceID  is (APPLICATION 2 Choice)
+
+                                                                 */
+        0x4e,0x01,0x01,  /* State initated */
+        0x0a,0x01, 0x16, /* Event Cause newCall*/
+        /* I d'ont know what this is  PRIVATE data */
+        0x63,0x05,0x84,0x03,0x31,0x30,0x32, /* loocks like  SubjectDeviceID */
+        0x62,0x02,0x87,0x00}; /* looks like CalledDeviceID*/
+  
+  CSTA_event_report_definitions::cSTAEventReport report; 
+  asn1::context ctx;
+  memcpy(ctx.buffer(),d,41);
+  report.decode(ctx);
+
+}
+
+int main(int argc,char **argv)
+{
+
+  CSTA_event_report_definitions::cSTAEventReport report; 
+  //asn1::context ctx;
+  test_decode();
+  //report.codec(ctx,asn1::CODEC_ENCODE);
+  std::cout<<"Hello world"<<std::endl;
+}
diff --git a/csta/modules.txt b/csta/modules.txt
new file mode 100644 (file)
index 0000000..7c95b21
--- /dev/null
@@ -0,0 +1,266 @@
+CSTA-accept-call
+CSTA-activate
+CSTA-agent-busy-event
+CSTA-agent-logged-off-event
+CSTA-agent-logged-on-event
+CSTA-agent-not-ready-event
+CSTA-agent-ready-event
+CSTA-agent-working-after-call-event
+CSTA-alternate-call
+CSTA-answer-call
+CSTA-application-context-information-csta3
+CSTA-application-context-information
+CSTA-associate-data
+CSTA-attach-media-service
+CSTA-auto-answer-event
+CSTA-auto-work-mode-event
+CSTA-back-in-service-event
+CSTA-bookmark-reached-event
+CSTA-bridged-event
+CSTA-button-information-event
+CSTA-button-press-event
+CSTA-button-press
+CSTA-call-back-call-related
+CSTA-call-back-event
+CSTA-call-back-message-call-related
+CSTA-call-back-message-event
+CSTA-call-back-message-non-call-related
+CSTA-call-back-non-call-related
+CSTA-call-cleared-event
+CSTA-call-connection-identifiers
+CSTA-call-control
+CSTA-call-detail-record
+CSTA-call-detail-records-notification
+CSTA-call-detail-records-report
+CSTA-call-information-event
+CSTA-caller-id-status-event
+CSTA-camp-on-call
+CSTA-cancel-call-back-message
+CSTA-cancel-call-back
+CSTA-cancel-telephony-tones
+CSTA-capability-exchange
+CSTA-change-connection-information
+CSTA-change-monitor-filter
+CSTA-change-system-status-filter
+CSTA-charge-info
+CSTA-charging-event
+CSTA-clear-call
+CSTA-clear-connection
+CSTA-clear
+CSTA-completed-event
+CSTA-concatenate-message
+CSTA-conference-call
+CSTA-conferenced-event
+CSTA-connection-cleared-event
+CSTA-connection-states
+CSTA-consultation-call
+CSTA-data-call-types
+CSTA-data-collected
+CSTA-data-collection-resumed
+CSTA-data-collection-suspended
+CSTA-data-collection
+CSTA-data-path-resumed
+CSTA-data-path-suspended
+CSTA-deactivate
+CSTA-deflect-call
+CSTA-delete-message
+CSTA-delivered-event
+CSTA-detach-media-service
+CSTA-device-capabilities-changed-event
+CSTA-device-feature-types
+CSTA-device-identifiers
+CSTA-dial-digits
+CSTA-digits-dialed-event
+CSTA-digits-generated-event
+CSTA-directed-pickup-call
+CSTA-display-updated-event
+CSTA-diverted-event
+CSTA-do-not-disturb-event
+CSTA-dtmf-detected-event
+CSTA-emptied-event
+CSTA-error-definition
+CSTA-escape-register-abort
+CSTA-escape-register-cancel
+CSTA-escape-register
+CSTA-escape-service
+CSTA-escape-types
+CSTA-established-event
+CSTA-event-causes
+CSTA-event-report-definitions
+CSTA-extension-types
+CSTA-failed-event
+CSTA-fast-data
+CSTA-forwarding-event
+CSTA-generate-digits
+CSTA-generate-telephony-tones
+CSTA-get-agent-state
+CSTA-get-auditory-apparatus-information
+CSTA-get-auto-answer
+CSTA-get-auto-work-mode
+CSTA-get-button-information
+CSTA-get-call-back
+CSTA-get-caller-id-status
+CSTA-get-csta-features-service
+CSTA-get-display
+CSTA-get-do-not-disturb
+CSTA-get-forwarding
+CSTA-get-hookswitch-status
+CSTA-get-lamp-information
+CSTA-get-lamp-mode
+CSTA-get-last-number-dialed
+CSTA-get-location-information
+CSTA-get-location-tracking-capabilities
+CSTA-get-location-tracking-sessions
+CSTA-get-logical-device-information
+CSTA-get-message-waiting-indicator
+CSTA-get-microphone-gain
+CSTA-get-microphone-mute
+CSTA-get-monitor
+CSTA-get-physical-device-information
+CSTA-get-registrations
+CSTA-get-ringer-status
+CSTA-get-routeing-mode
+CSTA-get-speaker-mute
+CSTA-get-speaker-volume
+CSTA-get-switching-function-capabilities
+CSTA-get-switching-function-devices
+CSTA-group-pickup-call
+CSTA-held-event
+CSTA-hold-call
+CSTA-hookswitch-event
+CSTA-interruption-detected-event
+CSTA-intrude-call
+CSTA-io-register-abort
+CSTA-io-register-cancel
+CSTA-io-register
+CSTA-join-call
+CSTA-lamp-mode-event
+CSTA-location-information-report
+CSTA-location-session-info
+CSTA-location-tracking-session-resumed
+CSTA-location-tracking-session-suspended
+CSTA-make-call
+CSTA-make-connection
+CSTA-make-predictive-call
+CSTA-media-attached-event
+CSTA-media-detached-event
+CSTA-media-services
+CSTA-message-waiting-event
+CSTA-microphone-gain-event
+CSTA-microphone-mute-event
+CSTA-monitor-info
+CSTA-monitor-start
+CSTA-monitor-stop
+CSTA-network-capabilities-changed-event
+CSTA-network-reached-event
+CSTA-not-recognized-event
+CSTA-offered-event
+CSTA-originated-event
+CSTA-out-of-service-event
+CSTA-park-call
+CSTA-partially-in-service-event
+CSTA-physical-device-feature
+CSTA-play-event
+CSTA-play-message
+CSTA-private-data-version-selection
+CSTA-private-event
+CSTA-query-voice-attribute
+CSTA-queue
+CSTA-queued-event
+CSTA-re-route-request
+CSTA-recognized-event
+CSTA-reconnect-call
+CSTA-record-event
+CSTA-record-message
+CSTA-registration-info
+CSTA-reposition
+CSTA-request-system-status
+CSTA-resume-data-collection
+CSTA-resume-data-path
+CSTA-resume-location-tracking-session
+CSTA-resume
+CSTA-retrieve-call
+CSTA-retrieved-event
+CSTA-review-event
+CSTA-review
+CSTA-ringer-status-event
+CSTA-route-end-request
+CSTA-route-register-abort
+CSTA-route-register-cancel
+CSTA-route-register
+CSTA-route-reject
+CSTA-route-request
+CSTA-route-select-request
+CSTA-route-used-request
+CSTA-routeing-mode-event
+CSTA-security
+CSTA-send-broadcast-data
+CSTA-send-data
+CSTA-send-message
+CSTA-send-multicast-data
+CSTA-send-stored-call-detail-records
+CSTA-send-user-information
+CSTA-service-completion-failure-event
+CSTA-service-initiated-event
+CSTA-set-agent-state
+CSTA-set-auto-answer
+CSTA-set-auto-work-mode
+CSTA-set-button-information
+CSTA-set-caller-id-status
+CSTA-set-display
+CSTA-set-do-not-disturb
+CSTA-set-forwarding
+CSTA-set-hookswitch-status
+CSTA-set-lamp-mode
+CSTA-set-location-information
+CSTA-set-message-waiting-indicator
+CSTA-set-microphone-gain
+CSTA-set-microphone-mute
+CSTA-set-ringer-status
+CSTA-set-routeing-mode
+CSTA-set-speaker-mute
+CSTA-set-speaker-volume
+CSTA-set-voice-attribute
+CSTA-silence-timeout-expired-event
+CSTA-single-step-conference
+CSTA-single-step-transfer
+CSTA-snapshot-call-data
+CSTA-snapshot-call
+CSTA-snapshot-device-data
+CSTA-snapshot-device
+CSTA-speaker-mute-event
+CSTA-speaker-volume-event
+CSTA-speech-detected-event
+CSTA-start-call-detail-records-transmission
+CSTA-start-data-collection
+CSTA-start-data-path
+CSTA-start-location-tracking-session
+CSTA-start
+CSTA-started-event
+CSTA-status-reporting
+CSTA-stop-call-detail-records
+CSTA-stop-data-collection
+CSTA-stop-data-path
+CSTA-stop-event
+CSTA-stop-location-tracking-session
+CSTA-stop
+CSTA-suspend-data-collection
+CSTA-suspend-data-path
+CSTA-suspend-location-tracking-session
+CSTA-suspend-play-event
+CSTA-suspend-record-event
+CSTA-suspend
+CSTA-switching-function-capabilities-changed
+CSTA-switching-function-devices-changed
+CSTA-switching-function-devices
+CSTA-switching-function-objects
+CSTA-synthesize-message
+CSTA-system-register-abort
+CSTA-system-register-cancel
+CSTA-system-register
+CSTA-system-status
+CSTA-telephony-tones-generated-event
+CSTA-transfer-call
+CSTA-transferred-event
+CSTA-voice-attributes-change-event
+CSTA-voice-error-occured-event
diff --git a/cstav1/AtraceCurlReader.cpp b/cstav1/AtraceCurlReader.cpp
new file mode 100644 (file)
index 0000000..b15aa8b
--- /dev/null
@@ -0,0 +1,13 @@
+#include <iostream>
+// lib curl muli. 
+#include "curl/curl.h"
+#include "AtraceReader.h"
+
+
+AtraceCurlReader::AtraceCurlReader()
+{
+}
+
+AtraceCurlReader::~AtraceCurlReader() 
+{
+}
diff --git a/cstav1/AtraceDecoder.h b/cstav1/AtraceDecoder.h
new file mode 100644 (file)
index 0000000..facd93c
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef ATRACEDECODER_H
+#define ATRACEDECODER_H
+
+/**
+ * This class is responsible to decode binary traces and
+ * converte them into a readable form. 
+ *  -> Needs tbl files to be able to make the correspondance
+ *  -> Need another listener. People might want trace from
+ *  decoder and not Binary traces.
+ * 
+ */ 
+class AtraceDecoder : public AtraceBinListener
+{
+  public:
+    AtraceDecoder();  
+    ~AtraceDecoder();
+
+    //
+    virtual void onBinState() {};
+    virtual void onBinAel() {};
+    virtual void onBinSend() {};
+    virtual void onBinCmRecv() {};
+
+    //
+    virtual void onBinSoftAno() {};
+    virtual void onBinHardAno() {};
+    virtual void onBinHistoric() {};
+    virtual void onBinDba() {};
+    virtual void onBinString() {};
+    
+    //
+    virtual void onIsbTrace() {};
+    virtual void onIsbDump() {};
+    
+    //
+    virtual void onBinPrintf() {};
+    virtual void onCstaCore() {};
+    virtual void onCstaServer() {};
+    virtual void onManagedServices() {};
+
+  protected:  
+};
+#endif /*ATRACEDECODER_H*/
diff --git a/cstav1/AtraceListener.h b/cstav1/AtraceListener.h
new file mode 100644 (file)
index 0000000..6ce237b
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef ATRACELISTENER_H
+#define ATRACELISTENER_H
+
+/**
+ * Interface to be implemented by
+ * classes that intend to process 
+ * Atrace Messages Implemented by Binary decoder
+ */ 
+class AtraceBinListener
+{
+  public:    
+    AtraceBinListener() = 0 ;
+    ~AtraceBinListener() {} ;
+    //
+    virtual void onBinState() {};
+    virtual void onBinAel() {};
+    virtual void onBinSend() {};
+    virtual void onBinCmRecv() {};
+
+    //
+    virtual void onBinSoftAno() {};
+    virtual void onBinHardAno() {};
+    virtual void onBinHistoric() {};
+    virtual void onBinDba() {};
+    virtual void onBinString() {};
+    
+    //
+    virtual void onIsbTrace() {};
+    virtual void onIsbDump() {};
+    
+    //
+    virtual void onBinPrintf() {};
+    virtual void onCstaCore() {};
+    virtual void onCstaServer() {};
+    virtual void onManagedServices() {};
+};
+/**
+ * Interface to be implemented by
+ * classes that intend to process 
+ * Atrace Messages
+ */ 
+class AtraceListener
+{
+  public:    
+    AtraceListener() = 0 ;
+    ~AtraceListener() {} ;
+
+    virtual void onIsbMessage() {};
+};
+#endif /*ATRACELISTENER_H*/
diff --git a/cstav1/AtraceMsgs.h b/cstav1/AtraceMsgs.h
new file mode 100644 (file)
index 0000000..e0f79cb
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef ATRACEMSGS_H
+#define ATRACEMSGS_H
+
+typedef unsigned char byte;
+typedef byte          g_isb_id; 
+typedef byte          g_isb_class; 
+
+#define AT_DBG_BIN_STATE             ((byte)0x0x01)
+#define AT_DBG_BIN_AEL               ((byte)0x0x02)
+#define AT_DBG_BIN_CMSEND            ((byte)0x0x03)
+#define AT_DBG_BIN_CMRECV            ((byte)0x0x04)
+
+#define AT_DBG_BIN_SOFTANO           ((byte)0x0x07)
+#define AT_DBG_BIN_HARDANO           ((byte)0x0x08)
+#define AT_DBG_BIN_HISTORIC          ((byte)0x0x09)
+#define AT_DBG_BIN_DBA               ((byte)0x0x0A)
+#define AT_DBG_BIN_STRING            ((byte)0x0x0B)
+
+#define AT_DBG_BIN_ISB_TRACE         ((byte)0x0x0D)
+#define AT_DBG_BIN_ISB_DUMP          ((byte)0x0x0E)
+#define AT_DBG_BIN_PRINTF            ((byte)0x0x0F)
+
+#define AT_DBG_BIN_CSTA_CORE         ((byte)0x0x19)
+#define AT_DBG_BIN_CSTA_SERVER       ((byte)0x0x1A)
+#define AT_DBG_BIN_MANAGED_SERVICES  ((byte)0x0x1B)
+
+
+/**
+ *
+ */ 
+typedef struct 
+  char                          spyb_header;
+  byte                          high_length;
+  byte                          low_length;
+  g_isb_id              transmitter_id;
+  g_isb_class   clas;
+  byte                          msg_family;
+  byte                          msg_name;
+  byte                          eqt_id;
+  byte                          sub_eqt_id;
+  byte                          param[1];
+} g_header;
+
+/**
+ *
+ */ 
+typedef struct {
+    byte                        trace_pattern;
+    byte                        trace_format;
+    WORD                        trace_sequence;
+    // This is an endianess problem
+    unsigned    trace_length_hi :  1;
+    unsigned    trace_sender    :  5;
+    unsigned    trace_truncated :  1;
+    unsigned    /* alignment */ :  1;
+    unsigned    trace_length_lo :  8;
+} g_dbg_trace_header;
+
+
+#endif /*ATRACEMSGS_H*/
diff --git a/cstav1/AtraceReader.h b/cstav1/AtraceReader.h
new file mode 100644 (file)
index 0000000..3b27538
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef ATRACEREADER_H
+#define ATRACEREADER_H
+
+/**
+ * Generique class to read Debug messages.
+ * Decline this class into two other classes
+ *  -> AtraceCURLReader
+ *  -> AtraceFileReader
+ */ 
+class AtraceReader
+{
+  public:
+    typedef std::list<AtraceListener *> ListenerList;
+    typedef ListenerList::iterator      iterator;
+
+    AtraceReader();
+    ~AtraceReader();
+
+    void registerListener(AtraceListener *l)
+    { m_Listener.push_back(l); };
+  protected:
+    ListenerList m_Listerners;
+
+};
+
+
+/**
+ * Atrace reader specialisation
+ * I need Host, Password Endianess
+ */ 
+class AtraceCurlReader : public AtraceReader
+{
+  public:
+    AtraceCurlReader();  
+    ~AtraceCurlReader();
+  protected:  
+};
+
+#endif /*ATRACEREADER_H*/
diff --git a/cstav1/CExpatImpl.h b/cstav1/CExpatImpl.h
new file mode 100644 (file)
index 0000000..929c2ff
--- /dev/null
@@ -0,0 +1,862 @@
+#ifndef DSSI_EXPATIMPL_H
+ #define DSSI_EXPATIMPL_H
+#ifdef __GNUC__
+#define __cdecl __attribute__((__cdecl__))
+#endif
+ //-----------------------------------------------------------------------------
+ // 
+ // @doc
+ //
+ // @module  ExpatImpl.h - Expat class container |
+ //
+ // This module contains the definition of the expat class container.
+ //
+ // Copyright (c) 1994-2002 - Descartes Systems Sciences, Inc.
+ //
+ // @end
+ //
+ // $History: ExpatImpl.h $
+ //      
+ //      *****************  Version 1  *****************
+ //      User: Tim Smith    Date: 1/29/02    Time: 1:57p
+ //      Created in $/Omni_V2/_ToolLib
+ //      1. String.h now replaced with StringCode.h.
+ //      2. StringRsrc.h modified to use new string class.
+ //      3. Added tons of new classes from the wedge work.
+ //      
+ //-----------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------
+ //
+ // Required include files
+ //
+ //-----------------------------------------------------------------------------
+ #include <assert.h>
+ #include "expat.h"
+ //-----------------------------------------------------------------------------
+ //
+ // Forward definitions
+ //
+ //-----------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------
+ //
+ // Template class definition
+ //
+ //-----------------------------------------------------------------------------
+ template <class _T>
+ class CExpatImpl
+ {
+ // @access Constructors and destructors
+ public:
+     
+     // @cmember General constructor
+     CExpatImpl ()
+     {
+         m_p = NULL;
+     }
+     // @cmember Destructor
+     ~CExpatImpl ()
+     {
+         Destroy ();
+     }
+ // @access Parser creation and deletion methods
+ public:
+     // @cmember Create a parser
+     bool Create (const XML_Char *pszEncoding = NULL, 
+         const XML_Char *pszSep = NULL)
+     {
+         //
+         // Destroy the old parser
+         //
+         Destroy ();
+         //
+         // If the encoding or seperator are empty, then NULL
+         //
+         if (pszEncoding != NULL && pszEncoding [0] == 0)
+             pszEncoding = NULL;
+         if (pszSep != NULL && pszSep [0] == 0)
+             pszSep = NULL;
+         //
+         // Create the new one
+         //
+         m_p = XML_ParserCreate_MM (pszEncoding, NULL, pszSep);
+         if (m_p == NULL)
+             return false;
+         //
+         // Invoke the post create routine
+         //
+         _T *pThis = static_cast <_T *> (this);
+         pThis ->OnPostCreate ();
+         //
+         // Set the user data used in callbacks
+         //
+         XML_SetUserData (m_p, (void *) this);
+         return true;
+     }
+     // @cmember Destroy the parser
+     void Destroy ()
+     {
+         if (m_p != NULL)
+             XML_ParserFree (m_p);
+         m_p = NULL;
+     }
+ // @access Parser parse methods
+ public:
+     // @cmember Parse a block of data
+     bool Parse (const char *pszBuffer, int nLength = -1, bool fIsFinal = true)
+     {
+         //
+         // Validate
+         //
+         assert (m_p != NULL);
+         //
+         // Get the length if not specified
+         //
+         if (nLength < 0)
+             nLength = strlen (pszBuffer);
+         //
+         // Invoke the parser
+         //
+         return XML_Parse (m_p, pszBuffer, nLength, fIsFinal) != 0;
+     }
+     // @cmember Parse a block of data
+ #ifdef WCHAR
+     bool Parse (const WCHAR *pszBuffer, int nLength = -1, bool fIsFinal = true)
+     {
+         //
+         // Validate
+         //
+         assert (m_p != NULL);
+         //
+         // Get the length if not specified
+         //
+         if (nLength < 0)
+             nLength = wcslen (pszBuffer) * 2;
+         //
+         // Invoke the parser
+         //
+         return XML_Parse (m_p, pszBuffer, nLength, fIsFinal) != 0;
+     }
+ #endif
+     // @cmember Parse internal buffer
+     bool ParseBuffer (int nLength, bool fIsFinal = true)
+     {
+         assert (m_p != NULL);
+         return XML_ParseBuffer (m_p, nLength, fIsFinal) != 0;
+     }
+     // @cmember Get the internal buffer
+     void *GetBuffer (int nLength)
+     {
+         assert (m_p != NULL);
+         return XML_GetBuffer (m_p, nLength);
+     }
+ // @access Parser callback enable/disable methods
+ public:
+     // @cmember Enable/Disable the start element handler
+     void EnableStartElementHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetStartElementHandler (m_p, fEnable ? StartElementHandler : NULL);
+     }
+     // @cmember Enable/Disable the end element handler
+     void EnableEndElementHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetEndElementHandler (m_p, fEnable ? EndElementHandler : NULL);
+     }
+     // @cmember Enable/Disable the element handlers
+     void EnableElementHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         EnableStartElementHandler (fEnable);
+         EnableEndElementHandler (fEnable);
+     }
+     // @cmember Enable/Disable the character data handler
+     void EnableCharacterDataHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetCharacterDataHandler (m_p,
+             fEnable ? CharacterDataHandler : NULL);
+     }
+     // @cmember Enable/Disable the processing instruction handler
+     void EnableProcessingInstructionHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetProcessingInstructionHandler (m_p, 
+             fEnable ? ProcessingInstructionHandler : NULL);
+     }
+     // @cmember Enable/Disable the comment handler
+     void EnableCommentHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetCommentHandler (m_p, fEnable ? CommentHandler : NULL);
+     }
+     // @cmember Enable/Disable the start CDATA section handler
+     void EnableStartCdataSectionHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetStartCdataSectionHandler (m_p, 
+             fEnable ? StartCdataSectionHandler : NULL);
+     }
+     // @cmember Enable/Disable the end CDATA section handler
+     void EnableEndCdataSectionHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetEndCdataSectionHandler (m_p, 
+             fEnable ? EndCdataSectionHandler : NULL);
+     }
+     // @cmember Enable/Disable the CDATA section handlers
+     void EnableCdataSectionHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         EnableStartCdataSectionHandler (fEnable);
+         EnableEndCdataSectionHandler (fEnable);
+     }
+     // @cmember Enable/Disable default handler
+     
+     void EnableDefaultHandler (bool fEnable = true, bool fExpand = true)
+     {
+         assert (m_p != NULL);
+         if (fExpand)
+         {
+             XML_SetDefaultHandlerExpand (m_p, 
+                 fEnable ? DefaultHandler : NULL);
+         }
+         else
+             XML_SetDefaultHandler (m_p, fEnable ? DefaultHandler : NULL);
+     }
+     
+     // @cmember Enable/Disable external entity ref handler
+     
+     void EnableExternalEntityRefHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetExternalEntityRefHandler (m_p, 
+             fEnable ? ExternalEntityRefHandler : NULL);
+     }
+     
+     // @cmember Enable/Disable unknown encoding handler
+     
+     void EnableUnknownEncodingHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetUnknownEncodingHandler (m_p, 
+             fEnable ? UnknownEncodingHandler : NULL,NULL);
+     }
+     
+     // @cmember Enable/Disable start namespace handler
+     
+     void EnableStartNamespaceDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetStartNamespaceDeclHandler (m_p, 
+             fEnable ? StartNamespaceDeclHandler : NULL);
+     }
+     
+     // @cmember Enable/Disable end namespace handler
+     
+     void EnableEndNamespaceDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetEndNamespaceDeclHandler (m_p, 
+             fEnable ? EndNamespaceDeclHandler : NULL);
+     }
+     // @cmember Enable/Disable namespace handlers
+     void EnableNamespaceDeclHandler (bool fEnable = true)
+     {
+         EnableStartNamespaceDeclHandler (fEnable);
+         EnableEndNamespaceDeclHandler (fEnable);
+     }
+     
+     // @cmember Enable/Disable the XML declaration handler
+     void EnableXmlDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetXmlDeclHandler (m_p, fEnable ? XmlDeclHandler : NULL);
+     }
+     // @cmember Enable/Disable the start DOCTYPE declaration handler
+     void EnableStartDoctypeDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetStartDoctypeDeclHandler (m_p, 
+             fEnable ? StartDoctypeDeclHandler : NULL);
+     }
+     // @cmember Enable/Disable the end DOCTYPE declaration handler
+     void EnableEndDoctypeDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         XML_SetEndDoctypeDeclHandler (m_p, 
+             fEnable ? EndDoctypeDeclHandler : NULL);
+     }
+     // @cmember Enable/Disable the DOCTYPE declaration handler
+     void EnableDoctypeDeclHandler (bool fEnable = true)
+     {
+         assert (m_p != NULL);
+         EnableStartDoctypeDeclHandler (fEnable);
+         EnableEndDoctypeDeclHandler (fEnable);
+     }
+ // @access Parser error reporting methods
+ public:
+     // @cmember Get last error
+     enum XML_Error GetErrorCode () 
+     {
+         assert (m_p != NULL);
+         return XML_GetErrorCode (m_p);
+     }
+     // @cmember Get the current byte index
+     long GetCurrentByteIndex () 
+     {
+         assert (m_p != NULL);
+         return XML_GetCurrentByteIndex (m_p);
+     }
+     // @cmember Get the current line number
+     int GetCurrentLineNumber () 
+     {
+         assert (m_p != NULL);
+         return XML_GetCurrentLineNumber (m_p);
+     }
+     // @cmember Get the current column number
+     int GetCurrentColumnNumber () 
+     {
+         assert (m_p != NULL);
+         return XML_GetCurrentColumnNumber (m_p);
+     }
+     // @cmember Get the current byte count
+     int GetCurrentByteCount () 
+     {
+         assert (m_p != NULL);
+         return XML_GetCurrentByteCount (m_p);
+     }
+     // @cmember Get the input context
+     const char *GetInputContext (int *pnOffset, int *pnSize)
+     {
+         assert (m_p != NULL);
+         return XML_GetInputContext (m_p, pnOffset, pnSize);
+     }
+     // @cmember Get last error string
+     const XML_LChar *GetErrorString () 
+     {
+         return XML_ErrorString (GetErrorCode ());
+     }
+ // @access Parser other methods
+ public:
+     // @cmember Return the version string
+     static const XML_LChar *GetExpatVersion ()
+     {
+         return XML_ExpatVersion ();
+     }
+     // @cmember Get the version information
+     static void GetExpatVersion (int *pnMajor, int *pnMinor, int *pnMicro)
+     {
+         XML_Expat_Version v = XML_ExpatVersionInfo ();
+         if (pnMajor)
+             *pnMajor = v .major;
+         if (pnMinor)
+             *pnMinor = v .minor;
+         if (pnMicro)
+             *pnMicro = v .micro;
+     }
+     // @cmember Get last error string
+     static const XML_LChar *GetErrorString (enum XML_Error nError) 
+     {
+         return XML_ErrorString (nError);
+     }
+ // @access Public handler methods
+ public:
+     // @cmember Start element handler
+     void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs)
+     {
+         return;
+     }
+     // @cmember End element handler
+     void OnEndElement (const XML_Char *pszName)
+     {
+         return;
+     }
+     // @cmember Character data handler
+     void OnCharacterData (const XML_Char *pszData, int nLength)
+     {
+         return;
+     }
+     // @cmember Processing instruction handler
+     void OnProcessingInstruction (const XML_Char *pszTarget, 
+         const XML_Char *pszData)
+     {
+         return;
+     }
+     // @cmember Comment handler
+     void OnComment (const XML_Char *pszData)
+     {
+         return;
+     }
+     // @cmember Start CDATA section handler
+     void OnStartCdataSection ()
+     {
+         return;
+     }
+     // @cmember End CDATA section handler
+     void OnEndCdataSection ()
+     {
+         return;
+     }
+     // @cmember Default handler
+     
+     void OnDefault (const XML_Char *pszData, int nLength)
+     {
+         return;
+     }
+     
+     // @cmember External entity ref handler
+     
+     bool OnExternalEntityRef (const XML_Char *pszContext,
+         const XML_Char *pszBase, const XML_Char *pszSystemID,
+         const XML_Char *pszPublicID)
+     {
+         return false;
+     }
+     
+     // @cmember Unknown encoding handler
+     
+     bool OnUnknownEncoding (const XML_Char *pszName, XML_Encoding *pInfo)
+     {
+         return false;
+     }
+     
+     // @cmember Start namespace declaration handler
+     
+     void OnStartNamespaceDecl (const XML_Char *pszPrefix, 
+         const XML_Char *pszURI)
+     {
+         return;
+     }
+     
+     // @cmember End namespace declaration handler
+     
+     void OnEndNamespaceDecl (const XML_Char *pszPrefix)
+     {
+         return;
+     }
+     
+     // @cmember XML declaration handler
+     void OnXmlDecl (const XML_Char *pszVersion, const XML_Char *pszEncoding,
+         bool fStandalone)
+     {
+         return;
+     }
+     // @cmember Start DOCTYPE declaration handler
+     void OnStartDoctypeDecl (const XML_Char *pszDoctypeName, 
+         const XML_Char *pszSysID, const XML_Char *pszPubID,
+         bool fHasInternalSubset)
+     {
+         return;
+     }
+     // @cmember End DOCTYPE declaration handler
+     void OnEndDoctypeDecl ()
+     {
+         return;
+     }
+ // @access Protected methods
+ protected:
+     // @cmember Handle any post creation
+     void OnPostCreate ()
+     {
+     }
+ // @access Protected static methods
+ protected:
+     // @cmember Start element handler wrapper
+     static void __cdecl StartElementHandler (void *pUserData,
+         const XML_Char *pszName, const XML_Char **papszAttrs)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnStartElement (pszName, papszAttrs);
+     }
+     // @cmember End element handler wrapper
+     static void __cdecl EndElementHandler (void *pUserData,
+         const XML_Char *pszName)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnEndElement (pszName);
+     }
+     // @cmember Character data handler wrapper
+     static void __cdecl CharacterDataHandler (void *pUserData,
+         const XML_Char *pszData, int nLength)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnCharacterData (pszData, nLength);
+     }
+     // @cmember Processing instruction handler wrapper
+     static void __cdecl ProcessingInstructionHandler (void *pUserData,
+         const XML_Char *pszTarget, const XML_Char *pszData)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnProcessingInstruction (pszTarget, pszData);
+     }
+     // @cmember Comment handler wrapper
+     static void __cdecl CommentHandler (void *pUserData,
+         const XML_Char *pszData)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnComment (pszData);
+     }
+     // @cmember Start CDATA section wrapper
+     static void __cdecl StartCdataSectionHandler (void *pUserData)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnStartCdataSection ();
+     }
+     // @cmember End CDATA section wrapper
+     static void __cdecl EndCdataSectionHandler (void *pUserData)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnEndCdataSection ();
+     }
+     // @cmember Default wrapper
+     
+     static void __cdecl DefaultHandler (void *pUserData, 
+         const XML_Char *pszData, int nLength)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnDefault (pszData, nLength);
+     }
+     
+     // @cmember External entity ref wrapper
+     
+     static int __cdecl ExternalEntityRefHandler (void *pUserData, 
+         const XML_Char *pszContext, const XML_Char *pszBase, 
+         const XML_Char *pszSystemID, const XML_Char *pszPublicID)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         return pThis ->OnExternalEntityRef (pszContext, 
+             pszBase, pszSystemID, pszPublicID) ? 1 : 0;
+     }
+     
+     // @cmember Unknown encoding wrapper
+     
+     static int __cdecl UnknownEncodingHandler (void *pUserData, 
+         const XML_Char *pszName, XML_Encoding *pInfo)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         return pThis ->OnUnknownEncoding (pszName, pInfo) ? 1 : 0;
+     }
+     
+     // @cmember Start namespace decl wrapper
+     
+     static void __cdecl StartNamespaceDeclHandler (void *pUserData, 
+         const XML_Char *pszPrefix, const XML_Char *pszURI)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnStartNamespaceDecl (pszPrefix, pszURI);
+     }
+     
+     // @cmember End namespace decl wrapper
+     
+     static void __cdecl EndNamespaceDeclHandler (void *pUserData, 
+         const XML_Char *pszPrefix)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnEndNamespaceDecl (pszPrefix);
+     }
+     
+     // @cmember XML declaration wrapper
+     static void __cdecl XmlDeclHandler (void *pUserData,
+         const XML_Char *pszVersion, const XML_Char *pszEncoding,
+         int nStandalone)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnXmlDecl (pszVersion, pszEncoding, nStandalone != 0);
+     }
+     // @cmember Start Doctype declaration wrapper
+     static void __cdecl StartDoctypeDeclHandler (void *pUserData,
+         const XML_Char *pszDoctypeName, const XML_Char *pszSysID, 
+         const XML_Char *pszPubID, int nHasInternalSubset)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnStartDoctypeDecl (pszDoctypeName, pszSysID, 
+             pszPubID, nHasInternalSubset != 0);
+     }
+     // @cmember End Doctype declaration wrapper
+     static void __cdecl EndDoctypeDeclHandler (void *pUserData)
+     {
+         _T *pThis = static_cast <_T *> ((CExpatImpl <_T> *) pUserData);
+         pThis ->OnEndDoctypeDecl ();
+     }
+ // @access Protected members
+ protected:
+     XML_Parser      m_p;
+ };
+ //-----------------------------------------------------------------------------
+ //
+ // Virtual method class definition
+ //
+ //-----------------------------------------------------------------------------
+ class CExpat : public CExpatImpl <CExpat>
+ {
+ // @access Constructors and destructors
+ public:
+     
+     CExpat ()
+     {
+     }
+ // @access Public handler methods
+ public:
+     // @cmember Start element handler
+     virtual void OnStartElement (const XML_Char *pszName, 
+         const XML_Char **papszAttrs)
+     {
+         return;
+     }
+     // @cmember End element handler
+     virtual void OnEndElement (const XML_Char *pszName)
+     {
+         return;
+     }
+     // @cmember Character data handler
+     virtual void OnCharacterData (const XML_Char *pszData, int nLength)
+     {
+         return;
+     }
+     // @cmember Processing instruction handler
+     virtual void OnProcessingInstruction (const XML_Char *pszTarget, 
+         const XML_Char *pszData)
+     {
+         return;
+     }
+     // @cmember Comment handler
+     virtual void OnComment (const XML_Char *pszData)
+     {
+         return;
+     }
+     // @cmember Start CDATA section handler
+     virtual void OnStartCdataSection ()
+     {
+         return;
+     }
+     // @cmember End CDATA section handler
+     virtual void OnEndCdataSection ()
+     {
+         return;
+     }
+     // @cmember Default handler
+     
+     virtual void OnDefault (const XML_Char *pszData, int nLength)
+     {
+         return;
+     }
+     
+     // @cmember External entity ref handler
+     
+     virtual bool OnExternalEntityRef (const XML_Char *pszContext,
+         const XML_Char *pszBase, const XML_Char *pszSystemID,
+         const XML_Char *pszPublicID)
+     {
+         return false;
+     }
+     
+     // @cmember Unknown encoding handler
+     
+     virtual bool OnUnknownEncoding (const XML_Char *pszName, XML_Encoding *pInfo)
+     {
+         return false;
+     }
+     
+     // @cmember Start namespace declaration handler
+     
+     virtual void OnStartNamespaceDecl (const XML_Char *pszPrefix, 
+         const XML_Char *pszURI)
+     {
+         return;
+     }
+     
+     // @cmember End namespace declaration handler
+     
+     virtual void OnEndNamespaceDecl (const XML_Char *pszPrefix)
+     {
+         return;
+     }
+     
+     // @cmember XML declaration handler
+     virtual void OnXmlDecl (const XML_Char *pszVersion, 
+         const XML_Char *pszEncoding, bool fStandalone)
+     {
+         return;
+     }
+     // @cmember Start DOCTYPE declaration handler
+     virtual void OnStartDoctypeDecl (const XML_Char *pszDoctypeName, 
+         const XML_Char *pszSysID, const XML_Char *pszPubID,
+         bool fHasInternalSubset)
+     {
+         return;
+     }
+     // @cmember End DOCTYPE declaration handler
+     virtual void OnEndDoctypeDecl ()
+     {
+         return;
+     }
+ };
+#endif // DSSI_EXPATIMPL_H
diff --git a/cstav1/CMakeLists.txt b/cstav1/CMakeLists.txt
new file mode 100644 (file)
index 0000000..da25dc7
--- /dev/null
@@ -0,0 +1,541 @@
+PROJECT(cstav1-lib)
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${rules_SOURCE_DIR}/")
+
+FIND_PACKAGE(PCAP REQUIRED)
+INCLUDE_DIRECTORIES(${PCAP_INCLUDE_DIRS})
+
+IF (WITH_CSTAV1)
+#for mingw32
+INCLUDE_DIRECTORIES(/include)
+INCLUDE_DIRECTORIES(${MAKE_CURRENT_BINARY_DIR})
+IF(NOT WIN32)
+FIND_PACKAGE(EXPAT REQUIRED )
+ENDIF(NOT WIN32)
+
+ADD_DEFINITIONS(-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER)
+SET(CSTAV1_ERULE "-e ber")
+SET(CSTAV1_MODEL ${asn1-data-models_SOURCE_DIR}/cstav1/ CACHE STRING "CSTA V1 datamodel source directory")
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt CSTAV1MODULES)
+
+FOREACH(ITEM ${CSTAV1MODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(CSTAV1SRC ${CSTAV1SRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(CSTAV1HDR ${CSTAV1HDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h"
+    )
+
+ENDFOREACH(ITEM)
+
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Generic_ROS_PDUs.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp 
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE}
+         -f Remote-Operations-Information-Objects.asn1
+         -f Remote-Operations-Generic-ROS-PDUs.asn1
+        -oRemote-Operations-Generic-ROS-PDUs 
+    DEPENDS ${asn1p_EXE}
+    COMMENT "Build ROGR .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Generic_ROS_PDUs.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp
+    GENERATED)
+#
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE}
+         -f Remote-Operations-Information-Objects.asn1
+        -oRemote-Operations-Information-Objects 
+    DEPENDS ${asn1p_EXE}
+    COMMENT "Build ROIO .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp
+    GENERATED)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-event.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_event.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE}
+         -f Remote-Operations-Information-Objects.asn1 
+         -f apdu_rose_94.asn1 
+         -f evt_definition_94.asn1 
+         -f err_error.asn1
+         -f obj_extension_94.asn1
+         -f obj_private_94.asn1
+         -f obj_feature.asn1 -f obj_status.asn1
+         -f obj_device.asn1 -f obj_call.asn1 
+        -f obj_connection.asn1 -f obj_switch.asn1 -oCSTA-event
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_extend.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_status.h 
+      COMMENT "Build CSTA-event .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/Model.uml
+    COMMAND cat
+    ${asn1-data-models_SOURCE_DIR}/cstav1/apdu_rose_94.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/evt_definition_94.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/obj_connection.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/obj_call.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/obj_feature.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/obj_status.asn1
+    ${asn1-data-models_SOURCE_DIR}/cstav1/err_error.asn1
+    ARGS | ${asn1p_EXE} -u CstaV1Events.uml
+    COMMAND ${CMAKE_COMMAND} -E rename _model.uml Model.uml
+    DEPENDS ${asn1p_EXE}
+    COMMENT "Build UML cstav1 Events for UML"
+    )
+
+#ADD_CUSTOM_TARGET(Model.uml ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_model.uml)
+#SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_CLEAN Model.uml)
+#SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_CLEAN _model.uml)
+
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-connect.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_connect.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE} 
+      -f obj_device.asn1 
+      -f obj_call.asn1 
+      -f obj_connection.asn1 
+      -f obj_switch.asn1 
+      -oCSTA-connect
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build CSTA-connect.h and .cpp"
+    )
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-status.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_status.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE} -f obj_status.asn1 -f obj_device.asn1 
+         -f obj_call.asn1 -f obj_connection.asn1 -f obj_switch.asn1 
+         -oCSTA-status
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build CSTA-status.h and .cpp"
+    )
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-feature.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_feature.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE} -f obj_device.asn1 -f obj_feature.asn1 
+         -f obj_call.asn1 -oCSTA-feature
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build CSTA-feature.h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-private.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_private.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE} -f obj_device.asn1 
+         -f obj_feature.asn1 
+         -f obj_switch.asn1 
+         -f obj_call.asn1 
+         -f obj_extension_94.asn1
+         -f err_error.asn1
+         -f Remote-Operations-Information-Objects.asn1 
+         -f  obj_private_94.asn1 -oCSTA-private
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build CSTA-private.h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-call.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_call.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} ${CSTAV1_ERULE} -f obj_device.asn1 -f obj_status.asn1 -f obj_call.asn1 -oCSTA-call
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-event.cpp 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_status.h
+      COMMENT "Build CSTA-call .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-device.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_device.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} -f obj_device.asn1 -f obj_status.asn1 -f obj_extension_94.asn1 -oCSTA-device
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      COMMENT "Build CSTA-device .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-extend.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_extend.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} 
+      -f obj_extension_94.asn1
+      -f obj_security.asn1 -f Remote-Operations-Information-Objects.asn1
+    -oCSTA-extend
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h 
+    COMMENT "Build CSTA-extend .h and .cpp ${asn1-data-models_SOURCE_DIR}/cstav1"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/Rose-Apdu.cpp
+    ${CMAKE_CURRENT_BINARY_DIR}/Rose_Apdu.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} -fapdu_rose_94.asn1
+           -fobj_call.asn1
+           -fobj_status.asn1 
+           -fobj_switch.asn1 
+           -fobj_connection.asn1 -fobj_device.asn1 -fobj_feature.asn1 
+           -ferr_error.asn1 -fevt_definition_94.asn1 
+           -f obj_extension_94.asn1 -f obj_security.asn1
+           -f Remote-Operations-Information-Objects.asn1
+    -oRose-Apdu
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h 
+      COMMENT "Build Rose-Apdu .h and .cpp"
+    )
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-switch.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_switch.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} 
+         -fobj_call.asn1 
+        -fobj_device.asn1 
+        -ferr_error.asn1 
+        -f obj_switch.asn1 
+        -f Remote-Operations-Information-Objects.asn1
+        -oCSTA-switch
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build cstav1 CSTA-switch.h and CSTA-switch.cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-secure.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_secure.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} 
+         -fobj_security.asn1
+        -oCSTA-secure
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      COMMENT "Build CSTA-secure .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-error.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_error.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} 
+         -f Remote-Operations-Information-Objects.asn1 
+         -ferr_error.asn1
+        -oCSTA-error
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      COMMENT "Build CSTA-error .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE-1.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} 
+         -fapdu_acse.asn1
+        -f Remote-Operations-Information-Objects.asn1
+         -oACSE-1
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build ACSE-1 .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA-MSG.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/CSTA_MSG.h
+   
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${CSTAV1_MODEL} -f apdu_csta.asn1 -f apdu_acse.asn1 -f
+    apdu_rose_94.asn1 -oCSTA-MSG
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h 
+    COMMENT "Build CSTA-MSG .h and .cpp"
+    )
+
+
+ADD_LIBRARY(cstav1
+      ${CSTAV1SRC}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    )
+
+ADD_EXECUTABLE(test_cstav1
+    main.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    )
+TARGET_LINK_LIBRARIES(test_cstav1 cstav1 asn1)
+
+IF (NOT CMAKE_CROSSCOMPILING)
+  IF(NOT WIN32)        
+    FIND_PACKAGE(FLTK REQUIRED
+           NAME FLTK)
+    IF(FLTK_BUILT_WITH_CMAKE)
+       INCLUDE_DIRECTORIES(${FLTK_INCLUDE_DIR}/../include)
+    ELSE(FLTK_BUILT_WITH_CMAKE)
+       INCLUDE_DIRECTORIES(${FLTK_INCLUDE_DIR})
+    ENDIF(FLTK_BUILT_WITH_CMAKE)
+
+    FIND_PACKAGE(OpenGL REQUIRED)
+  ELSE(NOT WIN32)
+    INCLUDE_DIRECTORIES(${FLTK_INCLUDE_DIR})
+  ENDIF(NOT WIN32)
+FLTK_WRAP_UI(Ui cstaspyui.fl)
+
+ADD_LIBRARY(Ui  
+    SequenceView.cpp 
+    HeaderView.cpp 
+    Model.cpp 
+    Controler.cpp 
+    ${Ui_FLTK_UI_SRCS}
+    Pcap.cpp
+    Packet.cpp
+    Timeline.cpp
+    TLMsg.cpp
+    IconFactory.cpp
+    CstaInsightLog.cpp
+    )
+ADD_DEPENDENCIES(Ui cstav1)
+
+ADD_EXECUTABLE(csta_insight 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+                )
+
+ADD_DEPENDENCIES(csta_insight Ui)
+ADD_DEPENDENCIES(csta_insight cstav1)
+IF(APPLE)
+TARGET_LINK_LIBRARIES(csta_insight Ui)
+TARGET_LINK_LIBRARIES(csta_insight ${EXPAT_LIB})
+SET_TARGET_PROPERTIES(csta_insight PROPERTIES LINKER_FLAGS "-framework Cocoa")
+#Missing and don't know why
+MESSAGE(" FLTK_INCLUDE_DIR = ${FLTK_INCLUDE_DIR}") 
+SET(FLTK_PNG_LIB /Users/aeb/Externals/MacOSX.10.11/fltk-1.3/lib/libfltk_png.a) 
+#TARGET_LINK_LIBRARIES(csta_insight /usr/local/lib/libfltk_png.a)
+TARGET_LINK_LIBRARIES(csta_insight ${FLTK_PNG_LIB})
+ENDIF(APPLE)
+
+IF(UNIX AND NOT APPLE)
+# Find libdl for fltk on Ubuntu dlsym
+FIND_LIBRARY(DL_LIBRARY NAMES dl libdl)
+MESSAGE("Looking for DL library")
+TARGET_LINK_LIBRARIES(csta_insight ${DL_LIBRARY})
+MESSAGE("Have for DL library ${DL_LIBRARY}")
+TARGET_LINK_LIBRARIES(csta_insight Ui X11 Xft Xinerama fltk_images ${EXPAT_LIB})
+ENDIF()
+
+IF(WIN32)
+MESSAGE("WIN32 SETTINGS ")
+  TARGET_LINK_LIBRARIES(csta_insight Ui ws2_32)
+  TARGET_LINK_LIBRARIES(csta_insight ${EXPAT_LIBRARY})
+  TARGET_LINK_LIBRARIES(csta_insight ${FLTK_LIBRARIES})
+ELSEIF(MINGW)
+       MESSAGE("MINGW SETTINGS ")
+TARGET_LINK_LIBRARIES(Ui C:/MinGW/msys/1.0/opt/lib/libfltk_png.a)
+TARGET_LINK_LIBRARIES(Ui C:/MinGW/msys/1.0/opt/lib/libfltk_z.a)
+TARGET_LINK_LIBRARIES(csta_insight C:/MinGW/msys/1.0/opt/lib/libfltk_png.a)
+TARGET_LINK_LIBRARIES(csta_insight Ui ws2_32)
+TARGET_LINK_LIBRARIES(csta_insight ${EXPAT_LIBRARY})
+#Missing and don't know why
+ENDIF(WIN32)
+
+TARGET_LINK_LIBRARIES(csta_insight ${FLTK_LIBRARIES})
+TARGET_LINK_LIBRARIES(csta_insight cstav1)
+TARGET_LINK_LIBRARIES(csta_insight asn1)
+TARGET_LINK_LIBRARIES(csta_insight ${PCAP_LIBRARIES})
+
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+#
+# Install stuff
+#
+
+IF (NOT CMAKE_CROSSCOMPILING)
+INSTALL(TARGETS csta_insight DESTINATION bin
+    COMPONENT Csta
+    )
+
+FILE(GLOB CSTA_IMAGES ${CMAKE_CURRENT_SOURCE_DIR}/images/*.png)
+INSTALL(FILES ${CSTA_IMAGES} DESTINATION share/csta_insight/images
+    COMPONENT Csta)
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+INSTALL(FILES 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_feature.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_private.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_secure.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_status.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_switch.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_device.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_error.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_event.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_extend.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_private.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_connect.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_call.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/CSTA_MSG.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/ACSE_1.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+       ${CMAKE_CURRENT_BINARY_DIR}/Rose_Apdu.h 
+       DESTINATION include/CSTA/
+    COMPONENT Csta-Header)
+
+FILE(GLOB CSTA_ACSE ${CMAKE_CURRENT_BINARY_DIR}/include/ACSE_1/*.h)
+INSTALL(FILES ${CSTA_ACSE} DESTINATION include/CSTA/ACSE_1
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_MSG ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_MSG/*.h)
+INSTALL(FILES ${CSTA_MSG} DESTINATION include/CSTA/CSTA_MSG
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_CONNECT ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_connect/*.h)
+INSTALL(FILES ${CSTA_CONNECT} DESTINATION include/CSTA/CSTA_connect
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_EVENT ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_event/*.h)
+INSTALL(FILES ${CSTA_EVENT} DESTINATION include/CSTA/CSTA_event
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_ERROR ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_error/*.h)
+INSTALL(FILES ${CSTA_ERROR} DESTINATION include/CSTA/CSTA_error
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_EXTEND ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_extend/*.h)
+INSTALL(FILES ${CSTA_EXTEND} DESTINATION include/CSTA/CSTA_extend
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_FEATURE ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_feature/*.h)
+INSTALL(FILES ${CSTA_FEATURE} DESTINATION include/CSTA/CSTA_feature
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_private/*.h)
+INSTALL(FILES ${CSTA_PRIVATE} DESTINATION include/CSTA/CSTA_private
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_SECURE ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_secure/*.h)
+INSTALL(FILES ${CSTA_SECURE} DESTINATION include/CSTA/CSTA_secure
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_STATUS ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_status/*.h)
+INSTALL(FILES ${CSTA_STATUS} DESTINATION include/CSTA/CSTA_status
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_SWITCH ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_switch/*.h)
+INSTALL(FILES ${CSTA_SWITCH} DESTINATION include/CSTA/CSTA_switch
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_CALL ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_call/*.h)
+INSTALL(FILES ${CSTA_CALL} DESTINATION include/CSTA/CSTA_call
+    COMPONENT Csta-Headers)
+
+FILE(GLOB CSTA_DEVICE ${CMAKE_CURRENT_BINARY_DIR}/include/CSTA_device/*.h)
+INSTALL(FILES ${CSTA_DEVICE} DESTINATION include/CSTA/CSTA_device
+    COMPONENT Csta-Headers)
+
+INSTALL(TARGETS cstav1 
+       DESTINATION lib
+    COMPONENT Csta-Lib
+    )
+
+#
+# Ok start working with Packaging stuff
+#
+INCLUDE(InstallRequiredSystemLibraries)
+#SET(CPACK_OUTPUT_CONFIG_FILE "${PROJECT_BINARY_DIR}/CPackConfig.cmake" )
+#SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Graphical user interface to visualize csta  messages from pcap files")
+#SET(CPACK_PACKAGE_VENDOR "Aeb")
+#SET(CPACK_PACKAGE_DESCRIPTION_FILE "")
+#SET(CPACK_RESOURCE_FILE_LICENSE "")
+#SET(CPACK_PACKAGE_VERSION_MAJOR "1")
+#SET(CPACK_PACKAGE_VERSION_MINOR "0")
+#SET(CPACK_PACKAGE_VERSION_PATCH "0")
+
+#SET(CPACK_PACKAGE_FILE_NAME "CstaSpyInstaller")
+#SET(CPACK_PACKAGE_NAME "CstaSpy")
+
+IF(WIN32)
+  SET(CPACK_GENERATOR "NSIS")
+ENDIF()
+
+# IF(UNIX)
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
+    SET(CPACK_INSTALL_CMAKE_PROJECTS "${PROJECT_BINARY_DIR};cstav1-lib;ALL;/")
+  SET(CPACK_RPM_COMPONENT_INSTALL ON)
+  SET(CPACK_PACKAGE_FILE_NAME "CstaSpyInstaller")
+  set(CPACK_COMPONENTS_ALL Csta-Headers Csta-Lib Csta)
+  SET(CPACK_COMPONENTS_IGNORE_GROUPS 1)
+  SET(CPACK_COMPONENTS_GROUPING "IGNORE")
+  SET(CPACK_GENERATOR "RPM")
+ENDIF()
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" )
+  SET(CPACK_GENERATOR "Bundel")
+ENDIF()
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy")
+SET(CPACK_PACKAGE_EXECUTABLES "cstaInsight" "CSTA Insight")
+INCLUDE(CPack)
+
+ENDIF (WITH_CSTAV1)
diff --git a/cstav1/Call.h b/cstav1/Call.h
new file mode 100644 (file)
index 0000000..355eb4c
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __CALL_H__
+
+/**
+ *
+ */
+class Call {
+  public:
+    enum Type 
+    {
+      UNKNOWN,
+      CSTA,
+      SIP
+    };
+
+    Call(std::string id, Type t = UNKNOWN) : m_Type(t), m_Id(id) {};
+    Call(const Call &c) : m_Type(c.Type), m_Id(c.m_Id)  {};
+    virtual ~Call() {} ;
+
+    // set get
+    Type get_Type() const;
+    void set_Type(Type t) {m_Type = t;};
+
+    std::string get_CallId() const;
+    void        set_CallId(std::string &s) {m_Id = s;};
+  protected:
+    Type        m_Type;
+    std::string m_Id; // Call Identifier, can be string for tags, and an integer or OCTET STRING for CSTA
+};
+#endif
diff --git a/cstav1/Controler.cpp b/cstav1/Controler.cpp
new file mode 100644 (file)
index 0000000..a95b699
--- /dev/null
@@ -0,0 +1,1127 @@
+#include <iostream>
+#include <cstdio>
+#include <iomanip>
+#include <sstream>
+#include <algorithm>
+#include <math.h>
+
+#include <pcap/pcap.h>
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Text_Buffer.H>
+
+#include "Pcap.h"
+#if defined(__WIN32__) || defined(_WINDOWS)
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <CstaInsightLog.h>
+#include "TLMsg.h"
+
+#include "Model.h"
+#include <SequenceView.h>
+#include <HeaderView.h>
+#include <FL/fl_draw.H>
+
+//Asn1
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+// CSTA Stubs
+#include "Rose_Apdu.h"
+#include "CSTA_event.h"
+#include "ACSE_1.h"
+#include "CSTA_MSG.h"
+
+#include "Controler.h"
+
+
+#include "Rose_Apdu.hpp"
+#include "CSTA_event.hpp"
+
+Controler::Controler(Model *m)
+    : m_Model(m),
+    m_SequenceUi(NULL),
+    m_HeaderUi(NULL)
+{
+  m_Events[2] = std::string("conferenced");
+  m_Events[3] = std::string("connectionCleared");
+  m_Events[4] = std::string("delivered");
+  m_Events[5] = std::string("diverted");
+  m_Events[6] = std::string("established");
+  m_Events[7] = std::string("failed");
+  m_Events[8] = std::string("held");
+  m_Events[9] = std::string("networkReached");
+  m_Events[10] = std::string("originated");
+  m_Events[11] = std::string("queued");
+  m_Events[12] = std::string("retrieved");
+  m_Events[13] = std::string("serviceInitiated");
+  m_Events[14] = std::string("transfered");
+  m_Events[101] = std::string("callInformation");
+  m_Events[102] = std::string("doNotDisturb");
+  m_Events[103] = std::string("forwarding");
+  m_Events[104] = std::string("messageWaiting");
+  m_Events[174] = std::string("maintenance");
+  m_Events[401] = std::string("privateEvent");
+  m_Events[301] = std::string("backInService");
+  m_Events[302] = std::string("outOfService");
+
+  m_Ops[10] = std::string("makeCall");
+  m_Ops[12] = std::string("queryDevice");
+  m_Ops[13] = std::string("reconnectCall");
+  m_Ops[14] = std::string("retrieveCall");
+  m_Ops[15] = std::string("setFeature");
+  m_Ops[16] = std::string("tranferCall");
+  m_Ops[2] = std::string("answerCall");
+  m_Ops[5] = std::string("clearConnection");
+  m_Ops[7] = std::string("consultationCall");
+  m_Ops[8] = std::string("divertCall");
+  m_Ops[9] = std::string("holdCall");
+  m_Ops[51] = std::string("escapeService");
+  m_Ops[71] = std::string("monitorStart");
+  m_Ops[52] = std::string("systemStatus");
+  m_Ops[74] = std::string("snapshotDevice");
+  m_Ops[101] = std::string("101");
+  m_Ops[107] = std::string("107xxx");
+  m_Ops[235] = std::string("changeConnectionInformation");
+
+}
+    
+Controler::~Controler()
+{
+}
+
+void
+Controler::load(const char *filename,const char *expression)
+{
+    std::string fn(filename);
+    Pcap cap(fn);
+    Packet packet;
+
+    if (expression != NULL)
+    {
+      cap.set_filter(expression);
+    }
+    // In case the stack is not empty
+    m_SizeStack = std::deque<int>();
+    
+
+    while (cap.next(packet) == true)
+    {
+      long plength= 0;
+      const struct sniff_tcp *tcp = packet.get_tcp();
+      const struct sniff_udp *udp = packet.get_udp(); 
+      unsigned short sport = 0,dport=0;
+
+      const unsigned char *data =packet.get_payload(plength);
+      if (tcp) 
+      {
+        sport = htons(tcp->th_sport);
+        dport = htons(tcp->th_dport);
+        CI_LOG_DEBUG("%lu.%lu Controler::load TCP sport=%d dport=%d payload len=%ld",
+                packet.get_seconds()
+                ,packet.get_miliseconds()
+                ,sport
+                ,dport
+                ,plength
+                );
+      } else if (udp) {
+        sport = htons(udp->sport);
+        dport = htons(udp->dport);
+        CI_LOG_DEBUG("%lu.%lu Controler::load UDP sport=%d dport=%d payload len=%ld",
+                packet.get_seconds()
+                ,packet.get_miliseconds()
+                ,sport
+                ,dport
+                ,plength
+                );
+      }
+
+      if (plength > 0)
+      {
+        char *ld = (char *)data;
+        std::stringstream ss;
+        ss.rdbuf()->sputn(ld,plength);
+     
+        if ((sport == 2555) ||( dport == 2555 )) {
+          parse_csta(packet,ss,plength);
+        } else if ((sport ==5059) || (dport == 5059) || (dport == 5060) || (sport == 5060)) {
+          //SIP Packet 
+          parse_sip(packet,ss);
+        } else if ( (sport == 8894) || (dport == 8894) || (dport == 56000) || (sport == 56000)  ) 
+        {
+          // OTS message I think mainly soap
+          if (plength > 6)
+              parse_ots(packet,ss);
+        }
+#if 0
+        if (m_DumpHex->value() )
+          for (int i = 0 ; i < plength ; i++)
+          {
+            printf("%02x ",data[i]); 
+          }
+#endif
+        //std::cout<<"\n";
+      }
+
+    }
+    if (m_Model)
+    {
+        std::cout<<"Controler::load tl_count="<<m_Model->tl_count()<<std::endl;
+    }
+}
+
+void
+Controler::close()
+{
+  m_Model->clean();
+    ;
+}
+
+
+void 
+Controler::onSelectTree()
+{;
+}
+void Controler::onSelectSequence()
+{
+    ;
+}
+
+
+void 
+Controler::parse_sip(const Packet &packet,std::stringstream &is)
+{;
+    const struct sniff_udp *udp = packet.get_udp(); 
+    const struct sniff_tcp *tcp = packet.get_tcp();
+    const struct sniff_ip  *ip  = packet.get_ip();
+    unsigned short sport,dport;
+    bool is_notify = false;
+    bool is_xml    = false;
+    int  length    = 0;
+    size_t found   = 0;
+    char buf[64];
+    memset(buf,0x00,64);
+    CI_LOG_DEBUG("Controler::parse_sip PROCESS size=%ld",
+            is.str().size());
+    std::stringstream ss;
+    std::string fline,line;
+    ss.str("");
+    // get first line
+    std::getline(is,fline,'\r');
+    is.seekg(0);
+    std::replace(fline.begin(),fline.end(),'/','.');
+
+    if (fline.find("NOTIFY") != std::string::npos)
+      is_notify = true;
+
+    if (udp) {
+      sport = htons(udp->sport);
+      dport = htons(udp->dport);
+    } else if (tcp)
+    {
+        sport = htons(tcp->th_sport);
+        dport = htons(tcp->th_dport);
+
+    } else {
+      CI_LOG_WARN("Controler::parse_sip HOHO SIP nor UDP neither TCP");
+    }
+
+    ss<<" "<<fline;
+
+   Timeline tld(ip->ip_dst,"");
+   Timeline tls(ip->ip_src,"");
+   CI_LOG_DEBUG("Controler::parse_sip PROCESS create TLMsg=%s size=%ld"
+           , fline.c_str()
+           , fline.size());
+   if (fline.size() < 7) 
+   {
+       fline.assign("sip wierd ");
+   }
+   TLMsg *msg = new TLMsg(packet,fline);
+   msg->msg_type(TLMsg::SIP);
+   ss.str("");
+   ss<<is.str()<<std::endl;
+   msg->m_content = ss.str();
+   if (m_Model) 
+   {
+       
+       m_Model->add_TLMsg(msg,tls,tld);
+   }
+#if 0           
+
+    // Add packet in sequence
+
+    // Ok parser data and check if it's a XML message
+    while (! std::getline(is,line,'\n').eof() )
+    {
+      std::replace(line.begin(),line.end(),'\r','\n');
+
+      if ( (found =line.find("Content-Length:")) != std::string::npos)
+      {
+        std::cout<<"Found Length : "<<line<<std::endl;
+        found = line.find(":");
+        // Found length extract
+        length =atoi(line.substr(found+1).c_str()); 
+      }
+      if ( (found =line.find("Content-Type:")) != std::string::npos)
+      {
+        if (line.find("application/xml") != std::string::npos)
+          is_xml = true;
+      }
+      if ( line.size()==1) {
+        //time to break;
+        break;
+      }
+      
+    }
+    if (length && is_notify && is_xml)
+    {
+      std::cout<<"OTS: OK Got length="<<length<<std::endl;
+      XMLMessage msg(tree,item);
+      msg.Create();
+
+      void *p = msg.GetBuffer(length);
+      is.read((char *)p,length);
+      std::cout<<"OTS: Read buffer to be parsed len="<<length<<std::endl;
+      msg.ParseBuffer(length);
+      
+    } else if (length == 0) {
+      // Length is 0 don't do any thing.
+      std::cout<<"Length is 0 don't print any thing."<<std::endl;
+    } else {
+      ss.str("");
+      std::cout<<" BAD len=0"<<std::endl;
+      ss<<is.str()<<std::endl;
+      m_Editor->insert(ss.str().c_str());
+    }
+#endif
+}
+void 
+Controler::parse_ots(const Packet &packet,std::stringstream &is)
+{
+    const struct sniff_tcp *tcp = packet.get_tcp(); 
+    const struct sniff_ip  *ip  = packet.get_ip();
+    unsigned short sport,dport;
+
+    char buf[64];
+    memset(buf,0x00,64);
+
+    std::stringstream ss;
+
+    sport = htons(tcp->th_sport);
+    dport = htons(tcp->th_dport);
+
+    ss.str(""); 
+    strcpy(buf,inet_ntoa(ip->ip_src)); 
+
+
+    //Fl_Tree_Item *item = tree->add("/XML");
+      
+
+    Timeline tld(ip->ip_dst,"");
+    Timeline tls(ip->ip_src,"");
+    TLMsg *msg = new TLMsg(packet,"XML ");
+    ss.str("");
+    CI_LOG_DEBUG("Controler::parse_ots");
+    ss<<is.str()<<std::endl;
+    msg->msg_type(TLMsg::SOAP_RESPONSE);
+    msg->m_content = ss.str();
+    //XMLMessage msg(tree,item);
+    //msg.Create();
+    std::string line;
+    size_t found;
+    int length = 0;
+    while (! std::getline(is,line,'\n').eof() )
+    {
+      std::replace(line.begin(),line.end(),'\r','\n');
+
+      if ( (found =line.find("Content-Length:")) != std::string::npos)
+      {
+        CI_LOG_DEBUG("Controler::parse_ots Found Length : %s",line.c_str());
+        found = line.find(":");
+        // Found length extract
+        length =atoi(line.substr(found+1).c_str()); 
+      }
+      if ( (found =line.find("SOAPAction:")) != std::string::npos)
+      {
+        CI_LOG_DEBUG("Controler::parse_ots Found Action : %s",line.c_str());
+        found = line.find(":");
+        // Found length extract
+        std::string soapaction(line.substr(found+1));
+        std::replace(soapaction.begin(),soapaction.end(),'\r',' ');
+        std::replace(soapaction.begin(),soapaction.end(),'\n',' ');
+        std::replace(soapaction.begin(),soapaction.end(),'\"',' ');
+        msg->msg_type(TLMsg::SOAP_REQUEST);
+        msg->name.append(soapaction.c_str()); 
+      }
+      if ( line.size()==1) {
+        //time to break;
+        break;
+      }
+      // Chunk XML
+      if (line.find("<?xml version=\"1.0\"") != std::string::npos)
+      {
+        int pos = is.tellg();
+        //void *p = msg.GetBuffer(is.str().size());
+        msg->msg_type(TLMsg::ICS_EVENT);
+        
+        long toparse = is.str().size() -pos;
+        //is.read((char *)p,is.str().size()-pos);
+        CI_LOG_DEBUG("Controler::parse_ots Read Buffer to be parsed chunk len=%ld"
+                , is.str().size());
+        //msg.ParseBuffer(is.str().size()-pos);
+#if 0
+        long index = msg.GetCurrentByteIndex();
+        if (index < toparse)
+        {
+            std::string notparsed((const char *)p+index,toparse-index);
+
+            m_Editor->insert("\nUNPARSED DATA\n");
+            m_Editor->insert(notparsed.c_str());
+        }
+#endif
+      }
+      
+    }
+      //m_Editor->insert("\n");
+    if (length)
+    {
+      CI_LOG_DEBUG("Controler::parser_ots : OK got length=%ld",length);  
+      CI_LOG_DEBUG("Controler::parser_ots : Read buffer to be parsed len=%ld"
+              , length);  
+      
+    } else 
+    {
+      CI_LOG_WARN("Controler::parse_ots: BAD len=0 true for chunk");
+    }
+   if (m_Model) 
+   {
+       m_Model->add_TLMsg(msg,tls,tld);
+   }
+    ;
+}
+
+
+void 
+Controler::parse_csta(const Packet &packet,std::stringstream &is,long read_len)
+{
+    int len = 0;
+    const struct sniff_tcp *tcp = packet.get_tcp(); 
+    const struct sniff_ip  *ip  = packet.get_ip();
+    unsigned short sport,dport;
+    char buf[64];
+    memset(buf,0x00,64);
+
+    sport = htons(tcp->th_sport);
+    dport = htons(tcp->th_dport);
+    strcpy(buf,inet_ntoa(ip->ip_src));
+
+
+    unsigned char bl[3];
+
+
+    while (  !is.eof() /*is.good()*/)
+    {
+      unsigned int low = 0,high = 0;
+      int at = is.tellg();
+      memset(bl,0x00,3);
+      is.read((char *)bl,2);
+      low = bl[0];
+      high = bl[1];
+      len = (unsigned short )bl[1] | ((unsigned short)bl[0] << 8);
+      CI_LOG_DEBUG("\n\n * HEADER b[0]=%u %u LEN=%ld at=%x",
+              low
+              ,high
+              ,len
+              ,at);
+      if ( ((  (bl[0] & 0xf8) == 0xa0) || ((bl[0] & 0xf8 ) == 0x60 )) && !m_SizeStack.empty() ) 
+      { // Probably a packet 
+        CI_LOG_DEBUG(" * HEADER pop length current=%ld new of m_SizeStack.front=%d or m_SizeStack.back=%d"
+                , len
+                , m_SizeStack.front()
+                , m_SizeStack.back());
+        len = m_SizeStack.back();
+        m_SizeStack.pop_back();
+        is.seekg(at); // Go back to initial position
+      } else {
+        // Prob next value if its a packet or another length
+        unsigned char c;
+        if (is.eof() || (at == -1))
+        {
+          CI_LOG_DEBUG(" *  Probabl nothing todo at == -1 or eof");
+          // On windows when at == -1 is.eof is not set
+          if (at == -1)
+            break;
+        } else {
+          c = is.get();
+          is.putback(c);
+          if ( ! ( ( (c & 0xf8) == 0xa0)  || ((c & 0xf8) == 0x60 )))  
+          { // Next Is not a  packet stack the length and restart reading
+            CI_LOG_DEBUG("\n * Push and read next c=%0x LEN=%ld at=%0x"
+                    , c
+                    , len
+                    , at);
+            CI_LOG_DEBUG(" stack empty = %d Size=%ld"
+                    , m_SizeStack.empty()
+                    , m_SizeStack.size());
+            m_SizeStack.push_back(len);
+            continue;
+          } else if (! m_SizeStack.empty())
+          { // Why should I pop the length ?
+            CI_LOG_DEBUG(" * HEADER use length current=%d queue len=%d"
+                    ,len
+                    ,m_SizeStack.front()
+                    );  
+          }
+        }
+      }
+
+      memset(bl,0x00,3);
+      if ( (len > 0) && (len < 4096))
+      {
+        int before,after;
+        // Top level that must be used
+        CSTA_MSG::CSTA_msg message;
+
+        //asn1::context ctx(len+1);
+        asn1::streams::ber ctx(len+1);
+        before = is.tellg();
+        is.read((char *)ctx.buffer(),len);
+        after = is.tellg();
+        if ((after - before ) != len)
+        {
+          CI_LOG_ERROR(" ERROR did not read right length %d expected: %ld only: %ld "
+                  ,(after-before)
+                  ,len
+                  ,is.gcount());
+        } else
+        {
+          CI_LOG_DEBUG(" * READ LENGTH %d",(after-before));
+        }
+        //int result = pdu.codec(ctx,pdu,asn1::CODEC_DECODE);
+        //int result = message.codec(ctx,message,asn1::CODEC_DECODE);
+        int result = message.decode(ctx);
+
+
+        if (( (ctx.nb_read_bits()>>3) == len) || (ctx.nb_read_bits() >>3) == read_len)
+        {
+            if (( (ctx.nb_read_bits()>>3) != len) || (ctx.nb_read_bits() >>3) == read_len)
+            {
+              CI_LOG_DEBUG(" * WIERD CASE may be I should push back len : %d expected: %d payload: %d analysed: "
+                      ,( after-before)
+                      , len
+                      , read_len
+                      , (ctx.nb_read_bits()>>3));
+            }
+            if (message.tag().byte()     == asn1::tag(1,0,true).byte()
+                    || message.tag().byte() == asn1::tag(1,1,true).byte() 
+                    || message.tag().byte() == asn1::tag(1,2,true).byte()
+                       )
+            {
+                   std::stringstream ss,stitle;
+                                  //int invokeID = .retError.invokeID;
+                                  stitle<<"acse ()";
+
+                                  ss<<message.get_aPDU_acse()<<std::endl;
+                                   Timeline tld(0,dport,"");
+                                   Timeline tls(0,sport,"");
+                                   TLMsg *msg = new TLMsg(packet,stitle.str().c_str());
+                                   msg->m_content = ss.str();
+                                   switch(message.get_aPDU_acse().get_kind())
+                                   {
+                                       case ACSE_1::ACSE_apdu::typeof_aarq :
+                                           msg->msg_type(TLMsg::CSTA_REQUEST);
+                                           break;
+                                       case ACSE_1::ACSE_apdu::typeof_aare :
+                                           msg->msg_type(TLMsg::CSTA_RESPONSE);
+                                           break;
+                                       case ACSE_1::ACSE_apdu::typeof_rlrq :
+                                           msg->msg_type(TLMsg::CSTA_REQUEST);
+                                           break;
+                                       case ACSE_1::ACSE_apdu::typeof_rlre :
+                                           msg->msg_type(TLMsg::CSTA_RESPONSE);
+                                           break;
+                                       default:
+                                           msg->msg_type(TLMsg::CSTA_REJECT);
+                                   }
+                                   if (m_Model) 
+                                   {
+                                       m_Model->add_TLMsg(msg,tls,tld);
+                                   }
+
+           } else 
+           {
+               Rose_Apdu::RoseAPDU &pdu= message.get_aPDU_rose();
+               switch (pdu.get_kind())
+               {
+                              case Rose_Apdu::RoseAPDU::typeof_invoke:
+                                CI_LOG_DEBUG("\tGot invoke ID=%ld",pdu.get_invoke().invokeID.get_sys_value());  
+                                if (pdu.get_invoke().operationValue.get_kind() == Remote_Operations_Information_Objects::OpCode::typeof_local)
+                                {
+                                  Remote_Operations_Information_Objects::IOPERATION::ptr op = pdu.get_invoke().argument;
+                                   // asn1::Object * _o = pdu.get_invoke().argument;
+                                   // Remote_Operations_Information_Objects::IOPERATION *op =
+                                   //   dynamic_cast<Remote_Operations_Information_Objects::IOPERATION *>(_o);
+                                    
+                                    doInvoke( packet
+                                           , pdu.get_invoke().operationValue.get_local().get_sys_value()
+                                           , pdu.get_invoke().invokeID.get_sys_value(),op);
+
+                                } else {
+                                
+                                }
+                                //  std::cout<<std::endl;
+                                break;
+                            case Rose_Apdu::RoseAPDU::typeof_retResult:
+                                CI_LOG_DEBUG("\tGot resultID=%ld",pdu.get_retResult().invokeID.get_sys_value());
+                               if ( (! pdu.get_retResult().anonymousSEQUENCE.is_nul()) && 
+                                   (pdu.get_retResult().anonymousSEQUENCE->operationValue.get_kind() == Remote_Operations_Information_Objects::OpCode::typeof_local))
+                                {
+                                  std::stringstream ss,ss1;
+                                 
+                                  if (m_Ops[pdu.get_retResult().anonymousSEQUENCE->operationValue.get_local().get_sys_value()].size() >0)
+                                  {
+                                    ss1<<"/SR "<<m_Ops[pdu.get_retResult().anonymousSEQUENCE->operationValue.get_local().get_sys_value()]<<" (id="<<pdu.get_retResult().invokeID.get_sys_value()<<")";
+                                  } else {
+                                    ss1<<"/SR ("<<pdu.get_retResult().anonymousSEQUENCE->operationValue.get_local().get_sys_value()<<")";
+                                  }
+                                  // complete other text fields
+                                       
+                                  ss<<pdu.get_retResult()<<std::endl;
+
+
+                                   Timeline tld(0,dport,"");
+                                   Timeline tls(0,sport,"");
+                                   TLMsg *msg = new TLMsg(packet,ss1.str().c_str());
+                                   msg->msg_type(TLMsg::CSTA_RESPONSE);
+                                   msg->m_content = ss.str();
+                                   if (m_Model) 
+                                   {
+                                       m_Model->add_TLMsg(msg,tls,tld);
+                                   }
+
+                                } else
+                               {
+                                 std::cout<<"Got Result anonymous is_nul ? "<<pdu.get_retResult().anonymousSEQUENCE.is_nul()<<std::endl;
+                               }  
+                                break;
+                            case Rose_Apdu::RoseAPDU::typeof_retError:
+                                {
+                                  std::stringstream ss,stitle;
+                                  int invokeID = pdu.get_retError().invokeID.get_sys_value();
+                                  stitle<<"retError ("<<invokeID<<")";
+
+                                  ss<<pdu.get_retError()<<std::endl;
+                                   Timeline tld(0,dport,"");
+                                   Timeline tls(0,sport,"");
+                                   TLMsg *msg = new TLMsg(packet,stitle.str().c_str());
+                                   msg->m_content = ss.str();
+                                   msg->msg_type(TLMsg::CSTA_RESPONSE_ERROR);
+                                   if (m_Model) 
+                                   {
+                                       m_Model->add_TLMsg(msg,tls,tld);
+                                   }
+
+                                  
+                                }
+                                break;
+                            case Rose_Apdu::RoseAPDU::typeof_reject:
+                              {
+                                std::stringstream ss,stitle;
+                                
+                                stitle<<"Reject "<<pdu.get_reject().invokeID;
+                                ss<<pdu.get_reject()<<std::endl;
+                                
+                                Timeline tld(0,dport,"");
+                                Timeline tls(0,sport,"");
+                                TLMsg *msg = new TLMsg(packet,stitle.str().c_str());
+                                
+                                msg->msg_type(TLMsg::CSTA_REJECT);
+                                msg->m_content = ss.str();
+                                
+                                if (m_Model) 
+                                {
+                                   m_Model->add_TLMsg(msg,tls,tld);
+                                }
+
+                              }
+                              break;
+                            default:
+                            ;
+             
+               } /* end switch */
+           }
+        } else
+        {
+          std::stringstream msg;
+          msg<<"Err Pdu len="<<len<<" read:"<<(ctx.nb_read_bits()>>3)<<"";
+          // not properly decoded see why.
+ //         tree->add(msg.str().c_str());
+          CI_LOG_DEBUG("\n * %s",msg.str().c_str());
+          Timeline tld(0,dport,"");
+          Timeline tls(0,sport,"");
+          TLMsg *tmsg = new TLMsg(packet,msg.str().c_str());
+          if (m_Model) 
+          {
+               tmsg->m_content.resize(len *3+2);
+               char * buf = const_cast<char *>(tmsg->m_content.c_str());
+               for (int i = 0 ; i < len ; i++)
+               {
+                   char b[4];
+                   sprintf(b,"%02x ",ctx.buffer()[i]);
+                   strcat(buf,b);
+               }
+               strcat(buf,"\n");
+               m_Model->add_TLMsg(tmsg,tls,tld);
+          }
+        }
+      } else {
+        int at = is.tellg();
+        if (at != -1 )
+        {
+         CI_LOG_ERROR(" * BAD LENGTH %d at=%0x",len,at); 
+        }
+      }
+    }
+
+}
+
+
+    
+void 
+Controler::doInvoke(const Packet &packet,int opId,int InvokeId,Remote_Operations_Information_Objects::IOPERATION *op)
+{
+    
+    const struct sniff_tcp *tcp = packet.get_tcp(); 
+    const struct sniff_ip  *ip  = packet.get_ip();
+    unsigned short sport,dport;
+
+    char buf[64];
+    memset(buf,0x00,64);
+
+    sport = htons(tcp->th_sport);
+    dport = htons(tcp->th_dport);
+    strcpy(buf,inet_ntoa(ip->ip_src));
+
+    CI_LOG_DEBUG("Controler::doInvoke Process invoke request opId=%d invokeId=%d",opId,InvokeId);
+
+    if (opId == 21)
+    {
+      std::stringstream ss,ss1;
+                                  // Get OPERATION 
+      CSTA_event::cSTAEventEvent *event;
+      event = dynamic_cast<CSTA_event::cSTAEventEvent *>(op); 
+                                  // Get OBJECT-TYPE
+      CSTA_event::CSTAEventReportArgument report; 
+      event->get_ArgumentType(report);
+      CI_LOG_DEBUG("Got type info=%ld",report.eventType.get_local().get_sys_value());
+      Remote_Operations_Information_Objects::IOBJECT_TYPE *event_obj;
+      asn1::Object * _o = report.eventInfo;
+      event_obj = dynamic_cast<Remote_Operations_Information_Objects::IOBJECT_TYPE *>(_o);
+      ss.str(""); ss1.str("");
+      std::string s  = report.crossRefIdentifier.get_sys_value();
+      unsigned char a0,a1,a2,a3;
+      a0 =  (unsigned short)s[0];
+      a1 =  (unsigned short)s[1];
+      a2 =  (unsigned short)s[2];
+      a3 =  (unsigned short)s[3];
+      int crid = (a2<<8) | a3;
+    
+      std::string addons;
+      Timeline tld(crid,dport,"");
+      Timeline tls(0,sport,"");
+      
+      if (m_Events[report.eventType.get_local().get_sys_value()].size()>0 )
+      {
+        ss1<<"/"<<m_Events[report.eventType.get_local().get_sys_value()]<<"("<<crid<<")";
+      } else
+        ss1<<"/Event_("<<crid<<")"<<report.eventType.get_local();
+      addons = ss1.str();
+      TLMsg *msg = NULL;
+      if (m_Model)
+          m_Model->new_TLMsg(packet,&msg);
+      doInvokeEvent(report.eventType.get_local().get_sys_value()
+                  ,event_obj,tld,addons,msg);
+      //TLMsg *msg = new TLMsg(packet,ss1.str().c_str());
+      //TLMsg *msg = new TLMsg(packet,addons);
+      msg->name = addons;
+      msg->msg_type(TLMsg::CSTA_EVENT);
+      
+      ss<<report<<std::endl;
+       msg->m_content = ss.str();
+      if (m_Model)
+          m_Model->add_TLMsg(msg,tls,tld);
+#if 0
+        
+      Fl_Tree_Item *item = tree->add(ss1.str().c_str());
+      // Here we can decide to add sub stree information and build a string for the sequence diagram
+      std::string addons;
+      addons = m_Events[report.eventType.local];
+      ProcessEvent(report.eventType.local,event_obj,item,addons);
+        
+      int lines = m_Editor->count_lines(0,m_Editor->buffer()->length(),1);
+                                   
+      item->user_data((void *)lines);
+      Fl_Text_Buffer *buffer = m_Editor->buffer();
+      m_Sequence->add_event(crid,packet,addons.c_str(),item);
+      assign_icons(item,1);
+                                 
+      ss<<" == From : "<<buf<<":"<<sport<<" To "<<inet_ntoa(ip->ip_dst)<<":"<<dport<<" ========================================="<<std::endl;
+      ss<<ss1.str()<<std::endl;
+      ss<<report<<std::endl;
+                                  // char *dst = (char *)malloc(ss.str().size()*2);
+                                  // fl_utf8froma(dst,ss.str().size()*2,ss.str().c_str(),ss.str().size());
+                                  //m_Buffer->append(ss.str().c_str());
+      m_Editor->insert(ss.str().c_str());
+#endif
+    } else {
+      std::stringstream ss,ss1;
+      asn1::Object *obj= dynamic_cast<asn1::Object *>(op);
+      Timeline tld(0,dport,"");
+      Timeline tls(0,sport,"");
+      if (m_Ops[opId].size() > 0)
+      {
+        ss1<<"/SReq "<<m_Ops[opId]<<" (id="<<(long)InvokeId<<")";
+      } else {
+        ss1<<"/Ope_("<<opId<<")";
+      }
+      TLMsg *msg = new TLMsg(packet,ss1.str().c_str());
+      msg->msg_type(TLMsg::CSTA_REQUEST);
+      if (obj != NULL)
+        obj->printf(ss);
+      msg->m_content =ss.str();
+      if (m_Model)
+          m_Model->add_TLMsg(msg,tls,tld);
+#if 0
+      Fl_Tree_Item *item = tree->add(ss1.str().c_str());
+
+      int lines = m_Editor->count_lines(0,m_Editor->buffer()->length(),1);
+                                   
+      item->user_data((void *)lines);
+      Fl_Text_Buffer *buffer = m_Editor->buffer();
+      m_Sequence->add_invoke(packet,ss1.str().c_str(),item);
+
+      assign_icons(item,0);
+      ss<<" == From : "<<buf<<":"<<sport<<" To "<<inet_ntoa(ip->ip_dst)<<":"<<dport<<" ========================================="<<std::endl; 
+      ss<<ss1.str()<<std::endl;
+      //ss<<" ==========================================="<<std::endl;
+      if (obj != NULL)
+        obj->printf(ss);
+#endif
+    }
+        ;
+}
+
+
+void 
+Controler::doInvokeEvent(int id,Remote_Operations_Information_Objects::IOBJECT_TYPE *_evt,Timeline &tld,std::string &str,TLMsg *_msg)
+{
+    switch (id)
+    {
+      case 3: //connectionCleared
+      {
+        CSTA_event::connectionClearedEvent *p = dynamic_cast<CSTA_event::connectionClearedEvent *>(_evt);
+        CSTA_event::ConnectionClearedEventInfo report; 
+        p->get_ArgumentType(report);
+        std::string octs = report.droppedConnection.call->get_sys_value();
+       std::string local(" Call=");
+        callToString(octs,local);
+        str+=local;
+        callToString(octs,_msg->m_callid);
+        //tree->add(item,local.c_str());
+        //tree->close(item);
+        std::ostringstream oss; oss << report.localConnectionInfo;
+        str+= std::string(" lCI=")+oss.str();
+      }
+      break;
+
+      case 4: //deliveredEvent
+      {
+        CSTA_event::deliveredEvent *p = dynamic_cast<CSTA_event::deliveredEvent *>(_evt);
+        CSTA_event::DeliEstaEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Delivered for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        
+       std::ostringstream oss ; oss<< report.localConnectionInfo;
+        str+= std::string(" lCI=") + oss.str();
+       if (**report.localConnectionInfo == CSTA_connect::LocalConnectionState::alerting)
+       {
+             std::string local;
+             if (report.alertingDevice.get_kind() == CSTA_device::SubjectDeviceID::typeof_deviceIdentifier)
+             {
+                switch(report.alertingDevice.get_deviceIdentifier().get_kind())
+                {
+                      case CSTA_device::ExtendedDeviceID::typeof_deviceIdentifier:
+                      break;
+                      case CSTA_device::ExtendedDeviceID::typeof_implicitPublic:
+                      break;
+                      case CSTA_device::ExtendedDeviceID::typeof_explicitPublic:
+                      break;
+                      case CSTA_device::ExtendedDeviceID::typeof_implicitPrivate:
+                      {
+                        std::string result = report.alertingDevice.get_deviceIdentifier().get_implicitPrivate().get_sys_value();
+                        local = std::string(" initiating=") + result;
+                        std::replace(result.begin(),result.end(),'\n',' ');
+                        tld.set_device(result);
+                        //tree->add(item,local.c_str());
+                        str+= local;
+                      }
+                      break;
+                      case CSTA_device::ExtendedDeviceID::typeof_explicitPrivate:
+                      break;
+                      default:
+                      ;      
+                }
+             }
+        }
+
+      }
+      break;
+
+      case 5: //divertedEvent
+      {
+        CSTA_event::divertedEvent *p = dynamic_cast<CSTA_event::divertedEvent *>(_evt);
+        CSTA_event::DivertedEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Diverted %s",report.connection->call->get_sys_value().c_str());
+        std::string octs = report.connection->call->get_sys_value();
+        callToString(octs,_msg->m_callid);
+        
+      }
+      break;
+      case 6: //establishedEvent
+      {
+        CSTA_event::establishedEvent *p = dynamic_cast<CSTA_event::establishedEvent *>(_evt);
+        CSTA_event::DeliEstaEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Established for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        std::ostringstream oss ; oss<< report.localConnectionInfo;
+        str+= std::string(" lCI=") + oss.str();
+
+
+      }
+      break;
+      case 7: //failedEvent
+      {
+        CSTA_event::failedEvent *p = dynamic_cast<CSTA_event::failedEvent *>(_evt);
+        CSTA_event::FailNetwOrigEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Failed for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        callToString(octs,_msg->m_callid);
+
+      }
+      break;
+      case 8: //heldEvent
+      {
+        CSTA_event::heldEvent *p = dynamic_cast<CSTA_event::heldEvent *>(_evt);
+        CSTA_event::HeldEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event held for call %s",report.heldConnection.call->get_sys_value().c_str());
+        std::string octs = report.heldConnection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        std::ostringstream oss ; oss<< report.localConnectionInfo;
+        str+= std::string(" lCI=") + oss.str();
+        
+      }
+      break;
+      case 9: //networkReachedEvent
+      {
+        CSTA_event::networkReachedEvent *p = dynamic_cast<CSTA_event::networkReachedEvent *>(_evt);
+        CSTA_event::FailNetwOrigEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Network reached for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        std::ostringstream oss; oss <<report.localConnectionInfo;
+        str+= std::string(" lCI=")+oss.str();
+        
+      }
+      break;
+      case 10: //originatedEvent
+      {
+        CSTA_event::originatedEvent *p = dynamic_cast<CSTA_event::originatedEvent *>(_evt);
+        CSTA_event::FailNetwOrigEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Originated for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        std::ostringstream oss ; oss<< report.localConnectionInfo;
+        str+= std::string(" lCI=") + oss.str();
+
+
+      }
+      break;
+      case 11: //queuedEvent
+      {
+        CSTA_event::queuedEvent *p = dynamic_cast<CSTA_event::queuedEvent *>(_evt);
+        CSTA_event::QueuedEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Queued for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        std::ostringstream oss ; oss<< report.localConnectionInfo;
+        str+= std::string(" lCI=") + oss.str();
+        
+      }
+      break;
+      case 12: //retrievedEvent
+      {
+        CSTA_event::retrievedEvent *p = dynamic_cast<CSTA_event::retrievedEvent *>(_evt);
+        CSTA_event::ConnectionEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Retrieved for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        
+      }
+      break;
+      case CSTA_event::serviceInitiatedEvent::uuid : //serviceInitiatedEvent
+      {
+        CSTA_event::serviceInitiatedEvent *p = dynamic_cast<CSTA_event::serviceInitiatedEvent *>(_evt);
+        CSTA_event::ServiceInitiatedEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event Initiated for call %s",report.initiatedConnection.call->get_sys_value().c_str());
+        std::string local;
+        std::string octs = report.initiatedConnection.call->get_sys_value();
+        //std::string octs1 = report.call;
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        // convert call string to integer 
+        switch (report.initiatingDevice.get_kind())
+        {
+          case CSTA_device::ExtendedDeviceID::typeof_deviceIdentifier:
+          break;
+          case CSTA_device::ExtendedDeviceID::typeof_implicitPublic:
+          break;
+          case CSTA_device::ExtendedDeviceID::typeof_explicitPublic:
+          break;
+          case CSTA_device::ExtendedDeviceID::typeof_implicitPrivate:
+          {
+            std::string result = report.initiatingDevice.get_implicitPrivate().get_sys_value();
+            local = std::string(" initiating=") + result;
+            std::replace(result.begin(),result.end(),'\n',' ');
+            tld.set_device(result);
+            //tree->add(item,local.c_str());
+            str+= local;
+          }
+          break;
+          case CSTA_device::ExtendedDeviceID::typeof_explicitPrivate:
+          break;
+          default:
+          ;      
+        }
+        std::ostringstream oss ; 
+       if (!report.localConnectionInfo.is_nul()) {
+         oss<< (report.localConnectionInfo);
+          str+= std::string(" lCI=") + oss.str();
+       }
+        //tree->close(item);
+
+      }
+      break;
+      case 14: //transferredEvent
+      {
+        CSTA_event::transferredEvent *p = dynamic_cast<CSTA_event::transferredEvent *>(_evt);
+        CSTA_event::TransferredEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event CallInformation for call %s",report.primaryOldCall.call->get_sys_value().c_str());
+        std::ostringstream oss ; oss<< report.localConnectionInfo;
+       std::string octs;
+       //if (! report.primaryOldCall.is_nul())
+                 octs = report.primaryOldCall.call->get_sys_value();
+       str+= " PrimOldCall=";
+        callToString(octs,str);
+       if (! report.secondaryOldCall.is_nul())
+         if ( ! report.secondaryOldCall->call.is_nul())
+                 octs = report.secondaryOldCall->call->get_sys_value();
+       str+= " SecondOldCall=";
+        callToString(octs,str);
+        str+= std::string(" lCI=") + oss.str();
+       
+        //octs = report.call;
+       if (report.transferredConnections->get_kind() == CSTA_connect::ConnectionList::typeof_callinformation) {
+               CSTA_call::ConnectionID conn = report.transferredConnections->get_callinformation()[0].endpoint;
+               if (!conn.call.is_nul())
+                 octs = conn.call->get_sys_value();
+               callToString(octs,_msg->m_callid);
+       }
+        
+        
+      }
+      break;
+      case 101: //callInformationEvent
+      {
+        CSTA_event::callInformationEvent *p = dynamic_cast<CSTA_event::callInformationEvent *>(_evt);
+        CSTA_event::CallInformationEventInfo report; 
+        p->get_ArgumentType(report);
+        CI_LOG_DEBUG("Event CallInformation for call %s",report.connection.call->get_sys_value().c_str());
+        std::string octs = report.connection.call->get_sys_value();
+        str+= " Call=";
+        callToString(octs,str);
+        callToString(octs,_msg->m_callid);
+        
+      }
+      break;
+
+      case 145: //otherPrivateEvent
+      {
+        CSTA_event::otherPrivateEvent *p = dynamic_cast<CSTA_event::otherPrivateEvent *>(_evt);
+      }
+      break;
+      default:
+        _msg->m_callid = "default";
+      ;
+    }
+
+
+}
+
+
+void 
+Controler::callToString(const std::string &ins,std::string &out)
+{
+    int res = 0;
+    for (std::string::const_iterator it = ins.begin() ; 
+                     it !=  ins.end(); ++it)
+                 res = res << 8 | (unsigned char)(*it);
+
+    std::stringstream ints; ints<<res;
+    out += ints.str();
+
+}
+void 
+Controler::select(TLMsg *m)
+{
+    Model::EventType_const_iterator it = std::find_if(m_Model->evt_begin(),m_Model->evt_end(),Model::tlmsg_finder(m));
+    if (it != m_Model->evt_end() )
+    {
+       m_Model->select(m);
+    }
+}
+
diff --git a/cstav1/Controler.h b/cstav1/Controler.h
new file mode 100644 (file)
index 0000000..0e1173c
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef CONTROLER_H__
+#define CONTROLER_H__
+
+#include <stack>
+#include <queue>
+#include <deque>
+#include <map>
+#include "sigslot.h"
+
+class Controler
+{
+  public:
+    Controler(Model *m);
+    ~Controler();
+
+
+    void load(const char *fn,const char *expr = NULL);
+    void close();
+    void onSelectTree();
+    void onSelectSequence();
+    //Not sur if it's the right place.
+    void parse_sip(const Packet &packet,std::stringstream &is);
+    void parse_ots(const Packet &packet,std::stringstream &is);
+    void parse_csta(const Packet &packet,std::stringstream &is,long read_length);
+    void doInvoke(const Packet &packet,int opId,int InvokeId,Remote_Operations_Information_Objects::IOPERATION *op);
+    void doInvokeEvent(int id,Remote_Operations_Information_Objects::IOBJECT_TYPE *_evt,Timeline &tld,std::string &str,TLMsg *_m);
+    void callToString(const std::string &ins,std::string &out);
+    // Invoked when an item in the tree is selected
+    void select(TLMsg *m);
+  protected: 
+    // Owns a pointer to view and one to Model
+    Model           *m_Model;
+    SequenceView    *m_SequenceUi;
+    HeaderView      *m_HeaderUi;
+
+    std::deque<int> m_SizeStack;
+    std::map<int,std::string>  m_Events;
+    std::map<int,std::string>  m_Ops;
+
+};
+
+#endif
diff --git a/cstav1/CstaInsightLog.cpp b/cstav1/CstaInsightLog.cpp
new file mode 100644 (file)
index 0000000..18cba25
--- /dev/null
@@ -0,0 +1,2 @@
+
+int cid_level = 1;
diff --git a/cstav1/CstaInsightLog.h b/cstav1/CstaInsightLog.h
new file mode 100644 (file)
index 0000000..f0d836f
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef CSTAINSIGHT_LOG_H__
+#define CSTAINSIGHT_LOG_H__
+
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ *10000 \
+                     + __GNUC_MINOR__ * 100 \
+                     + __GNUC_PATCHLEVEL__ )
+#endif
+
+#if  defined(__APPLE__) || (GCC_VERSION > 40800)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+#if defined(_WIN32)
+# include <io.h>
+#else
+#include <string.h>
+#endif
+
+
+extern int cid_level;
+
+#if defined(__GNUC__) && defined(DEBUG)
+
+#define __MYFILE__ (strrchr(__FILE__,'/')?strrchr(__FILE__,'/')+1 : __FILE__)
+
+# define CI_LOG_DEBUG(fmt,args...) do {\
+   if (cid_level >= 7)  \
+   {   fprintf(stderr,fmt,##args);\
+        fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__); \
+   }  \
+} while (0);
+
+# define CI_LOG_INFO(fmt,args...) do {\
+   if (cid_level >= 3)  \
+   {  fprintf(stderr,fmt,##args);\
+     fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+   } \
+} while (0);
+
+# define CI_LOG_WARN(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__);\
+} while (0);
+
+# define CI_LOG_ERROR(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__);\
+} while (0);
+
+#elif defined(_WIN32) || defined(_WINDOWS)
+
+#define __MYFILE__ (strrchr(__FILE__,'/')?strrchr(__FILE__,'/')+1 : __FILE__)
+
+# define CI_LOG_DEBUG(fmt,...) do {\
+   if (cid_level >= 7)  \
+   {   fprintf(stderr,fmt,__VA_ARGS__);\
+        fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__); \
+   }  \
+  } while (0);
+
+# define CI_LOG_INFO(fmt,...) do {\
+  } while (0);
+
+# define CI_LOG_WARN(fmt,...) do {\
+   fprintf(stderr,fmt,__VA_ARGS__);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+  } while (0);
+
+# define CI_LOG_ERROR(fmt,...) do {\
+   fprintf(stderr,fmt,__VA_ARGS__);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+  } while (0);
+#else
+// Not debug  but Release Target
+# if not(defined(CI_LOG_DEBUG))
+#   define CI_LOG_DEBUG(fmt,args...) do {} while (0); 
+  //static inline void CI_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+# else
+  static inline void CI_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+# endif
+
+#define CI_LOG_INFO(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+# define CI_LOG_WARN(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+# define CI_LOG_ERROR(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+#endif
+
+#endif
diff --git a/cstav1/HeaderView.cpp b/cstav1/HeaderView.cpp
new file mode 100644 (file)
index 0000000..2a56363
--- /dev/null
@@ -0,0 +1,127 @@
+#include <iostream>
+#include <cstdio>
+#include <iomanip>
+#include <sstream>
+#include <math.h>
+// For windows
+#include <pcap/pcap.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_Preferences.H>
+
+#include "Pcap.h"
+#if defined( __WIN32__) || defined(_WINDOWS)
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "TLMsg.h"
+
+#include <HeaderView.h>
+#include <FL/fl_draw.H>
+
+#include "Model.h"
+
+
+
+HeaderView::HeaderView(int x,int y , int h, int w, const char *l)
+    : Fl_Widget(x,y,h,w,l) , m_Model(NULL)
+{
+  
+       ;
+}
+
+HeaderView::~HeaderView()
+{
+       ;
+}
+
+void HeaderView::resize(int X,int Y,int W,int H)
+{
+#if 0
+    printf("HeaderView::resize : x=%d y=%d w=%d h=%d\n",X,Y,W,H);
+#endif
+    Fl_Widget::resize(X,Y,W,H);
+    damage(FL_DAMAGE_ALL);
+}
+void 
+HeaderView::draw()
+{
+ int m_separator = 120;
+ int y_base      = 40;
+ char iPath[79];
+ Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");
+ Fl_Preferences iconPath(app,"iconPath");
+ iconPath.get("path",iPath,"",79);
+#if 0
+ printf("HeaderView:Draw x=%d y=%d\n",x(),y());
+#endif
+ std::string imgServer(iPath); imgServer.append(std::string("Server_24.png"));
+ std::string imgVT(iPath); imgVT.append("VT_24.png");
+ Fl_PNG_Image   s(imgServer.c_str());
+ Fl_PNG_Image   sip(imgVT.c_str());
+ if (m_Model)
+ {
+     int i = 0;
+     Timeline        tl_csta = Timeline(0,m_Model->portCsta(),"");
+     //
+     fl_color(FL_BLACK);
+     fl_font(0,8);
+     for (Model::TimelineType_const_iterator it = m_Model->tl_begin();
+             it != m_Model->tl_end();
+             ++it)
+     {
+         if ((*it) == tl_csta) {
+            s.draw(x()+140+i*120,y()+5);
+            fl_draw((*it).name(),x()+130 + i*m_separator,y()-2+y_base);
+         } else 
+         {
+            std::string dev;
+            (*it).get_device(dev);
+            sip.draw(x()+140+i*120 ,y()+5);
+            if (dev.size() > 1) {
+              fl_draw(dev.c_str(),x()+170 + i*m_separator,y()-2+20);
+            }
+            fl_draw((*it).name(),x()+130 + i*m_separator,y()-2+y_base);
+         }
+        i++;
+     }
+     size(150 + i*m_separator + 50,h());
+ } else
+ {
+       s.draw(x()+140,y()+5);
+   
+    for (int i = 1 ; i < 5; i++)
+         sip.draw(x()+140+i*120 ,y()+5);
+ }
+}
+
+void 
+HeaderView::model(Model *m) 
+{
+    m_Model = m;
+    m->subscribe(this);
+};
+
+void 
+HeaderView::onClean()
+{
+    std::cout<<"HeaderView::onClean"<<std::endl;
+    damage(FL_DAMAGE_ALL);
+    //redraw();
+    parent()->redraw();
+}
+
+void 
+HeaderView::onAdd(TLMsg * ,Timeline &tls,Timeline &tld)
+{
+    ;
+  this->damage(FL_DAMAGE_ALL);
+  this->parent()->redraw();
+}
diff --git a/cstav1/HeaderView.h b/cstav1/HeaderView.h
new file mode 100644 (file)
index 0000000..6a8f3fb
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef HEADERVIEW_H__
+#define HEADERVIEW_H__
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <stdlib.h>
+#include <time.h>
+
+#if defined(__WIN32__) || defined(_WINDOWS)
+#include <pcap/pcap.h>
+#endif
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include <FL/Fl_Scroll.H>
+#include "Timeline.h"
+// Packet information ...
+#include "Pcap.h"
+#if defined(__WIN32__) || defined (_WINDOWS)
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "TLMsg.h"
+#include "sigslot.h"
+#include "Observer.h"
+
+class Model;
+
+class HeaderView : public Fl_Widget, public Observer
+{
+  public:
+
+    HeaderView(int x,int y , int h, int w, const char *l=NULL);
+    ~HeaderView();
+
+    void draw();
+   
+    void resize(int X,int Y,int W,int H);
+
+    void model(Model *m) ;
+    void onClean();
+    void onNew(TLMsg *msg) {};
+    void onAdd(TLMsg * ,Timeline &tls,Timeline &tld);
+    void onSelected(TLMsg *msg) {};
+    inline void onScroll(int _x) { 
+       Fl_Scroll *s = dynamic_cast<Fl_Scroll *>(this->parent());
+       Fl_Scrollbar *sb = &dynamic_cast<Fl_Scroll *>(this->parent())->hscrollbar;
+       s->scroll_to(_x,s->yposition());
+       s->redraw();
+    };
+
+  protected:
+    Model   *m_Model;
+};
+
+#endif
diff --git a/cstav1/IconFactory.cpp b/cstav1/IconFactory.cpp
new file mode 100644 (file)
index 0000000..d45019c
--- /dev/null
@@ -0,0 +1,45 @@
+#include <map>
+#include <string>
+
+
+#include <FL/Fl_Image.H>
+#include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_Preferences.H>
+
+#include "IconFactory.h"
+
+IconFactory *IconFactory::m_IconFactory = NULL;
+
+IconFactory::IconFactory()
+{
+}
+
+Fl_Image *IconFactory::get_Icon(const char *n)
+{
+    if (m_IconFactory == NULL)
+    {
+        m_IconFactory = new IconFactory();
+    }
+
+    return m_IconFactory->image(n);
+
+}
+
+Fl_Image *IconFactory::image(const char *name)
+{
+    if (m_Images[name] == NULL)
+    {
+        char iPath[79];
+        // Build the picture
+        Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");
+        Fl_Preferences iconPath(app,"iconPath");
+        iconPath.get("path",iPath,"",79);
+        std::string img(iPath); 
+        
+        img.append(name);
+        m_Images[std::string(name)] = new Fl_PNG_Image(img.c_str());
+    }
+    return m_Images[name];
+}
+
+
diff --git a/cstav1/IconFactory.h b/cstav1/IconFactory.h
new file mode 100644 (file)
index 0000000..a35dc04
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef ICON_FACTORY_H__
+#define ICON_FACTORY_H__
+
+
+
+class IconFactory
+{
+  public:
+    IconFactory();
+
+    Fl_Image *image(const char *name);
+    static Fl_Image *get_Icon(const char *);
+  protected:
+
+    std::map<std::string,Fl_Image *>    m_Images;
+  private:
+    static IconFactory *m_IconFactory;
+    
+};
+
+#endif
diff --git a/cstav1/Model.cpp b/cstav1/Model.cpp
new file mode 100644 (file)
index 0000000..9d43959
--- /dev/null
@@ -0,0 +1,182 @@
+#include <algorithm>
+#include <functional>
+
+#include <fstream>
+
+#include "Model.h"
+
+
+Model::Model()
+ : m_portCsta(2555),m_portSip(5059),m_portXml(8894)
+{
+  Timeline csta(0,m_portCsta,"CSTA srv");
+  m_Timelines.push_back(csta);
+}
+
+Model::~Model()
+{
+}
+
+void 
+Model::parse_sip(const Packet &packet,std::stringstream &is)
+{
+    ;
+}
+
+void 
+Model::parse_ots(const Packet &packet,std::stringstream &is)
+{
+    ;
+}
+
+void 
+Model::parse_csta(const Packet &packet,std::stringstream &is)
+{
+    ;
+}
+
+void
+Model::clean()
+{
+  m_Timelines.erase(m_Timelines.begin(),m_Timelines.end());
+  // 
+  for_each(m_Events.begin(),m_Events.end(),tlmsg_deleter());
+  m_Events.erase(m_Events.begin(),m_Events.end());
+  int crid = 0;
+  unsigned short port= m_portCsta;
+  Timeline csta(crid,port,"CSTA srv");
+  m_Timelines.push_back(csta);
+  
+  m_Calls.clear();
+  m_OnClean();
+}
+
+void
+Model::new_TLMsg(const Packet &p,TLMsg **m)
+{
+    std::string nm("NEWMSG");
+    *m  = new TLMsg(p,nm);
+}
+
+void
+Model::add_TLMsg(TLMsg *m,Timeline &tls,Timeline &tld)
+{
+  int  dist = 0;
+  bool found = false;
+  // Find destination Timeline If not found add it in the list.
+  found = find_timeline(tld,dist);
+  if (!found)
+      m_Timelines.push_back(tld);
+  m->distance = dist;
+
+  // Find Source Timeline 
+  if ( ! find_timeline(tls,dist))
+      m_Timelines.push_back(tls);
+  
+  if (m != NULL)
+      m->sdistance = dist;
+  if (m != NULL) 
+      m_Events.push_back(m);
+  
+  // Ok, process Calls msg->msg_type(TLMsg::CSTA_EVENT);
+  if (m->msg_type() == TLMsg::CSTA_EVENT) {
+    int nbcalls = m_Calls.size();
+    Calls_const_iterator it = m_Calls.find(m->m_callid);
+    if ( it ==  m_Calls.end()) {
+      m_Calls[m->m_callid] = nbcalls;
+    }
+  }
+
+  m_OnAdd(m,tls,tld);
+}
+
+
+bool 
+Model::have_Call(std::string &c,int &i) const
+{
+ Calls_const_iterator it = m_Calls.find(c);
+ if (it != m_Calls.end()) {
+   i = (it)->second;
+   return true;
+ }
+ return false;
+}
+
+bool
+Model::find_timeline(const Timeline &tl,int &distance )
+{
+  bool found = false;
+  int dist = 0;
+  
+
+  for (TimelineType_const_iterator it= m_Timelines.begin() ; 
+          it != m_Timelines.end(); ++it)
+  {
+      if ((*it) == tl){
+        found = true;
+        break;
+      }
+    dist++;
+  }
+  distance = dist;
+  return found;
+
+}
+
+    
+void 
+Model::subscribe(Observer *o)
+{
+  m_OnClean.connect(o,&Observer::onClean);
+  m_OnAdd.connect(o,&Observer::onAdd);
+  m_OnSelected.connect(o,&Observer::onSelected);
+  m_OnScroll.connect(o,&Observer::onScroll);
+}
+
+void 
+Model::select(TLMsg *m)
+{
+    m_OnSelected(m);
+}
+
+
+    
+void 
+Model::export_msc(const char *fn)
+{
+  int i = 0;
+  std::ofstream msc(fn);
+
+
+
+  for (TimelineType_const_iterator it= m_Timelines.begin() ; 
+          it != m_Timelines.end(); ++it , i++)
+  {
+      std::string dev;
+      (*it).get_device(dev);
+      
+      if ((it) != m_Timelines.begin()){
+        msc<<",";
+      }
+      msc<<"L"<<i<<" [label=\""<<(*it).name();
+      if (dev.size() > 0)
+      {
+      msc<<" "<<dev;
+      }
+      msc<<"\"]"<<std::endl;
+  }
+  msc<<";"<<std::endl<<std::endl;
+ // Now the events 
+  for (EventType_const_iterator it= m_Events.begin() ; 
+          it != m_Events.end(); ++it)
+  {
+      
+      msc<<"L"<<(*it)->sdistance<<"-> L"<<(*it)->distance<<": [label=\""<<(*it)->name<<"\"];"<<std::endl;
+  }
+
+  msc.close();
+}
diff --git a/cstav1/Model.h b/cstav1/Model.h
new file mode 100644 (file)
index 0000000..6ead015
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef MODEL_H__
+#define MODEL_H__
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include <stdlib.h>
+#include <time.h>
+
+#if defined(__WIN32__) || defined(_WINDOWS)
+#include <pcap/pcap.h>
+#endif
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include "Timeline.h"
+// Packet information ...
+#include "Pcap.h"
+#if defined(__WIN32__) || defined(_WINDOWS)
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "TLMsg.h"
+#include "sigslot.h"
+#include "Observer.h"
+class Model {
+  public:
+
+     typedef std::vector<Timeline> TimelineType;
+     typedef std::vector<Timeline>::const_iterator TimelineType_const_iterator;
+     typedef std::vector<TLMsg *> EventType;
+     typedef std::vector<TLMsg *>::const_iterator EventType_const_iterator;
+
+     typedef std::map<std::string,int> Calls;
+     typedef std::map<std::string,int>::const_iterator  Calls_const_iterator;
+
+     typedef sigslot::signal0<> cleanEvent;
+     typedef sigslot::signal3<TLMsg *,Timeline &,Timeline &> addEvent;
+     typedef sigslot::signal1<TLMsg *> selectEvent;
+     typedef sigslot::signal1<int> scrollEvent;
+
+     struct tlmsg_deleter {
+          inline void operator ()(TLMsg *& e) { delete e; e= NULL;}
+     };
+     
+     struct tlmsg_finder {
+       tlmsg_finder(TLMsg * e) : m_e(e) {};
+          inline bool operator ()(TLMsg * e) { return e == m_e;};
+       TLMsg *m_e;
+     };
+
+    Model();
+    ~Model();
+
+    inline int tl_count() {return m_Timelines.size();};
+    inline TimelineType_const_iterator  tl_begin() {return m_Timelines.begin();};
+    inline TimelineType_const_iterator  tl_end() {return m_Timelines.end();};
+    
+    inline EventType_const_iterator  evt_begin() {return m_Events.begin();};
+    inline EventType_const_iterator  evt_end() {return m_Events.end();};
+
+    inline short portCsta() { return m_portCsta;};
+    inline short portSip()  { return m_portSip; };
+    inline short portXml()  { return m_portXml; };
+
+    inline void scroll_to(int x) {m_OnScroll(x);};
+    void parse_sip(const Packet &packet,std::stringstream &is);
+    void parse_ots(const Packet &packet,std::stringstream &is);
+    void parse_csta(const Packet &packet,std::stringstream &is);
+
+    // We should find setter and getters here.
+
+    /**
+     * \brief build a new TimeLine Message. Also inform all views that a new entry has just been created.
+     */
+    void new_TLMsg(const Packet &p,TLMsg **_msg);
+
+    void add_TLMsg(TLMsg *_msg,Timeline &tsl,Timeline &tld);
+
+    bool have_Call(std::string &,int &) const;
+    void clean();
+
+    void select(TLMsg *m);
+
+    void export_msc(const char *fn);
+
+    bool find_timeline(const Timeline &tl,int &distance );
+    // Mvc subscription
+    void subscribe(Observer *o);
+  protected:
+    TimelineType    m_Timelines;
+    EventType       m_Events;
+    short           m_portCsta;
+    short           m_portSip;
+    short           m_portXml;
+
+    // Calls
+    Calls           m_Calls;
+    // Events
+    cleanEvent      m_OnClean;
+    addEvent        m_OnAdd;
+    selectEvent     m_OnSelected;
+    selectEvent     m_OnNew;
+    scrollEvent     m_OnScroll;
+};
+
+#endif
diff --git a/cstav1/Observer.h b/cstav1/Observer.h
new file mode 100644 (file)
index 0000000..0cdaf34
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef OBSERVER_H__
+#define OBSERVER_H__
+#include "sigslot.h"
+
+class Observer : public sigslot::has_slots<>
+{
+  public:
+    Observer() {};
+    virtual ~Observer() {};
+    virtual void onClean() = 0;
+    virtual void onNew(TLMsg *msg) = 0;
+    virtual void onAdd(TLMsg *msg,Timeline &tls,Timeline &tld) = 0;
+    virtual void onSelected(TLMsg *msg) = 0;
+    virtual void onScroll(int x) = 0;
+};
+
+#endif
diff --git a/cstav1/Packet.cpp b/cstav1/Packet.cpp
new file mode 100644 (file)
index 0000000..9b4a772
--- /dev/null
@@ -0,0 +1,264 @@
+#include <iostream>
+#include <pcap/pcap.h>
+
+#include "Packet.h"
+#define __FAVOR_BSD
+#if ! defined(__WIN32__) &&  ! defined(_WINDOWS)
+#include "netinet/in.h"
+#include "netinet/tcp.h"
+#endif
+#include "SniffHeader.h"
+#define SIZE_ETHERNET 14
+
+#include <string.h>
+#include <stdlib.h>
+
+//#define PAYLOAD_DEBUG
+
+Packet::Packet()
+    : m_managed(false)
+{
+}
+
+Packet::~Packet()
+{
+    if (m_managed)
+    {
+        std::cout<<"Packet::~Packet Release allocated\n";
+        free(mp_data);
+    }
+}
+
+
+Packet::Packet(const unsigned char *d,size_t length)
+  : m_managed(false)
+{
+}
+
+
+Packet::Packet(const Header &header,const unsigned char *data)
+ : m_header(header),
+  mp_data(const_cast<unsigned char *>(data))
+    ,m_managed(false)
+{
+}
+
+Packet::Packet(const Packet &p) : m_header(p.m_header), mp_data(p.mp_data) 
+  ,m_managed(false)
+{
+
+}
+
+Packet & Packet::operator =(const Packet &p)
+{
+        if (this != &p) 
+        {
+            m_header = p.m_header;
+            mp_data  = p.mp_data;
+        }
+        return *this;
+}
+    
+const unsigned char *
+Packet::get_payload(long &length)
+{
+       const struct sniff_ethernet *ethernet; /* The ethernet header */
+       const struct sniff_ip *ip; /* The IP header */
+       const struct sniff_tcp *tcp; /* The TCP header */
+       const char unsigned *payload; /* Packet payload */
+    long  cooked_header = 0;
+       u_int size_ip;
+       u_int size_tcp;
+
+    // OK cast at the proper position
+
+    if ( ((mp_data[2] == 0x03) && (mp_data[3] == 0x04))
+        ||
+        ((mp_data[14] == 0x08) && (mp_data[15] == 0x00))) {
+      cooked_header = 2;
+#ifdef PAYLOAD_DEBUG
+      std::cout<<"Packet::get_payload Cooked header\n";
+#endif
+    }
+       ethernet = (struct sniff_ethernet*)(mp_data+cooked_header);
+       ip = (struct sniff_ip*)(mp_data + SIZE_ETHERNET+cooked_header);
+         size_ip = IP_HL(ip)*4;
+         if (size_ip < 20) {
+               printf("   * Invalid IP header length: %u bytes\n", size_ip);
+               return NULL;
+         }
+       tcp = (struct sniff_tcp*)(mp_data + SIZE_ETHERNET + size_ip+cooked_header);
+       if (ip->ip_p == 0x06) {
+         size_tcp = TH_OFF(tcp)*4;
+         if (size_tcp < 20) {
+               printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
+               return NULL;
+      }
+    } else if (ip->ip_p == 0x11) { // UDP 
+      size_tcp = sizeof(sniff_udp);
+    } else {
+        size_tcp = 0;
+               printf("   * Invalid unkwnow protocol: %u bytes %02x\n", size_tcp,ip->ip_p);
+      
+    }
+       payload = (u_char *)(mp_data + SIZE_ETHERNET + size_ip + size_tcp+cooked_header);
+  
+    int len = payload -mp_data;
+    length = m_header.len-len;
+    return payload;
+}
+
+const struct sniff_ip *
+Packet::get_ip() const /* The IP header */
+{
+       const struct sniff_ethernet *ethernet; /* The ethernet header */
+       const struct sniff_ip *ip; /* The IP header */
+       const struct sniff_tcp *tcp; /* The TCP header */
+       const char unsigned *payload; /* Packet payload */
+    long  cooked_header = 0;
+       u_int size_ip;
+       u_int size_tcp;
+
+    // OK cast at the proper position
+
+    if ( ((mp_data[2] == 0x03) && (mp_data[3] == 0x04))
+        ||
+        ((mp_data[14] == 0x08) && (mp_data[15] == 0x00))) {
+      cooked_header = 2;
+#ifdef PAYLOAD_DEBUG
+      std::cout<<" Cooked header\n";
+#endif
+    }
+       ethernet = (struct sniff_ethernet*)(mp_data+cooked_header);
+       ip = (struct sniff_ip*)(mp_data + SIZE_ETHERNET+cooked_header);
+       size_ip = IP_HL(ip)*4;
+       if (size_ip < 20) {
+               printf("   * Invalid IP header length: %u bytes\n", size_ip);
+               return NULL;
+       }
+    return ip;
+
+}
+
+const struct sniff_tcp *
+Packet::get_tcp() const /* The TCP header */
+{
+       const struct sniff_ethernet *ethernet; /* The ethernet header */
+       const struct sniff_ip *ip; /* The IP header */
+       const struct sniff_tcp *tcp = NULL; /* The TCP header */
+       const char unsigned *payload; /* Packet payload */
+    long  cooked_header = 0;
+       u_int size_ip;
+       u_int size_tcp;
+
+    // OK cast at the proper position
+
+    if ( ((mp_data[2] == 0x03) && (mp_data[3] == 0x04))
+        ||
+        ((mp_data[14] == 0x08) && (mp_data[15] == 0x00))) {
+      cooked_header = 2;
+#ifdef PAYLOAD_DEBUG
+      std::cout<<"Packet::get_tcp Cooked header\n";
+#endif
+    }
+       ethernet = (struct sniff_ethernet*)(mp_data+cooked_header);
+       ip = (struct sniff_ip*)(mp_data + SIZE_ETHERNET+cooked_header);
+   size_ip = IP_HL(ip)*4;
+       if (size_ip < 20) {
+               printf("   * Invalid IP header length: %u bytes\n", size_ip);
+               return NULL;
+       }
+       if (ip->ip_p == 0x06) {
+         tcp = (struct sniff_tcp*)(mp_data + SIZE_ETHERNET + size_ip+cooked_header);
+         size_tcp = TH_OFF(tcp)*4;
+         if (size_tcp < 20) {
+               printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
+               return NULL;
+         }
+    }
+
+    return tcp;
+}
+
+
+const struct sniff_udp *
+Packet::get_udp() const /* The TCP header */
+{
+       const struct sniff_ethernet *ethernet; /* The ethernet header */
+       const struct sniff_ip *ip; /* The IP header */
+       const struct sniff_udp *udp = NULL; /* The TCP header */
+       const char unsigned *payload; /* Packet payload */
+    long  cooked_header = 0;
+       u_int size_ip;
+       u_int size_udp;
+
+    // OK cast at the proper position
+
+    if ( ((mp_data[2] == 0x03) && (mp_data[3] == 0x04))
+        ||
+        ((mp_data[14] == 0x08) && (mp_data[15] == 0x00))) {
+      cooked_header = 2;
+#ifdef PAYLOAD_DEBUG
+      std::cout<<"Packet::get_udp Cooked header\n";
+#endif
+    }
+       ethernet = (struct sniff_ethernet*)(mp_data+cooked_header);
+       ip = (struct sniff_ip*)(mp_data + SIZE_ETHERNET+cooked_header);
+   size_ip = IP_HL(ip)*4;
+       if (size_ip < 20) {
+               printf("   * Invalid IP header length: %u bytes\n", size_ip);
+               return NULL;
+       }
+       if (ip->ip_p == 0x11) {
+         udp = (struct sniff_udp*)(mp_data + SIZE_ETHERNET + size_ip+cooked_header);
+#if 0
+      size_udp = TH_OFF(tcp)*4;
+         if (size_udp < sizeof(struct_udp)) {
+               printf("   * Invalid UDP header length: %u bytes\n", size_tcp);
+               return NULL;
+         }
+#endif
+    }
+
+    return udp;
+}
+
+void
+Packet::manage()
+{
+    if (m_managed || mp_data == NULL)
+        return;
+    unsigned char * dest = (unsigned char *)malloc(m_header.caplen);
+    memcpy(dest, mp_data,m_header.caplen);
+    mp_data = dest;
+    m_managed = true;
+}
+
+std::string 
+Packet::string_srcdst(void)
+{
+    const struct sniff_udp *udp = get_udp(); 
+    const struct sniff_tcp *tcp = get_tcp();
+    const struct sniff_ip  *ip  = get_ip();
+    unsigned short sport,dport;
+    
+    char buf[128];
+
+    if (udp) {
+      sport = htons(udp->sport);
+      dport = htons(udp->dport);
+    } else if (tcp)
+    {
+      sport = htons(tcp->th_sport);
+      dport = htons(tcp->th_dport);
+    }
+    strcpy(buf,inet_ntoa(ip->ip_src));
+    strcat(buf,":");
+    int len = strlen(buf); 
+    sprintf(buf+len,"%d To %s:%d",sport,inet_ntoa(ip->ip_dst),dport);
+
+    std::string result(buf);
+    return result;
+
+
+}
diff --git a/cstav1/Packet.h b/cstav1/Packet.h
new file mode 100644 (file)
index 0000000..bce54b1
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __MPACKET_H__
+#define __MPACKET_H__
+#if defined(WIN32) || defined(_WINDOWS)
+#else
+// Only for Unix
+#define __FAVOR_BSD
+#include <netinet/in.h>
+#include "netinet/tcp.h"
+#include <arpa/inet.h>
+#endif
+#include "SniffHeader.h"
+
+#include <pcap/pcap.h>
+
+class Packet {
+  public:
+
+    typedef struct pcap_pkthdr Header;
+    Packet();
+     ~Packet();
+    Packet(const Packet &p) ;
+    Packet(const unsigned char *,size_t length);
+    Packet(const Header &header,const unsigned char *data);
+
+    Packet & operator =(const Packet &p);
+    
+    inline struct timeval  get_timeval() const
+    { return m_header.ts; };
+    
+    inline long get_seconds() const
+    { return m_header.ts.tv_sec; };
+   
+    inline long get_miliseconds() const
+    { return m_header.ts.tv_usec; };
+
+    inline long get_length() const 
+    { return m_header.len; };
+  
+       const struct sniff_ip *get_ip() const; /* The IP header */
+       const struct sniff_tcp *get_tcp() const; /* The TCP header */
+       const struct sniff_udp *get_udp() const; /* The TCP header */
+
+    std::string string_srcdst(void);
+    /**
+     * Return data only if available
+     */
+    const unsigned char *get_payload(long &len);
+
+    /// 
+    /// @brief keep a local copy of the buffer.
+    ///
+    /// By default, the data are those from the pcap librarie.
+    void manage();
+  protected:
+    Header          m_header;
+    unsigned char   *mp_data;
+    bool            m_managed;
+};
+
+#endif
diff --git a/cstav1/Pcap.cpp b/cstav1/Pcap.cpp
new file mode 100644 (file)
index 0000000..b16f225
--- /dev/null
@@ -0,0 +1,73 @@
+#include <iostream>
+#include <pcap/pcap.h>
+#include "Pcap.h"
+#include "CstaInsightLog.h"
+
+char Pcap::s_ebuf[PCAP_ERRBUF_SIZE + 1] = "";
+
+Pcap::Pcap(const std::string &file_name)
+  : m_ok(true)
+    ,m_mp_pcap_t(NULL)
+{
+  CI_LOG_DEBUG("Pcap::Pcap with file %s",file_name.c_str());
+  if (! (m_mp_pcap_t = pcap_open_offline(file_name.c_str(),s_ebuf)) )
+  {
+    // error
+         std::cerr<<"Failed open cap file\n";
+      m_ok = false;
+  }
+}
+
+Pcap::~Pcap()
+{
+  CI_LOG_DEBUG("Pcap::~Pcap");
+  if (m_mp_pcap_t)
+    pcap_close(m_mp_pcap_t);
+}
+
+void
+Pcap::set_filter(const std::string &expression)
+{
+    struct bpf_program bpf;
+
+    int ret = pcap_compile(m_mp_pcap_t,&bpf,
+            expression.c_str(),false,0);
+
+    if (ret < 0)
+    {
+      CI_LOG_ERROR("Pcap::set_filter Failed compile expression : %s",expression.c_str());
+    }
+    if (! (ret < 0 ) && pcap_setfilter(m_mp_pcap_t,&bpf) < 0 )
+    {
+      CI_LOG_ERROR("Pcap::set_filter  Failed set filter");
+    }
+    pcap_freecode(&bpf);
+
+    m_filter = expression;
+}
+
+//friend
+//
+Pcap &operator>>(Pcap &cap , Packet &packet)
+{
+  static struct pcap_pkthdr *header;
+  static const u_char *data;
+
+  switch( pcap_next_ex(cap.m_mp_pcap_t, const_cast<pcap_pkthdr **>(&header), 
+              &data ) )
+  {
+    case 1: // ok
+      packet = Packet(*header,data); 
+         break;
+    case -1: //error
+      cap.m_ok = false;
+         break;
+    default: // EOF or expires
+      cap.m_ok = false;
+        ;
+  }
+  return cap;
+
+
+}
+
diff --git a/cstav1/Pcap.h b/cstav1/Pcap.h
new file mode 100644 (file)
index 0000000..5b9219f
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef PCAPPP_H__
+#define PCAPPP_H__
+
+#include "Packet.h"
+#include <pcap.h>
+#include <string>
+
+
+class Pcap {
+  public:
+    Pcap(const std::string &f);
+    ~Pcap();
+
+  bool next(Packet &p) 
+       { return (*this>>p);};
+
+  friend Pcap &operator>>(Pcap &p,Packet &packet); 
+
+
+  void set_filter(const std::string &expression);
+  operator bool() const
+  {
+    return m_ok;
+  };
+  protected:
+    static char s_ebuf[];
+    pcap_t      *m_mp_pcap_t;
+    bool        m_ok;
+    std::string m_filter;
+    std::string m_filename;
+};
+
+#endif
diff --git a/cstav1/PrivateEla.cpp b/cstav1/PrivateEla.cpp
new file mode 100644 (file)
index 0000000..5347743
--- /dev/null
@@ -0,0 +1,12 @@
+#include <iostream>
+
+#include "PrivateEla.h"
+
+PrivateEla::PrivateEla(const char *)
+{
+}
+
+PrivateEla::~PrivateEla()
+{
+}
+
diff --git a/cstav1/PrivateEla.h b/cstav1/PrivateEla.h
new file mode 100644 (file)
index 0000000..b9d0273
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef PRIVATE_ELA_H__
+#define PRIVATE_ELA_H__
+
+
+class PrivateEla {
+  public:
+    PrivateEla(const char *=NULL);
+    ~PrivateEla();
+
+    struct _Cs {
+      unsigned short    connCall;
+      unsigned short    connNeqt;
+      unsigned short    connType;
+    };
+
+    struct Event {
+      unsigned char     pType;  // Private type
+      unsigned short    pId;    // Private identifier 
+      unsigned long     tbd;
+      unsigned long     crid;   // Crid
+      struct _Cs               arr[5]; //
+      char              arrS1[25];  // Array of chars
+      char              arrS2[25];  // Array of chars
+      unsigned char     as1Type;
+      unsigned char     as2Type;
+      char              arrL1[25];  // Array of chars
+      char              arrL2[25];  // Array of chars
+      unsigned char     al1Type;
+      unsigned char     al2Type;
+      unsigned short    line;    // Private identifier 
+      unsigned short    cause;    // Private identifier 
+    };
+
+  protected:
+
+};
+
+
+
+#endif
diff --git a/cstav1/SequenceView.cpp b/cstav1/SequenceView.cpp
new file mode 100644 (file)
index 0000000..74c0e0f
--- /dev/null
@@ -0,0 +1,731 @@
+#include <iostream>
+#include <cstdio>
+#include <iomanip>
+#include <sstream>
+#include <math.h>
+#include <map>
+// Seems to be included before every thing else.
+#include <pcap/pcap.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include <FL/Fl_Image.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Scrollbar.H>
+
+#if defined(WIN32) || defined(_WIN32) || defined(_WINDOWS)
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "Pcap.h"
+
+#include "XMLMessage.h"
+
+#include "TLMsg.h"
+#include <FL/Fl_Text_Editor.H>
+#include <FL/Fl_Text_Buffer.H>
+#include <SequenceView.h>
+#include <FL/fl_draw.H>
+
+#include "Model.h"
+#include "IconFactory.h"
+
+SequenceView::
+SequenceView(int x,int y , int h, int w, const char *l)
+    : Fl_Widget(x,y,h,w,l)
+      ,m_separator(120),
+      m_Model(NULL),
+      m_Editor(NULL),
+      m_Buffer(NULL),
+      m_Selected(NULL),
+      m_Tree(NULL)
+{
+  int crid = 0;
+  unsigned short csta_port = 2555;
+  color(FL_WHITE);
+  Timeline csta(crid,csta_port,"CSTA srv");
+  m_Crids.push_back(csta);
+}
+
+void 
+SequenceView::add_event(int crid,Packet &p,const char *name,Fl_Tree_Item *_item)
+{
+  const struct sniff_ip *ip = p.get_ip();
+  const struct sniff_tcp *tcp = p.get_tcp();
+  int dist = 0;
+  TLMsg e(p,"");
+  e.crid        = crid;
+  e.name        = name;
+  e.item        = _item;
+  e.sdistance   =   0;
+  short csta_src = 2555;
+  bool found = false;
+  unsigned short dest_port = htons(tcp->th_dport);
+  unsigned short src_port  = htons(tcp->th_sport);
+  Timeline tl(crid,dest_port,"");
+  for (CridType_const_iterator it= m_Crids.begin() ; 
+          it != m_Crids.end(); ++it)
+  {
+
+      if ((*it) == tl){
+        found = true;
+//        std::cout<<"Crid in list\n";
+        break;
+      }
+    dist++;
+  }
+  if (!found)
+  {
+      m_Crids.push_back(tl);
+  }
+  e.distance = dist;
+  m_Events.push_back(e);
+}
+
+void 
+SequenceView::add_invoke(Packet &packet,const char *name, Fl_Tree_Item *_item )
+{
+  const struct sniff_ip *ip = packet.get_ip();
+  const struct sniff_tcp *tcp = packet.get_tcp();
+  bool found = false; 
+  int dist = 0;
+  int crid = 0;
+  unsigned short dest_port = htons(tcp->th_dport);
+  unsigned short src_port  = htons(tcp->th_sport);
+  Timeline tl(crid,dest_port,"");
+  found = find_timeline(tl,dist);
+
+  if (!found)
+      m_Crids.push_back(tl);
+  // Add a message in the list
+  TLMsg e(packet,name);
+  e.crid = ip->ip_src.s_addr;
+  e.name = name;
+  e.item = _item;
+  //e.packet = packet;
+  //e.packet.manage();
+  e.distance = dist;
+  
+  Timeline tls(crid,src_port,"");
+  if ( ! find_timeline(tls,dist))
+      m_Crids.push_back(tls);
+  e.sdistance = dist;
+  
+  m_Events.push_back(e);
+  (m_Events.back()).packet.manage();
+
+}
+
+void 
+SequenceView::add_result(Packet &packet,const char *name, Fl_Tree_Item *_item )
+{
+  const struct sniff_ip *ip = packet.get_ip();
+  const struct sniff_tcp *tcp = packet.get_tcp();
+  bool found = false; 
+  int dist = 0;
+  int crid = 0;
+  unsigned short dest_port = htons(tcp->th_dport);
+  unsigned short src_port  = htons(tcp->th_sport);
+  Timeline tl(crid,dest_port,"");
+  found = find_timeline(tl,dist);
+
+  if (!found)
+      m_Crids.push_back(tl);
+#if 1 
+  // Add a message in the list
+  TLMsg e(packet,name);
+  e.crid = ip->ip_src.s_addr;
+  e.name = name;
+  e.item = _item;
+  e.distance = dist;
+  
+  Timeline tls(crid,src_port,"");
+  if ( ! find_timeline(tls,dist))
+      m_Crids.push_back(tls);
+  e.sdistance = dist;
+  
+  m_Events.push_back(e);
+  (m_Events.back()).packet.manage();
+#endif
+
+}
+
+bool
+SequenceView::find_timeline(const Timeline &tl,int &distance )
+{
+  bool found = false;
+  int dist = 0;
+  
+
+  for (CridType_const_iterator it= m_Crids.begin() ; 
+          it != m_Crids.end(); ++it)
+  {
+      if ((*it) == tl){
+        found = true;
+        break;
+      }
+    dist++;
+  }
+  distance = dist;
+  return found;
+
+}
+
+void
+SequenceView::add_sip(const char *name,Packet &packet, Fl_Tree_Item *_item )
+{
+  int dist = 0;
+  bool found = false;
+//  std::cout<<"SequenceView::add_sip\n";
+  const struct sniff_ip *ip = packet.get_ip();
+
+  Timeline tl(ip->ip_dst,"");
+  found = find_timeline(tl,dist);
+
+  if (!found)
+      m_Crids.push_back(tl);
+#if 1 
+  // Add a message in the list
+  TLMsg e;
+  e.tv   = packet.get_timeval();
+  e.crid = ip->ip_src.s_addr;
+  e.name = name;
+  e.item = _item;
+  e.packet = packet;
+  //e.packet.manage();
+  e.distance = dist;
+  
+  Timeline tls(ip->ip_src,"");
+  if ( ! find_timeline(tls,dist))
+      m_Crids.push_back(tls);
+  e.sdistance = dist;
+  
+  m_Events.push_back(e);
+  (m_Events.back()).packet.manage();
+#endif
+}
+
+       
+void 
+SequenceView::clear()
+{
+  color(FL_WHITE);
+  m_Crids.erase(m_Crids.begin(),m_Crids.end());
+  m_Events.erase(m_Events.begin(),m_Events.end());
+  damage(FL_DAMAGE_ALL);
+  int crid = 0;
+  unsigned short port= 2555;
+  Timeline csta(crid,port,"CSTA srv");
+  m_Crids.push_back(csta);
+}
+
+void SequenceView::resize(int  _x, int _y, int  w, int  h )
+{
+  Fl_Widget::resize(_x,_y,w,h);
+}
+
+void 
+SequenceView::draw()
+{
+#if 0
+  if (m_Model) {
+      Fl_Scrollbar *sb = &dynamic_cast<Fl_Scroll *>(this->parent())->hscrollbar;
+         m_Model->scroll_to(sb->value());
+  }
+#endif
+  uchar s = damage();
+  if (s & FL_DAMAGE_ALL) {
+    draw2();
+  } else {
+    //draw2();
+  }
+}
+
+void 
+SequenceView::draw1()
+{
+    int new_x = 0;
+    int new_y = 0;
+    int y_base =20;
+    int space  = 19;
+    int line = 0,column = 0;
+    
+    color(FL_WHITE);
+    
+    fl_push_clip(x(),y(),w(),h());
+    fl_push_matrix();
+    fl_translate(x(),y());
+  
+    fl_font(0,10);
+    fl_color(FL_BLACK);
+    // Draw crid length
+    for (CridType_const_iterator it = m_Crids.begin();
+            it!= m_Crids.end();
+            ++it)
+    {
+        std::stringstream scrid;
+        // draw text ...
+        fl_draw((*it).name(),x()+130 + column*m_separator,y()-2+y_base);
+        // beginning of line ....
+        fl_begin_line(); 
+          fl_vertex(150+column*m_separator,y_base);
+          fl_vertex(150+column*m_separator,y_base+h());
+        fl_end_line();
+        column++;
+    }
+    new_y = 19+22;
+    new_x = 150 + column*m_separator + 50;
+    line = 1;
+    for (EventType_const_iterator it = m_Events.begin();
+            it != m_Events.end();
+            ++it)
+    {
+        if ((*it).item && (*it).item->is_selected())
+        {
+            fl_color(FL_RED);
+        } else
+            fl_color(FL_BLUE);
+        // Begin arrow line 
+        fl_begin_line(); 
+          fl_vertex(150+(*it).sdistance*m_separator,y_base+space*line);
+          fl_vertex(150+(*it).distance*m_separator,y_base+space*line);
+        fl_end_line();
+        // Should draw an arrow
+        int delta;
+        if ((*it).sdistance > (*it).distance) 
+        {
+            delta = 5;
+        } else
+            delta = -5;
+        fl_begin_line(); 
+          fl_vertex(150 +delta +(*it).distance*m_separator ,y_base-3+space*line);
+          fl_vertex(150+(*it).distance*m_separator,y_base+space*line);
+          fl_vertex(150 + delta +(*it).distance*m_separator,y_base+3+space*line);
+        fl_end_line();
+        new_y+= space;
+        if ((*it).item && (*it).item->is_selected())
+        {
+            fl_color(FL_RED);
+        } else
+            fl_color(FL_BLACK);
+        // Draw the text
+        std::string ts;
+        tvtostring((*it).get_timeval(),ts);
+        ts = ts ;//+ (*it).name;
+        fl_draw(ts.c_str(),15+x(),y()-2+space*line+y_base);
+        ts = (*it).name;
+        if ((*it).distance > ((*it).sdistance))
+        {
+            fl_draw(ts.c_str(),150+x()+(*it).sdistance*m_separator,y()-2+space*line+y_base);
+        } else 
+        {
+            fl_draw(ts.c_str(),150+x()+(*it).distance*m_separator,y()-2+space*line+y_base);
+        }
+        line++;
+    } 
+
+    fl_pop_matrix();
+    fl_pop_clip();
+    if (new_x < w())
+           new_x = w();
+    if (new_y < h())
+      new_y = h();
+    size(new_x,new_y);
+}
+
+
+void 
+SequenceView::draw2()
+{
+    int new_x = 0;
+    int new_y = 0;
+    int y_base =20;
+    int space  = 19;
+    int line = 0,column = 0;
+    
+    color(FL_WHITE);
+    
+    fl_push_clip(x(),y(),w(),h());
+    fl_push_matrix();
+    fl_translate(x(),y());
+  
+    fl_font(0,10);
+    fl_color(FL_BLACK);
+    // Draw crid length
+    for (Model::TimelineType_const_iterator it = m_Model->tl_begin();
+            it!= m_Model->tl_end();
+            ++it)
+    {
+        std::stringstream scrid;
+        // draw text ...
+        fl_draw((*it).name(),x()+130 + column*m_separator,y()-2+y_base);
+        // beginning of line ....
+        fl_begin_line(); 
+          fl_vertex(150+column*m_separator,y_base);
+          fl_vertex(150+column*m_separator,y_base+h());
+        fl_end_line();
+        column++;
+    }
+    new_y = 19+22;
+    new_x = 150 + column*m_separator + 50;
+    line = 1;
+    for (Model::EventType_const_iterator it = m_Model->evt_begin();
+            it != m_Model->evt_end();
+            ++it)
+    {
+       int id;
+       // Draw Background box
+       if (m_Model->have_Call((*it)->m_callid,id)) {
+         struct col {
+           unsigned char r;
+           unsigned char g;
+           unsigned char b;
+         } col[] = {
+           {0xAA,0xAA,0xAA},
+           {0xAA,0xFF,0xFF},
+           {0xAA,0xFF,0x00},
+           {0xFF,0x00,0x88},
+           {0x55,0xAA,0x55}
+         } ;
+         fl_rectf(x(),y()+space*(line)+5,150+new_x,space,col[id].r,col[id].g,col[id].b)        ;
+       } else {
+         fl_rectf(x(),y()+space*(line)+5,150+new_x,space,0xFF,0xFF,0xFF)       ;
+       }
+        if ((*it) == m_Selected)
+        {
+            fl_color(FL_RED);
+        } else
+            fl_color(FL_BLUE);
+        // Begin arrow line 
+        fl_begin_line(); 
+          fl_vertex(150+(*it)->sdistance*m_separator,y_base+space*line);
+          fl_vertex(150+(*it)->distance*m_separator,y_base+space*line);
+        fl_end_line();
+        // Should draw an arrow
+        int delta;
+        if ((*it)->sdistance > (*it)->distance) 
+        {
+            delta = 5;
+        } else
+            delta = -5;
+        fl_begin_line(); 
+          fl_vertex(150 +delta +(*it)->distance*m_separator ,y_base-3+space*line);
+          fl_vertex(150+(*it)->distance*m_separator,y_base+space*line);
+          fl_vertex(150 + delta +(*it)->distance*m_separator,y_base+3+space*line);
+        fl_end_line();
+        new_y+= space;
+        if ((*it)->item && (*it)->item->is_selected())
+        {
+            fl_color(FL_RED);
+        } else
+            fl_color(FL_BLACK);
+        // Draw the text
+        std::string ts;
+        tvtostring((*it)->get_timeval(),ts);
+        ts = ts ;//+ (*it).name;
+        fl_draw(ts.c_str(),15+x(),y()-2+space*line+y_base);
+        ts = (*it)->name;
+        if ((*it)->distance > ((*it)->sdistance))
+        {
+            fl_draw(ts.c_str(),150+x()+(*it)->sdistance*m_separator,y()-2+space*line+y_base);
+        } else 
+        {
+            fl_draw(ts.c_str(),150+x()+(*it)->distance*m_separator,y()-2+space*line+y_base);
+        }
+        line++;
+    }
+    // Redraw lines
+    column = 0; 
+    fl_color(FL_BLACK);
+    fl_line_style(FL_DASH);
+    // Draw crid length
+    for (Model::TimelineType_const_iterator it = m_Model->tl_begin();
+            it!= m_Model->tl_end();
+            ++it)
+    {
+        // beginning of line ....
+        fl_begin_line(); 
+          fl_vertex(150+column*m_separator,y_base);
+          fl_vertex(150+column*m_separator,y_base+h());
+        fl_end_line();
+        column++;
+    }
+    fl_line_style(0);
+
+    fl_pop_matrix();
+    fl_pop_clip();
+    if (new_x < w())
+           new_x = w();
+    if (new_y < h())
+      new_y = h();
+    size(new_x,new_y);
+}
+
+void SequenceView::tvtostring(struct timeval v,std::string &s)
+{
+  time_t t = v.tv_sec;
+  char   buf[22];
+  std::stringstream ss;
+  struct tm *tm = localtime(&t);
+  memset(buf,0x00,22);
+#ifdef WIN32
+  strftime(buf,21,"%y-%m-%d %H:%M:%S",tm);
+#else
+  strftime(buf,21,"%F %H:%M:%S",tm);
+#endif
+  long milliseconds = v.tv_usec /1000;
+  ss<<buf<<"."<<std::setw(3)<<std::setfill('0')<<std::right<<milliseconds<<"     ";
+  s.assign(ss.str());
+}
+
+/**
+ *
+ */
+void SequenceView::model(Model *m)
+{
+    m_Model = m;
+    m->subscribe(this);
+};
+
+int SequenceView::handle(int  e)
+{
+    int X = x(); int Y = y(); int W = w(); int H = h();
+    int dx = Fl::event_x() - X;
+    int dy = Fl::event_y() - Y;
+    switch(e) 
+    {
+        case FL_NO_EVENT:
+            break;
+        case FL_DRAG:
+            {
+            //printf("SequenceView::handle drag %d dx=%d\n",e,dx);
+            return 1;
+            }
+            break;
+        case FL_PUSH:
+            {
+                Fl_Scrollbar *sb = &dynamic_cast<Fl_Scroll *>(this->parent())->scrollbar;
+                if (sb) {
+                    int y_base = 19;
+                    int lines  = 1;
+                    for (Model::EventType_const_iterator it = m_Model->evt_begin();
+                            it != m_Model->evt_end();
+                            ++it)
+                    {
+                        if ( (dy > y_base * lines ) && dy < (y_base *(lines + 1)) )  {
+                            //printf("Found : %s\n",(*it)->name.c_str());
+                            m_Model->select((*it));
+                            this->parent()->redraw();
+                            break;
+                        }
+                        if (dy > y_base) {
+                          lines++;
+                        } else 
+                            break;
+                    }
+                }
+            }
+            if (callback() && (when() & FL_WHEN_CHANGED))
+                do_callback();
+            return 1;
+            break;
+        case FL_RELEASE:
+           // printf("SequenceView::handle release %d\n",e);
+            this->parent()->redraw();
+            if (callback() && (when() & FL_WHEN_CHANGED))
+                do_callback();
+            return 1;
+            break;
+        case FL_MOVE:
+            //printf("SequenceView::handle move %d\n",e);
+            break;
+        case FL_ENTER:
+        case FL_LEAVE:
+          if (m_Model) {
+              Fl_Scrollbar *sb = &dynamic_cast<Fl_Scroll *>(this->parent())->hscrollbar;
+              m_Model->scroll_to(sb->value());
+          }
+            return 1;
+            break;
+        case FL_SHOW:
+            break;
+        default:
+            //printf("SequenceView::handle %d\n",e);
+           ;
+    }
+    return Fl_Widget::handle(e);
+}
+
+void SequenceView::onSelected(TLMsg *s)
+{
+  m_Selected = s;
+  m_Editor->scroll(s->line()+1,0);
+  // Find item in Tree
+  Fl_Tree_Item *item = m_Tree->first();
+  do {
+      if (item->user_data() == s) {
+          m_Tree->select_only(item,0); // Don't call callback. infinit loop
+          break;
+      }
+  } while  ((item = m_Tree->next(item)) != NULL);
+          
+  redraw();
+}
+    
+/**
+ * The name of tree items must be unique.
+ */ 
+static int counter = 0;
+
+void SequenceView::onClean()
+{
+  counter = 0; 
+  damage(FL_DAMAGE_ALL);
+}
+
+void SequenceView::onNew(TLMsg *s)
+{
+
+}
+
+void SequenceView::onAdd(TLMsg *msg,Timeline &tsl,Timeline &tld)
+{
+  std::stringstream ss; //Used for output
+  Fl_Tree_Item * item = NULL;
+  if (msg) 
+  {
+//       std::cout<<"SequenceView::onAdd "<<msg->name<<std::endl;
+      if (msg->name.size() > 1) 
+      {
+          if ( msg->name.size() < 4)
+          {
+            m_CurrentTreeItem = item = m_Tree->add("undefined");
+          } else
+         {
+              ss<<msg->name<<" "<<counter;
+             counter++;  
+              m_CurrentTreeItem = item = m_Tree->add(ss.str().c_str());
+         }
+         int lines = m_Editor->count_lines(0,m_Editor->buffer()->length(),1);
+          /*
+          * As said, the string used by add must be unique. 
+          */ 
+         if (item) 
+         {       
+            item->user_data((void *)msg);
+         } else 
+         {
+            std::cerr<<"SequenceView::onAdd item is NULL msg.name.size : "<<msg->name.size()<<std::endl;                 
+         }
+          msg->line(lines);
+          ss<<"== "<<msg->packet.string_srcdst()<<" =="<<std::endl;
+          // Here, I should add the decoded content
+          if (msg->msg_type() != TLMsg::SIP)
+            ss<<msg->name<<std::endl;
+          ss<<msg->m_content;
+          m_Editor->insert(ss.str().c_str());
+      }
+      switch (msg->msg_type())
+      {
+          case TLMsg::CSTA_REQUEST:
+              if (item)
+                item->usericon(IconFactory::get_Icon("Request_16.png"));
+              break;
+          case TLMsg::CSTA_RESPONSE:
+              if (item)
+                item->usericon(IconFactory::get_Icon("Response_16.png"));
+              break;
+          case TLMsg::CSTA_RESPONSE_ERROR:
+              if (item)
+                item->usericon(IconFactory::get_Icon("ResponseError_16.png"));
+              break;
+          case TLMsg::CSTA_REJECT:
+              if (item)
+                item->usericon(IconFactory::get_Icon("ResponseReject_16.png"));
+              break;
+          case TLMsg::CSTA_EVENT:
+              if (item)
+                item->usericon(IconFactory::get_Icon("Lighting_16.png"));
+              break;
+          case TLMsg::SOAP_REQUEST:
+          {
+              if (item) 
+              {
+                size_t found = 0;
+                item->usericon(IconFactory::get_Icon("RequestSoap_16.png"));
+                XMLMessage xmlmsg(m_Tree,item);
+                xmlmsg.Create();
+
+                void *p = xmlmsg.GetBuffer(msg->m_content.size());
+                if ( (found =msg->m_content.find("<?xml version=")) != std::string::npos)
+                {
+                    strncpy((char *)p,msg->m_content.substr(found).c_str(),msg->m_content.size()-found);
+                    xmlmsg.ParseBuffer(msg->m_content.size()-found);
+                }
+      
+              }
+              break;
+          }
+          case TLMsg::SOAP_RESPONSE:
+              if (item) 
+              {
+                size_t found = 0;
+                item->usericon(IconFactory::get_Icon("ResponseSoap_16.png"));
+                XMLMessage xmlmsg(m_Tree,item);
+                xmlmsg.Create();
+
+                void *p = xmlmsg.GetBuffer(msg->m_content.size());
+                if ( (found =msg->m_content.find("<?xml version=")) != std::string::npos)
+                {
+                    strncpy((char *)p,msg->m_content.substr(found).c_str(),msg->m_content.size()-found);
+                    xmlmsg.ParseBuffer(msg->m_content.size()-found);
+                }
+              }
+              break;
+          case TLMsg::SIP:
+              if (item) 
+              {
+                size_t found = 0;
+                item->usericon(IconFactory::get_Icon("Sip_16.png"));
+                if ( (found =msg->m_content.find("<?xml version=")) != std::string::npos)
+                {
+                    XMLMessage xmlmsg(m_Tree,item);
+                    xmlmsg.Create();
+                    void *p = xmlmsg.GetBuffer(msg->m_content.size());
+                    strncpy((char *)p,msg->m_content.substr(found).c_str(),msg->m_content.size()-found);
+                    xmlmsg.ParseBuffer(msg->m_content.size()-found);
+                }
+              }
+              break;
+          case TLMsg::ICS_EVENT:
+              if (item)
+              {
+                size_t found = 0;
+                item->usericon(IconFactory::get_Icon("Lighting_16.png"));
+                XMLMessage xmlmsg(m_Tree,item);
+                xmlmsg.Create();
+
+                void *p = xmlmsg.GetBuffer(msg->m_content.size());
+                if ( (found =msg->m_content.find("<?xml version=")) != std::string::npos)
+                {
+                    strncpy((char *)p,msg->m_content.substr(found).c_str(),msg->m_content.size()-found);
+                    xmlmsg.ParseBuffer(msg->m_content.size()-found);
+                }
+              }
+              break;
+          default:
+              ;
+      };
+  } else
+  {
+//       std::cout<<"SequenceView::onAdd"<<std::endl;
+    ;
+  }
+  damage(FL_DAMAGE_ALL);
+  this->parent()->redraw();  
+  m_Tree->parent()->redraw();
+}
diff --git a/cstav1/SequenceView.h b/cstav1/SequenceView.h
new file mode 100644 (file)
index 0000000..a74c1dd
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __SEQ_VIEW_H__
+#define __SEQ_VIEW_H__
+#include <iostream>
+#include <string>
+#include <vector>
+#include <stdlib.h>
+#include <time.h>
+
+#if defined(__WIN32__) || defined(_WINDOWS)
+#include <pcap/pcap.h>
+#endif
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+#include "Timeline.h"
+// Packet information ...
+#if defined(__WIN32__) ||defined(_WINDOWS)
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "Pcap.h"
+
+#include "sigslot.h"
+#include "TLMsg.h"
+#include "Observer.h"
+/**
+ */
+
+class Model;
+
+class SequenceView : public Fl_Widget ,public Observer 
+                    //,public sigslot::multi_threaded_local
+{
+ public:
+     typedef std::vector<Timeline> CridType;
+     typedef std::vector<Timeline>::const_iterator CridType_const_iterator;
+     typedef std::vector<TLMsg> EventType;
+     typedef std::vector<TLMsg>::const_iterator EventType_const_iterator;
+
+     SequenceView(int x,int y , int h, int w, const char *l=NULL);
+
+     void draw();
+     void draw1(); // Old way
+     
+     void draw2(); // New way
+     
+     int handle(int event);
+     void clear();
+
+     void resize(int  x, int   y, int  w, int  h );
+
+     void add_event(int crid,Packet &p,const char *name, Fl_Tree_Item *_item = NULL);
+     void add_invoke(Packet &packet,const char *name, Fl_Tree_Item *_item = NULL);
+     void add_result(Packet &packet,const char *name, Fl_Tree_Item *_item = NULL);
+     void add_sip(const char *name,Packet &packet, Fl_Tree_Item *_item = NULL);
+
+     inline void tree(Fl_Tree *t) {m_Tree = t;};
+     inline void editor(Fl_Text_Editor *t) {m_Editor = t;};
+
+    bool find_timeline(const Timeline &tl,int &distance );
+  
+    void model(Model *m);
+
+    void onClean();
+    void onNew(TLMsg *);
+    void onAdd(TLMsg *,Timeline &tsl,Timeline &tld);
+    void onSelected(TLMsg *);
+    void onScroll(int x) { };
+  protected:
+     void tvtostring(struct timeval t,std::string &s);
+
+  protected:
+     CridType           m_Crids;
+     EventType          m_Events;
+
+    TLMsg   *m_Selected;
+    long    m_separator;
+    int     m_new_x;
+    int     m_new_y;
+    Fl_Tree         *m_Tree;
+    Fl_Tree_Item    *m_CurrentTreeItem;
+    Fl_Text_Editor  *m_Editor;
+    Fl_Text_Buffer  *m_Buffer;
+    Model           *m_Model;
+};
+
+#endif
+//
+//
+//
diff --git a/cstav1/SniffHeader.h b/cstav1/SniffHeader.h
new file mode 100644 (file)
index 0000000..b4fa55b
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __SNIFF_HEADER_H__
+#define __SNIFF_HEADER_H__
+
+/* Ethernet addresses are 6 bytes */
+#define ETHER_ADDR_LEN 6
+
+       /* Ethernet header */
+       struct sniff_ethernet {
+               u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
+               u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
+               u_short ether_type; /* IP? ARP? RARP? etc */
+       };
+
+       /* IP header */
+       struct sniff_ip {
+               u_char ip_vhl;          /* version << 4 | header length >> 2 */
+               u_char ip_tos;          /* type of service */
+               u_short ip_len;         /* total length */
+               u_short ip_id;          /* identification */
+               u_short ip_off;         /* fragment offset field */
+       #define IP_RF 0x8000            /* reserved fragment flag */
+       #define IP_DF 0x4000            /* dont fragment flag */
+       #define IP_MF 0x2000            /* more fragments flag */
+       #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
+               u_char ip_ttl;          /* time to live */
+               u_char ip_p;            /* protocol */
+               u_short ip_sum;         /* checksum */
+               struct in_addr ip_src,ip_dst; /* source and dest address */
+       };
+       #define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
+       #define IP_V(ip)                (((ip)->ip_vhl) >> 4)
+
+       /* TCP header */
+       struct sniff_tcp {
+               u_short th_sport;       /* source port */
+               u_short th_dport;       /* destination port */
+#ifdef WIN32
+               unsigned long th_seq;           /* sequence number */
+               unsigned long th_ack;           /* acknowledgement number */
+#else
+               tcp_seq th_seq;         /* sequence number */
+               tcp_seq th_ack;         /* acknowledgement number */
+#endif
+               u_char th_offx2;        /* data offset, rsvd */
+       #define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
+               u_char th_flags;
+       #define TH_FIN 0x01
+       #define TH_SYN 0x02
+       #define TH_RST 0x04
+       #define TH_PUSH 0x08
+       #define TH_ACK 0x10
+       #define TH_URG 0x20
+       #define TH_ECE 0x40
+       #define TH_CWR 0x80
+       #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
+               u_short th_win;         /* window */
+               u_short th_sum;         /* checksum */
+               u_short th_urp;         /* urgent pointer */
+};
+
+struct sniff_udp {
+    u_short sport;
+    u_short dport;
+    u_short length;
+    u_short checksum;
+};
+
+#endif
diff --git a/cstav1/TLMsg.cpp b/cstav1/TLMsg.cpp
new file mode 100644 (file)
index 0000000..d86df09
--- /dev/null
@@ -0,0 +1,52 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#include <stdlib.h>
+#include <time.h>
+
+#if defined(_WINDOWS)
+#include <pcap/pcap.h>
+#endif
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+
+#include <CstaInsightLog.h>
+
+#if ! defined(__WIN32__) && ! defined(_WINDOWS)
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "Pcap.h"
+#include "TLMsg.h"
+
+TLMsg::TLMsg(const Packet &p,const std::string &_name)
+  : packet(p), name(_name),item(NULL),m_callid(""),m_Type(TLMsg::UNKNOWN)
+{
+}
+
+TLMsg::TLMsg(const TLMsg &t)
+{
+  name      = t.name;
+  distance  = t.distance;
+  sdistance = t.sdistance;
+  packet    = t.packet;
+  crid      = t.crid;
+  item      = t.item;
+  m_callid  = t.m_callid; 
+  m_Type    = t.m_Type;  
+}
+
+TLMsg::~TLMsg()
+{
+  CI_LOG_DEBUG("TLMsg::~TLMsg %s",name.c_str());
+}
+    
+void 
+TLMsg::set_distance(int source,int dest)
+{
+    sdistance = source;
+    distance  = dest;
+}
diff --git a/cstav1/TLMsg.h b/cstav1/TLMsg.h
new file mode 100644 (file)
index 0000000..0d0a7a1
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef TIMELINE_MSG_H__
+#define TIMELINE_MSG_H__
+
+/**
+ * TimelineMsg class represents one line in the sequence diagram.
+ *
+ * For now, all attributes are public but they need to be made protected.
+ * The value tv can directly be extracated from the Packet Class.
+ *
+ *
+ */
+class TLMsg {
+  public:
+
+    enum eMsgType {
+      SIP,
+      CSTA_REQUEST,
+      CSTA_RESPONSE,
+      CSTA_EVENT,
+      CSTA_RESPONSE_ERROR,
+      CSTA_REJECT,
+      SOAP_REQUEST,
+      SOAP_RESPONSE,
+      ICS_EVENT,
+      UNKNOWN
+    };
+    inline eMsgType msg_type() { return m_Type;};
+    inline void msg_type(eMsgType t) {m_Type = t; };
+
+    // The Distance in stored in a pair where first is source and second dest.
+    typedef std::pair<int,int> Distance;
+    
+    TLMsg() : item(NULL) {};
+    
+    TLMsg(const Packet &p,const std::string &_name);
+    
+    TLMsg(const TLMsg &t);
+    ~TLMsg();
+    inline struct timeval get_timeval() const {return packet.get_timeval();};
+    
+    Distance get_distance() const {return Distance(sdistance,distance);};
+
+    void set_distance(int source,int dest);
+    // Title settings 
+    inline void title(const std::string &s) {m_title = s;};
+    inline const char * title(void) {return m_title.c_str();};
+
+    inline void line(int l ) {m_line = l;};
+    inline int  line(void) {return m_line;};
+
+    inline void call_id(const std::string &s) {m_callid = s;};
+    inline std::string call_id() {return m_callid;};
+    eMsgType   m_Type;
+    std::string name;
+    int  crid;       // Destination of the message. Crid was used because at the begining, only CSTA was concerned
+    int distance;    // Distance from 0 to Crid is not enough for sip messages. 
+    int sdistance;   // By default, sdistance is 0
+    struct timeval tv;
+    // What to when sip with source and destination ?
+    Packet packet;
+    std::string m_title;        // Title of the message will be different from core message
+    std::string m_callid;       // Callid used to color line depending on call
+    Fl_Tree_Item *item;         // This must disapear 
+    int             m_line;     // Save the position of the text for this line.
+    std::string     m_content;  // Content to be displayed  
+} ;
+
+
+#endif
diff --git a/cstav1/TLMsgCsta.h b/cstav1/TLMsgCsta.h
new file mode 100644 (file)
index 0000000..0aaee72
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef TLMSGCSTA_H__
+#define TLMSGCSTA_H__
+
+class TLMsgCsta : public TLMsg
+{
+  public:
+    TLMsgCsta();
+    TLMsgCsta(
+            long crid,
+            long eventType,
+            Remote_Operations_Information_Objects::IOBJECT_TYPE *event_obj);
+    ~TLMsgCsta();
+
+
+};
+
+#endif
diff --git a/cstav1/TLMsgSip.h b/cstav1/TLMsgSip.h
new file mode 100644 (file)
index 0000000..018692e
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef TLMSGSIP_H__
+#define TLMSGSIP_H__
+
+class TLMsgSip : public TLMsg
+{
+  public:
+    TLMsgSip();
+    TLMsgSip(const TLMsgSip &_m);
+    ~TLMsgSip();
+  protected:
+};
+
+#endif
diff --git a/cstav1/TLMsgXml.h b/cstav1/TLMsgXml.h
new file mode 100644 (file)
index 0000000..c7a6153
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef TLMSGXML_H__
+#define TLMSGXML_H__
+
+
+class TLMsgXml : public TLMsg
+{
+  public:
+    TLMsgXml();
+    ~TLMsgXml();
+
+  protected:
+};
+#endif
diff --git a/cstav1/Timeline.cpp b/cstav1/Timeline.cpp
new file mode 100644 (file)
index 0000000..9d7b3ef
--- /dev/null
@@ -0,0 +1,119 @@
+#include <iostream>
+#include <sstream>
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include "Timeline.h"
+
+Timeline::Timeline(int crid, const char *name)
+  : m_crid(crid), m_port(0),m_name(name),m_type(TL_CRID)
+{
+    if (m_name.size() < 2)
+    {
+        std::stringstream ss;
+        ss<<"Crid<"<<crid<<">";
+        m_name = ss.str();
+    }
+}
+
+Timeline::Timeline(int crid, unsigned short port,const char *name)
+  : m_crid(crid), m_port(port),m_name(name),m_type(TL_CRID_PORT)
+{
+    if (m_name.size() < 2)
+    {
+        std::stringstream ss;
+        ss<<"Crid<"<<crid<<">{"<<port<<"}";
+        m_name = ss.str();
+    }
+}
+
+
+Timeline::Timeline(unsigned short port, const char *name)
+  : m_crid(0),m_port(port), m_name(name),m_type(TL_PORT)
+{
+    if (m_name.size() < 2)
+    {
+        std::stringstream ss;
+        ss<<"Crid<"<<m_crid<<">("<<port<<")";
+        m_name = ss.str();
+    }
+}
+
+
+Timeline::Timeline(struct in_addr crid, const char *name)
+  : m_crid((int)crid.s_addr), m_port(0),m_name(name),m_type(TL_IP)
+{
+    if (m_name.size() < 2)
+    {
+        std::stringstream ss;
+        ss<<"@<"<<inet_ntoa(crid)<<">";
+        m_name = ss.str();
+    }
+}
+
+
+Timeline::Timeline(const Timeline &t)
+{
+    m_crid = t.m_crid;
+    m_name = t.m_name;
+    m_type = t.m_type;
+    m_port = t.m_port;
+    m_device = t.m_device;
+}
+
+Timeline::~Timeline()
+{
+}
+
+bool 
+Timeline::operator ==(const Timeline &_t) const
+{
+  if (m_type == TL_CRID)
+  {
+    return (m_crid == _t.m_crid);
+  } else if (m_type == TL_CRID_PORT && _t.m_type == TL_CRID) 
+  {
+    return (m_crid == _t.m_crid);
+  } else if (m_type == TL_CRID_PORT && _t.m_type == TL_CRID_PORT) 
+  {
+    return ((m_port == _t.m_port) &&
+            (m_crid == _t.m_crid) 
+           );
+  } else if (m_type == TL_CRID_PORT && _t.m_type == TL_PORT) 
+  {
+    return ((m_port == _t.m_port) 
+           );
+  } else if (m_type == TL_PORT && _t.m_type == TL_CRID_PORT) 
+  {
+    return ((m_port == _t.m_port)  
+           );
+  } else if (m_type == TL_IP && _t.m_type == TL_IP) 
+  {
+    return ((m_crid == _t.m_crid)  
+           );
+  } else if (m_type == TL_PORT && _t.m_type == TL_PORT) 
+  {
+    return ((m_port == _t.m_port)  
+           );
+  }else 
+    return false;
+}
+
+
+bool 
+Timeline::operator ==(const struct in_addr &_t) const
+{
+    return (m_crid == _t.s_addr) && (m_type == TL_IP);
+}
+
+bool 
+Timeline::operator ==(short _t) const
+{
+    return (m_port == _t) && (
+                   (m_type == TL_PORT)
+                   ||(m_type == TL_CRID_PORT));
+}
diff --git a/cstav1/Timeline.h b/cstav1/Timeline.h
new file mode 100644 (file)
index 0000000..0608686
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __TIMELINE_H__
+#define __TIMELINE_H__
+
+class Timeline {
+  public:
+      enum {
+          TL_CRID,
+          TL_CRID_PORT,
+          TL_PORT,       // from one IP port to another
+          TL_IP
+      };
+    Timeline (int crid,const char *name=NULL);
+    Timeline (int crid,unsigned short port,const char *name=NULL);
+    Timeline (unsigned short port,const char *name=NULL);
+    Timeline (struct in_addr  crid,const char *name=NULL);
+    Timeline (const Timeline &t);
+    virtual ~Timeline();
+
+    inline const char *name() const {return m_name.c_str();};
+
+    inline void set_device(std::string &_d) { m_device = _d;};
+    inline void get_device(std::string &_d) const {  _d = m_device;};
+
+    bool operator ==(const Timeline &_t) const;
+    bool operator ==(short _t) const;
+    bool operator ==(const struct in_addr &_t) const;
+
+  protected:
+  std::string    m_name;
+  int            m_crid;     // In case the time lines belongs to csta events
+  int            m_type;
+  unsigned short m_port;
+  std::string    m_device; // Device number. If available not null.
+};
+
+#endif
diff --git a/cstav1/XMLMessage.h b/cstav1/XMLMessage.h
new file mode 100644 (file)
index 0000000..ed15355
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef XMLMESSAGES_H__
+#define XMLMESSAGES_H__
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <stack>
+#include <stdlib.h>
+#include <time.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Widget.H>
+#include <FL/Fl_Tree.H>
+
+#include  "CExpatImpl.h"
+/**
+ * \brief This class is used to parse ics events and soap requests.
+ * The parse request will be put in a tree
+ */
+class XMLMessage  : public CExpatImpl<XMLMessage>
+{
+  public:
+    XMLMessage(Fl_Tree *tree,Fl_Tree_Item *item) :m_tree(tree),m_item(item){
+      m_stack.push(item);
+      item->close();
+    };
+    ~XMLMessage() {};
+    void OnPostCreate()
+    {
+        // Enable all the event routines we want
+        EnableStartElementHandler ();
+        EnableEndElementHandler ();
+        // Note: EnableElementHandler will do both start and end
+        EnableCharacterDataHandler ();
+    }
+
+     virtual void OnStartElement (const XML_Char *pszName, 
+         const XML_Char **papszAttrs)
+     {
+         m_stack.push(m_tree->add(m_stack.top(),pszName));
+         return;
+     }
+     // @cmember End element handler
+     virtual void OnEndElement (const XML_Char *pszName)
+     {
+         m_stack.pop();
+         return;
+     }
+     // @cmember Character data handler
+     virtual void OnCharacterData (const XML_Char *pszData, int nLength)
+     {
+         std::string old(m_stack.top()->label());
+         std::string toadd(pszData,nLength);
+         old+= " ";
+         old+=toadd;
+         m_stack.top()->label(old.c_str());
+         return;
+     }
+
+  protected:
+    Fl_Tree         *m_tree; // The tree were to inserr sub elements
+    Fl_Tree_Item    *m_item; // Base Itesm
+    std::stack<Fl_Tree_Item *>  m_stack;
+};
+#endif
diff --git a/cstav1/cstaspyui.fl b/cstav1/cstaspyui.fl
new file mode 100644 (file)
index 0000000..93424f5
--- /dev/null
@@ -0,0 +1,688 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0300 
+header_name {.h} 
+code_name {.cxx}
+decl {\#include <iostream>} {public global
+} 
+
+decl {\#include <fstream>} {public global
+} 
+
+decl {\#include <string.h>} {public global
+} 
+
+decl {\#include <sstream>} {private global
+} 
+
+decl {\#include <map>} {public global
+} 
+
+decl {\#include <algorithm>} {private global
+} 
+
+decl {\#include <stack>} {public global
+} 
+
+declblock {\#if defined(__WIN32__) ||defined (_WINDOWS)} {public after {\#endif}
+} {
+  decl {\#include <pcap/pcap.h>} {public global
+  }
+} 
+
+decl {\#include "XMLMessage.h"} {public global
+} 
+
+decl {\#include "Pcap.h"} {public global
+} 
+
+decl {\#include <FL/Fl_File_Chooser.H>} {private global
+} 
+
+decl {\#include <FL/Fl_PNG_Image.H>} {public local
+} 
+
+decl {\#include <FL/Fl_Text_Editor.H>} {public local
+} 
+
+decl {\#include <FL/Fl_Text_Buffer.H>} {public local
+} 
+
+decl {\#include "CstaInsightLog.h"} {public global
+} 
+
+declblock {\#if defined(__WIN32__) ||defined (_WINDOWS)} {public after {\#endif}
+} {
+  decl {\#include <pcap/pcap.h>} {public global
+  }
+  decl {\#else} {public global
+  }
+  decl {\#include <netinet/in.h>} {public global
+  }
+  decl {\#include <arpa/inet.h>} {public global
+  }
+} 
+
+decl {\#include "rtasn1/asn1.h"} {
+  comment {// Asn1 stuff} private local
+} 
+
+decl {\#include "rtasn1/asn1_codec.h"} {private global
+} 
+
+decl {\#include "rtasn1/asn1_codec_ber.h"} {private local
+} 
+
+decl {\#include "Rose_Apdu.h"} {
+  comment {// CSTA stubs} public global
+} 
+
+decl {\#include "CSTA_event.h"} {public global
+} 
+
+decl {\#include "SequenceView.h"} {public global
+} 
+
+decl {\#include "HeaderView.h"} {public global
+} 
+
+decl {\#include "Model.h"} {
+  comment {// Model View Controler files} public global
+} 
+
+decl {\#include "Controler.h"} {public global
+} 
+
+decl {Fl_File_Chooser *fc;} {
+  comment {// File Chooser} private local
+} 
+
+class MainUI {open
+} {
+  Function {MainUI()} {} {
+    code {m_Buffer = new Fl_Text_Buffer(1024*16);\r
+m_Model     = new Model();\r
+m_Controler = new Controler(m_Model);} {}
+  }
+  Function {make_window()} {open
+  } {
+    Fl_Window m_Window {
+      label {CSTA Insight} open
+      xywh {815 139 1035 855} type Double resizable
+      code0 {fc = new Fl_File_Chooser(".","*",Fl_File_Chooser::SINGLE,"Select OmniPCX Office CSTA stream");} visible
+    } {
+      Fl_Menu_Bar {} {open
+        xywh {0 0 1035 22}
+      } {
+        Submenu {} {
+          label {&File}
+          xywh {0 0 100 20} labelsize 12
+        } {
+          MenuItem {} {
+            label {&Open}
+            callback {int i;\r
+int count = 0;\r
+char relative[FL_PATH_MAX];\r
+\r
+fc->show();\r
+\r
+while(fc->visible() )\r
+{\r
+  Fl::wait();\r
+}\r
+\r
+count = fc->count();\r
+std::cout<<"Got count  = "<<count<<"\\n";\r
+\r
+if (count > 0)\r
+{\r
+  for (i = 0 ; i < count; i++)\r
+  {\r
+    if (!fc->value(i))\r
+      break;\r
+    fl_filename_relative(relative,sizeof(relative),fc->value(i));\r
+    std::cout<<" Selected : "<<relative<<std::endl;\r
+    if (strstr(fc->value(i),".pcap"))\r
+    {\r
+      char *pos = (char *)strstr(fc->value(i),".pcap");\r
+      m_current_filename = relative;\r
+\#ifndef __WIN32__\r
+      while (*pos != '/')\r
+        pos--;\r
+\#endif\r
+      pos++;\r
+      std::cout<<"Process PCAP file :"<<fc->value(i)<<std::endl;\r
+      if (!tree->root())\r
+      {\r
+        tree->add("ROOT");\r
+      }\r
+      tree->root_label(pos);\r
+      m_Controler->load(relative);\r
+//      do_pcap(relative);\r
+    } else {\r
+      std::cout<<"Unsuported format\\n";\r
+    }\r
+    \r
+  }\r
+}\r
+\r
+char iPath[100];\r
+\r
+Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");\r
+Fl_Preferences Cfg(app,m_current_filename.c_str());\r
+Cfg.get("filter",iPath,m_InputChoice->value(),99);\r
+m_InputChoice->value(iPath);\r
+//Cfg.set("filter",m_InputChoice->value());}
+            xywh {0 0 100 20} labelsize 12
+          }
+          MenuItem {} {
+            label {&Close}
+            callback {tree->clear_children(tree->root());\r
+m_Controler->close();\r
+tree->root_label("ROOT");\r
+m_Sequence->clear();\r
+tree->redraw();\r
+m_Sequence->redraw();\r
+m_Scroll->redraw();\r
+m_Editor->buffer()->remove(0,m_Editor->buffer()->length());}
+            xywh {0 0 100 20} labelsize 12 divider
+          }
+          MenuItem {} {
+            label {&Export XMI}
+            xywh {0 0 100 20} labelsize 12
+          }
+          MenuItem {} {
+            label {Export Msc}
+            callback {int i;\r
+int count = 0;\r
+char relative[FL_PATH_MAX];\r
+\r
+fc->show();\r
+\r
+while(fc->visible() )\r
+{\r
+  Fl::wait();\r
+}\r
+\r
+count = fc->count();\r
+\r
+\r
+if (count > 0)\r
+{\r
+  for (i = 0 ; i < count; i++)\r
+  {\r
+    if (!fc->value(i))\r
+      break;\r
+    fl_filename_relative(relative,sizeof(relative),fc->value(i));\r
+    std::cout<<" Selected : "<<relative<<std::endl;\r
+    if (strstr(fc->value(i),".pcap"))\r
+    {\r
+      \r
+      char *pos = strstr(relative,".pcap");\r
+      //m_current_filename = relative;\r
+\#ifndef __WIN32__\r
+      //while (*pos != '/')\r
+      //  pos--;\r
+\#else\r
+      std::cout<<"HOHOHOHOHO"<<std::endl;\r
+\#endif\r
+      if (pos != NULL)\r
+      {\r
+        strcpy(pos,".signaling");\r
+      }\r
+      \r
+      std::cout<<"Export to  file :"<<relative<<std::endl;\r
+      m_Model->export_msc(relative);\r
+      //m_Controler->load(relative);\r
+//      do_pcap(relative);\r
+    } else {\r
+      std::cout<<"Unsuported format\\n";\r
+    }\r
+    \r
+  }\r
+}\r
+\r
+//Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");\r
+//Fl_Preferences Cfg(app,m_current_filename.c_str());\r
+//Cfg.get("filter",iPath,m_InputChoice->value(),99);\r
+//m_InputChoice->value(iPath);}
+            xywh {0 0 100 20} labelsize 12 divider
+          }
+          MenuItem {} {
+            label {&Preferences}
+            callback {m_Preferences->show();}
+            xywh {0 0 100 20} labelsize 12
+          }
+          MenuItem {} {
+            label {&Print}
+            xywh {0 0 100 20} labelsize 12 divider
+          }
+          MenuItem {} {
+            label {&Quit}
+            callback {exit(1);}
+            xywh {0 0 100 20} labelsize 12
+          }
+        }
+        Submenu {} {
+          label {&View} open
+          xywh {0 0 100 20} labelsize 12
+        } {
+          MenuItem {} {
+            label {Expand Tree}
+            xywh {0 0 36 21} labelsize 12
+          }
+          MenuItem {} {
+            label {Collapse Tree}
+            xywh {0 0 36 21} labelsize 12
+          }
+        }
+        Submenu {} {
+          label {&Help} open
+          xywh {0 0 100 20} labelsize 12
+        } {
+          MenuItem {} {
+            label {&About}
+            xywh {0 0 100 20} labelsize 12
+          }
+        }
+      }
+      Fl_Group {} {open
+        xywh {0 22 1035 22}
+      } {
+        Fl_Button {} {
+          label Apply
+          callback {if (m_current_filename.size() > 3) {\r
+  std::string rl(tree->root()->label());\r
+  // First clean inputs.\r
+  do_close();\r
+  // call do_pcap with filter.\r
+  std::string filter(m_InputChoice->value());\r
+  //do_pcap(m_current_filename.c_str(),m_Filter->value());\r
+//  do_pcap(m_current_filename.c_str(),filter.c_str());\r
+\r
+  m_Controler->load(m_current_filename.c_str(),filter.c_str());\r
+  m_ScrollHeader->redraw();\r
+  tree->root()->label(rl.c_str());\r
+}}
+          xywh {401 22 70 22} labelsize 12
+        }
+        Fl_Button {} {
+          label Clear
+          callback {if (m_current_filename.size() > 4) \r
+{\r
+    do_close();\r
+    m_ScrollHeader->redraw();\r
+}}
+          xywh {469 22 70 22} labelsize 12
+        }
+        Fl_Input_Choice m_InputChoice {
+          label Filter
+          callback {char iPath[100];\r
+\r
+Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");\r
+Fl_Preferences Cfg(app,m_current_filename.c_str());\r
+//Cfg.get("filter",iPath,m_InputChoice->value(),99);\r
+Cfg.set("filter",m_InputChoice->value());} open
+          xywh {36 22 365 22} down_box DOWN_FRAME labelsize 12 textsize 12
+        } {}
+        Fl_Box {} {
+          xywh {543 23 489 21} resizable
+        }
+      }
+      Fl_Tile {} {
+        callback {CI_LOG_DEBUG("Tile Event");
+//tree->redraw();\r
+//m_Editor->redraw();\r
+//m_Sequence->redraw();\r
+\r
+//m_Tabs->damage(FL_DAMAGE_ALL);\r
+//m_Tabs->value()->redraw()} open selected
+        xywh {0 45 1035 810} box BORDER_BOX when 1 resizable
+      } {
+        Fl_Tree tree {
+          callback {Fl_Tree_Item *item = tree->callback_item();\r
+\r
+if (item)\r
+{\r
+  if (tree->callback_reason() == FL_TREE_REASON_SELECTED)\r
+  {\r
+    m_Controler->select((TLMsg *)item->user_data());\r
+    //m_Editor->scroll((long )item->user_data(),0);
+    m_Scroll->redraw();
+  } else if (tree->callback_reason() == FL_TREE_REASON_DESELECTED)\r
+  {\r
+  }\r
+} else {\r
+  // No Item forget the event\r
+}\r
+\r
+tree->clear_changed();}
+          xywh {0 45 300 610} selection_color 23 labelsize 10 align 65
+        }
+        Fl_Scroll m_ScrollHeader {
+          xywh {300 45 735 70} box DOWN_BOX color 7 labelsize 12
+        } {
+          Fl_Box m_Header {
+            xywh {300 45 735 70} color 7 selection_color 40
+            code0 {\#include "HeaderView.h"}
+            class HeaderView
+          }
+        }
+        Fl_Scroll m_Scroll {
+          callback {printf("Event : Scroll\\n");
+m_Scroll->clear_changed();} open
+          xywh {300 115 735 540} box DOWN_BOX color 7 align 65 when 1
+        } {
+          Fl_Box m_Sequence {
+            label {Sequence view}
+            callback {printf("Possile if handle method is properly coded\\n");}
+            xywh {300 115 735 540} color 7 selection_color 55 labelsize 12 when 1
+            code0 {\#include "SequenceView.h"}
+            class SequenceView
+          }
+        }
+        Fl_Group {} {open
+          xywh {0 655 1035 200} box FLAT_BOX
+        } {
+          Fl_Tabs m_Tabs {open
+            xywh {0 655 1035 200} labelsize 12 align 65 when 1
+          } {
+            Fl_Group {} {
+              label Traces
+              xywh {7 680 1030 175} selection_color 41 labelsize 12 resizable
+            } {
+              Fl_Text_Editor m_Editor {
+                callback {//m_Editor->buffer(m_Buffer);\r
+printf("m_Editor what here ?\\n");}
+                xywh {10 686 1023 165} box BORDER_BOX labelsize 10 textsize 12 resizable
+              }
+            }
+            Fl_Group {} {
+              label Preferences open
+              xywh {7 680 1030 175} selection_color 41 labelsize 12 hide
+            } {
+              Fl_Scroll {} {open
+                xywh {0 680 1034 171}
+              } {
+                Fl_Group {} {
+                  label Ports open
+                  xywh {20 705 300 140} box ENGRAVED_FRAME color 48 labelsize 12 align 133
+                } {
+                  Fl_Input {} {
+                    label {CSTA port :}
+                    xywh {100 725 96 22} labelsize 12 textsize 12
+                    code0 {o->value("2555");}
+                  }
+                  Fl_Input {} {
+                    label {SIP    port :}
+                    xywh {100 751 96 22} labelsize 12 textsize 12
+                    code0 {o->value("5059");}
+                  }
+                  Fl_Input {} {
+                    label {OTS   port :}
+                    xywh {100 777 95 22} labelsize 12 textsize 12
+                    code0 {o->value("8894");}
+                  }
+                  Fl_Box {} {
+                    xywh {22 818 293 25} resizable
+                  }
+                }
+                Fl_Box {} {
+                  label License
+                  xywh {349 705 267 140} box ENGRAVED_FRAME labelsize 12 align 5
+                }
+                Fl_Box {} {
+                  xywh {630 708 29 126} resizable
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  Function {make_prefs()} {open
+  } {
+    Fl_Window m_Preferences {
+      label Preferences
+      xywh {1360 53 370 350} type Double modal visible
+    } {
+      Fl_Tabs {} {open
+        xywh {0 1 370 325}
+      } {
+        Fl_Group {} {
+          label {Gérénal}
+          xywh {0 25 370 300} labelsize 12 hide
+        } {
+          Fl_Group {} {
+            label Application open
+            xywh {5 45 357 270} box EMBOSSED_FRAME labelsize 12 align 517
+          } {
+            Fl_File_Input m_IconPath {
+              label Icon
+              xywh {42 54 293 32} labelsize 12 textsize 12
+            }
+          }
+        }
+        Fl_Group {} {
+          label {Séquence View}
+          xywh {0 25 370 300} labelsize 12 hide
+        } {
+          Fl_Check_Button {} {
+            label {Display port number   }
+            xywh {145 33 20 25} down_box DOWN_BOX labelsize 12 align 4
+          }
+          Fl_Spinner {} {
+            label {Timeline space            }
+            xywh {145 53 50 25} labelsize 12 value 150
+          }
+        }
+        Fl_Group {} {
+          label Ports
+          xywh {0 25 370 300} labelsize 12 hide
+        } {
+          Fl_Group {} {
+            label {Port numbers} open
+            xywh {11 47 345 275} box ENGRAVED_FRAME labelsize 12 align 5
+          } {
+            Fl_Input {} {
+              label {CSTA port    }
+              xywh {100 60 70 25} labelsize 12 textsize 12
+              code0 {o->value("2555");}
+            }
+            Fl_Input {} {
+              label {OTS   port    }
+              xywh {100 88 70 25} labelsize 12 textsize 12
+              code0 {o->value("8894");}
+            }
+            Fl_Input {} {
+              label {SIP    port    }
+              xywh {100 116 70 25} labelsize 12 textsize 12
+              code0 {o->value("5059");}
+            }
+          }
+        }
+        Fl_Group {} {
+          label Debug open
+          xywh {0 25 370 300} labelsize 12
+        } {
+          Fl_Check_Button m_DumpHex {
+            label {Dump hex in console    }
+            xywh {150 29 67 25} down_box DOWN_BOX labelsize 12 align 4
+          }
+          Fl_Input_Choice m_Asn1DebugLevel {
+            label {Asn1 Debug Level        } open
+            xywh {150 51 67 25} labelsize 12 textsize 12
+          } {
+            MenuItem {} {
+              label Critical
+              callback {asn1::types::debug_level = 4;\r
+m_Asn1DebugLevel->value("Critical");}
+              xywh {15 15 100 20}
+            }
+            MenuItem {} {
+              label Error
+              callback {asn1::types::debug_level = 5;\r
+m_Asn1DebugLevel->value("Error");}
+              xywh {15 15 100 20}
+            }
+            MenuItem {} {
+              label Info
+              callback {asn1::types::debug_level = 6;\r
+m_Asn1DebugLevel->value("Info");}
+              xywh {15 15 100 20}
+            }
+            MenuItem {} {
+              label Debug
+              callback {asn1::types::debug_level = 7;\r
+m_Asn1DebugLevel->value("Debug");}
+              xywh {15 15 100 20}
+            }
+          }
+          Fl_Input_Choice m_AppDebugLevel {
+            label {App Debug Level          } open
+            xywh {150 80 67 25} labelsize 12 align 132 textsize 12
+          } {
+            MenuItem {} {
+              label Critical
+              callback {cid_level = 4;
+m_AppDebugLevel->value("Critical");}
+              xywh {0 0 100 20}
+            }
+            MenuItem {} {
+              label Error
+              callback {cid_level = 3;
+m_AppDebugLevel->value("Error");}
+              xywh {0 0 100 20}
+            }
+            MenuItem {} {
+              label Warning
+              callback {cid_level = 4;
+m_AppDebugLevel->value("Warning");}
+              xywh {0 0 100 20}
+            }
+            MenuItem {} {
+              label Info
+              callback {cid_level = 5;
+m_AppDebugLevel->value("Info");}
+              xywh {0 0 100 20}
+            }
+            MenuItem {} {
+              label Debug
+              callback {cid_level = 8;
+m_AppDebugLevel->value("Debug");}
+              xywh {0 0 100 20}
+            }
+          }
+        }
+      }
+      Fl_Group {} {open
+        xywh {2 324 369 26}
+      } {
+        Fl_Return_Button {} {
+          label Ok
+          callback {writePrefs();\r
+m_Preferences->hide();}
+          xywh {239 327 54 22}
+        }
+        Fl_Button {} {
+          label Cancel
+          callback {m_Preferences->hide();}
+          xywh {290 327 81 22}
+        }
+      }
+    }
+  }
+  Function {readPrefs()} {} {
+    code {Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");\r
+\r
+Fl_Preferences iconPath(app,"iconPath");\r
+char ipath[79];\r
+iconPath.get("path",ipath,"/home/aebersol/Devs/home/home/parser/asn1/cstav1/images/",79);\r
+m_IconPath->value(ipath);} {}
+  }
+  Function {writePrefs()} {} {
+    code {Fl_Preferences app(Fl_Preferences::USER,"CSTASpy","main");\r
+\r
+Fl_Preferences iconPath(app,"iconPath");\r
+iconPath.set("path",m_IconPath->value());} {}
+  }
+  Function {show(int argc,char **argv)} {open
+  } {
+    code {m_Editor->buffer(m_Buffer);\r
+// Only here\r
+m_InputChoice->add("");\r
+m_InputChoice->add("not(src and dst port 5059 or port 5080)");\r
+m_InputChoice->add("not(port 5080)");\r
+m_InputChoice->add("not(src and dst port 5059 or port 5080 or 8894)");\r
+\r
+asn1::types::debug_level = 6;\r
+m_Asn1DebugLevel->value("Info");\r
+m_Header->model(m_Model);\r
+m_Sequence->model(m_Model);\r
+m_Sequence->tree(tree);\r
+m_Sequence->editor(m_Editor);\r
+m_Window->show(argc,argv);} {}
+  }
+  Function {do_close()} {} {
+    code {tree->clear_children(tree->root());\r
+tree->root_label("ROOT");\r
+m_Sequence->clear();\r
+tree->redraw();\r
+m_Sequence->redraw();\r
+m_Scroll->redraw();\r
+m_Editor->buffer()->remove(0,m_Editor->buffer()->length());\r
+m_Controler->close();\r
+m_Header->damage(FL_DAMAGE_ALL);\r
+m_Header->redraw();} {}
+  }
+  decl {Fl_Text_Buffer *m_Buffer;} {protected local
+  }
+  decl {std::string m_current_filename} {protected local
+  }
+  decl {Model *m_Model;} {protected local
+  }
+  decl {Controler *m_Controler;} {protected local
+  }
+  Function {callToString(const std::string &ins,std::string &out)} {open
+  } {
+    code {int res = 0;\r
+for (std::string::const_iterator it = ins.begin() ; \r
+         it !=  ins.end(); ++it)\r
+         res = res << 8 | (unsigned char)(*it);\r
+\r
+std::stringstream ints; ints<<res;\r
+out += ints.str();} {}
+  }
+  Function {make_slash_screen()} {
+    comment {//Build the splash screen} open
+  } {
+    code {Fl_Window *o = new Fl_Window(550,400,"Splash Screen"); 
+o->type(241);
+o->begin();
+  Fl_Group *g = new Fl_Group(0,0,550,400);
+  g->resizable(o);
+o->end();
+o->set_non_modal();
+o->clear_border();
+o->resizable(o);
+
+o->border(false);
+
+o->show();
+// o->flush();
+do {
+  Fl::check();
+} while(! o->visible());} {}
+  }
+} 
+
+Function {} {
+  comment {// Main entry point}
+} {
+  code {MainUI m;\r
+m.make_window();\r
+m.make_prefs();\r
+m.readPrefs();\r
+m.show(argc,argv);\r
+Fl::run();} {}
+} 
diff --git a/cstav1/data/double_appel_csta.pcap b/cstav1/data/double_appel_csta.pcap
new file mode 100755 (executable)
index 0000000..3efb828
Binary files /dev/null and b/cstav1/data/double_appel_csta.pcap differ
diff --git a/cstav1/data/listen_vm_vhe_csta.pcap b/cstav1/data/listen_vm_vhe_csta.pcap
new file mode 100755 (executable)
index 0000000..995db65
Binary files /dev/null and b/cstav1/data/listen_vm_vhe_csta.pcap differ
diff --git a/cstav1/data/ma_change_filtering_level_3_csta.pcap b/cstav1/data/ma_change_filtering_level_3_csta.pcap
new file mode 100755 (executable)
index 0000000..dba936c
Binary files /dev/null and b/cstav1/data/ma_change_filtering_level_3_csta.pcap differ
diff --git a/cstav1/data/ma_change_filtering_level_filtering_to_screening_csta.pcap b/cstav1/data/ma_change_filtering_level_filtering_to_screening_csta.pcap
new file mode 100755 (executable)
index 0000000..5481831
Binary files /dev/null and b/cstav1/data/ma_change_filtering_level_filtering_to_screening_csta.pcap differ
diff --git a/cstav1/data/ma_change_filtering_level_none_to_filtering_csta.pcap b/cstav1/data/ma_change_filtering_level_none_to_filtering_csta.pcap
new file mode 100755 (executable)
index 0000000..8f6d3c9
Binary files /dev/null and b/cstav1/data/ma_change_filtering_level_none_to_filtering_csta.pcap differ
diff --git a/cstav1/data/make_call_csta.pcap b/cstav1/data/make_call_csta.pcap
new file mode 100755 (executable)
index 0000000..cbd2b99
Binary files /dev/null and b/cstav1/data/make_call_csta.pcap differ
diff --git a/cstav1/data/make_call_redirect_vm_csta.pcap b/cstav1/data/make_call_redirect_vm_csta.pcap
new file mode 100755 (executable)
index 0000000..c147372
Binary files /dev/null and b/cstav1/data/make_call_redirect_vm_csta.pcap differ
diff --git a/cstav1/data/myicoffice_monitor_sip_transfer_call_withoutsip_releasing.pcap b/cstav1/data/myicoffice_monitor_sip_transfer_call_withoutsip_releasing.pcap
new file mode 100755 (executable)
index 0000000..75f257b
Binary files /dev/null and b/cstav1/data/myicoffice_monitor_sip_transfer_call_withoutsip_releasing.pcap differ
diff --git a/cstav1/data/myicoffice_msip130_make_call_ua.pcap b/cstav1/data/myicoffice_msip130_make_call_ua.pcap
new file mode 100755 (executable)
index 0000000..42d802c
Binary files /dev/null and b/cstav1/data/myicoffice_msip130_make_call_ua.pcap differ
diff --git a/cstav1/data/ots_start_csta.pcap b/cstav1/data/ots_start_csta.pcap
new file mode 100755 (executable)
index 0000000..e579ebf
Binary files /dev/null and b/cstav1/data/ots_start_csta.pcap differ
diff --git a/cstav1/data/sip130_make_call_ua.pcap b/cstav1/data/sip130_make_call_ua.pcap
new file mode 100755 (executable)
index 0000000..ada847e
Binary files /dev/null and b/cstav1/data/sip130_make_call_ua.pcap differ
diff --git a/cstav1/images/Funnel_16.png b/cstav1/images/Funnel_16.png
new file mode 100755 (executable)
index 0000000..1ee93d9
Binary files /dev/null and b/cstav1/images/Funnel_16.png differ
diff --git a/cstav1/images/Lighting_16.png b/cstav1/images/Lighting_16.png
new file mode 100755 (executable)
index 0000000..a03d096
Binary files /dev/null and b/cstav1/images/Lighting_16.png differ
diff --git a/cstav1/images/RequestSoap_16.png b/cstav1/images/RequestSoap_16.png
new file mode 100755 (executable)
index 0000000..1663fb7
Binary files /dev/null and b/cstav1/images/RequestSoap_16.png differ
diff --git a/cstav1/images/Request_16.png b/cstav1/images/Request_16.png
new file mode 100755 (executable)
index 0000000..053d6c4
Binary files /dev/null and b/cstav1/images/Request_16.png differ
diff --git a/cstav1/images/ResponseError_16.png b/cstav1/images/ResponseError_16.png
new file mode 100755 (executable)
index 0000000..bc3677c
Binary files /dev/null and b/cstav1/images/ResponseError_16.png differ
diff --git a/cstav1/images/ResponseReject_16.png b/cstav1/images/ResponseReject_16.png
new file mode 100755 (executable)
index 0000000..2dcffc0
Binary files /dev/null and b/cstav1/images/ResponseReject_16.png differ
diff --git a/cstav1/images/ResponseSoap_16.png b/cstav1/images/ResponseSoap_16.png
new file mode 100755 (executable)
index 0000000..8d9c1d2
Binary files /dev/null and b/cstav1/images/ResponseSoap_16.png differ
diff --git a/cstav1/images/Response_16.png b/cstav1/images/Response_16.png
new file mode 100755 (executable)
index 0000000..7e75e46
Binary files /dev/null and b/cstav1/images/Response_16.png differ
diff --git a/cstav1/images/Server_24.png b/cstav1/images/Server_24.png
new file mode 100755 (executable)
index 0000000..5e22562
Binary files /dev/null and b/cstav1/images/Server_24.png differ
diff --git a/cstav1/images/Server_48.png b/cstav1/images/Server_48.png
new file mode 100755 (executable)
index 0000000..6cb37e8
Binary files /dev/null and b/cstav1/images/Server_48.png differ
diff --git a/cstav1/images/Sip_16.png b/cstav1/images/Sip_16.png
new file mode 100755 (executable)
index 0000000..c7c56ed
Binary files /dev/null and b/cstav1/images/Sip_16.png differ
diff --git a/cstav1/images/VTSip_24.png b/cstav1/images/VTSip_24.png
new file mode 100755 (executable)
index 0000000..c8fd25a
Binary files /dev/null and b/cstav1/images/VTSip_24.png differ
diff --git a/cstav1/images/VTSip_48.png b/cstav1/images/VTSip_48.png
new file mode 100755 (executable)
index 0000000..d0676f0
Binary files /dev/null and b/cstav1/images/VTSip_48.png differ
diff --git a/cstav1/images/VT_24.png b/cstav1/images/VT_24.png
new file mode 100755 (executable)
index 0000000..3dd2e36
Binary files /dev/null and b/cstav1/images/VT_24.png differ
diff --git a/cstav1/images/VT_48.png b/cstav1/images/VT_48.png
new file mode 100755 (executable)
index 0000000..71e0c97
Binary files /dev/null and b/cstav1/images/VT_48.png differ
diff --git a/cstav1/main.cpp b/cstav1/main.cpp
new file mode 100644 (file)
index 0000000..2e5be98
--- /dev/null
@@ -0,0 +1,158 @@
+
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <typeinfo>
+#include <stdlib.h>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "Rose_Apdu.h"
+#include "CSTA_event.h"
+
+#include "Rose_Apdu.hpp"
+#include "CSTA_event.hpp"
+/**
+CSTAEventReportArgument ::= SEQUENCE {
+  crossRefIdentifier MonitorCorssRefID
+  eventSpecificInfo  EventSpecificInfo
+}
+ *
+ServiceInitiatedEventInfo ::= SEQUENCE {
+  initatedConnection ConnectionID,
+  localConnectionInfo LocalConnectionState OPTIONAL
+  cause EventCause OPTIONAL
+  }
+ *
+ConnectionID ::= [APPLICATION 11] CHOICE {
+  call  [2] IMPLICIT OCTET STRING OPTIONAL,
+  device CHOICE {
+    staticID DeviceID,
+    dynamicID [3] IMPLICIT OCTET STRING
+  }
+}
+
+CallID ::= OCTET STRING
+LocalDeviceID ::= CHOICE [
+  staticID DeviceID
+  dynamicID [3] IMPLICIT OCTET STRING
+}
+
+DeviceID ::= SEQUENCE {
+  deviceIdentifier CHOICE {
+  }
+}
+ */
+
+int test_decode()
+{
+  /* This sequence is for Alcatel CSTA which is not compatible with the ecma
+   * 285 description. Just  forget it. Events are described diferently*/
+  const unsigned char d[] ={ 0x30,0x46,
+        0x55,0x04,0x00,0x00,0x00,0x04,
+        0x80,0x01,0x0d, // For alcated, this Event Type 13 
+        //Context Specific - Primitive - Id=0 tag. Len 1 - value 0d 13 what is this ?
+        0x30,0x1d, /* ServiceInitiatedEvent SEQUENCE len 0x1d  29*/
+                0x6b,0x0a, /* ConnectionID tag APPL 11 len 10 CHOICE*/
+                     0x82,0x02,0x00,0x76, /* This should be both of ConnectionID*/
+                     0x83,0x04,0x00, 0x03,0x00,0x00, /* supposed to be dynamic ID*/
+                     /**  */
+        /* I d'ont know what this is */
+        0x4e,0x01,0x01,  /* State initated */
+        0x0a,0x01, 0x16, /* Event Cause newCall*/
+        0x63,0x05,0x84,0x03,0x31,0x30,0x32,
+        0x62,0x02,0x87,0X00,
+        0x7d,0x1c,  /* private date [APPLICATION 24 ] implicit */
+            0x06,0x06,0x2b,0x0c,0x89,0x36,0x83, 0x74,/*  manufacturer OBJECT ID  1.3.12.1206.500 */
+            0x04,0x12,0x03,0x01,0x00,0x00,0x0c,0x49,0x43,0x54,0x4f,0x55,0x43,0x48,0x5f,
+            0x4e , 0x4f,0x4e,0x45,0x00
+  };
+  
+  CSTA_event::CSTAEventReportArgument report; 
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),d,74);
+  //report.codec(ctx,report,asn1::CODEC_DECODE);
+  report.decode(ctx);
+  std::cout<<"Go type info="<<report.eventType.get_local().get_value()<<std::endl;
+  return 0;
+}
+
+int main(int argc,char **argv)
+{
+
+  //CSTA_event_report_definitions::cSTAEventReport report; 
+  //asn1::context ctx;
+  
+  if (argc > 1) {
+    // Try to decode a stream ....
+      std::ifstream is;
+    is.open(argv[1],std::ios::binary);
+    int len = 0;
+    char bl[2];
+    
+    memset(bl,0x00,3);
+    while (is.read(bl,2) && is.good()) 
+    {
+        len = bl[1] | bl[0]<<8;
+        std::cout<<" Read header "<<(unsigned short)bl[0]<<"-"<<(unsigned short)bl[1]<<" should decode len="<<len<<std::endl;
+        if (len < 4096)
+        {
+            Rose_Apdu::RoseAPDU pdu;
+            //asn1::context ctx(len);
+            asn1::streams::ber ctx(len);
+            is.read((char *)ctx.buffer(),len);
+            //pdu.codec(ctx,pdu,asn1::CODEC_DECODE);
+            pdu.decode(ctx);
+            if ( (ctx.nb_read_bits()>>3) == len )
+            {
+                std::cout<<"\n\n\tYES COMPLETELY DECODED\n";
+                switch (pdu.get_kind())
+                {
+                    case Rose_Apdu::RoseAPDU::typeof_invoke:
+                        std::cout<<"\tGot invoke ID="<<pdu.get_invoke().invokeID<<" ";
+                        if (pdu.get_invoke().operationValue.get_kind() == Remote_Operations_Information_Objects::OpCode::typeof_local)
+                        {
+                            std::cout<<" op code="<<pdu.get_invoke().operationValue.get_local()<<" "<<typeid(&pdu.get_invoke().argument).name()<<"\n";
+                            if (pdu.get_invoke().operationValue.get_local().get_value() == 21)
+                            {
+                              // Get OPERATION 
+                              CSTA_event::cSTAEventEvent *event;
+                              asn1::Object *_o = pdu.get_invoke().argument;
+                              event = dynamic_cast<CSTA_event::cSTAEventEvent *>(_o); 
+                              // Get OBJECT-TYPE
+                              CSTA_event::CSTAEventReportArgument report; 
+                              event->get_ArgumentType(report);
+                              std::cout<<"Go type info="<<report.eventType.get_local()<<std::endl;
+                              Remote_Operations_Information_Objects::IOBJECT_TYPE *event_obj;
+                              asn1::Object *_o1 = report.eventInfo; 
+                              event_obj = dynamic_cast<Remote_Operations_Information_Objects::IOBJECT_TYPE *>(_o1);
+
+                            }
+                        } else {
+                          std::cout<<std::endl;
+                        }
+                        break;
+                    case Rose_Apdu::RoseAPDU::typeof_retResult:
+                        break;
+                    case Rose_Apdu::RoseAPDU::typeof_retError:
+                        break;
+                    case Rose_Apdu::RoseAPDU::typeof_reject:
+                        break;
+                    default:
+                    ;
+                }
+            } else {
+                std::cout<<"\n\n\tINCOMPLET DECODE len="<<len<<" Decoded= "<<(ctx.nb_read_bits()>>3)<<"\n";
+            }
+        }
+        std::cout<<"\n\n";
+    }
+  
+  }
+  else 
+    test_decode();
+  //report.codec(ctx,asn1::CODEC_ENCODE);
+  std::cout<<"Hello world"<<std::endl;
+}
diff --git a/cstav1/modules.txt b/cstav1/modules.txt
new file mode 100644 (file)
index 0000000..3ea7420
--- /dev/null
@@ -0,0 +1,14 @@
+CSTA-connect
+CSTA-call
+CSTA-event
+CSTA-device
+CSTA-error
+CSTA-extend
+CSTA-feature
+CSTA-private
+CSTA-status
+CSTA-secure
+CSTA-switch
+Rose-Apdu
+CSTA-MSG
+ACSE-1
diff --git a/cstav1/sigslot.h b/cstav1/sigslot.h
new file mode 100755 (executable)
index 0000000..d52f380
--- /dev/null
@@ -0,0 +1,2521 @@
+// sigslot.h: Signal/Slot classes\r
+//\r
+// \r
+// Written by Sarah Thompson (sarah@telergy.com) 2002.\r
+//\r
+// License: Public domain. You are free to use this code however you like, with the proviso that\r
+//          the author takes on no responsibility or liability for any use.\r
+//\r
+// QUICK DOCUMENTATION \r
+//             \r
+//                             (see also the full documentation at http://sigslot.sourceforge.net/)\r
+//\r
+//             #define switches\r
+//                     SIGSLOT_PURE_ISO                        - Define this to force ISO C++ compliance. This also disables\r
+//                                                                               all of the thread safety support on platforms where it is \r
+//                                                                               available.\r
+//\r
+//                     SIGSLOT_USE_POSIX_THREADS       - Force use of Posix threads when using a C++ compiler other than\r
+//                                                                               gcc on a platform that supports Posix threads. (When using gcc,\r
+//                                                                               this is the default - use SIGSLOT_PURE_ISO to disable this if \r
+//                                                                               necessary)\r
+//\r
+//                     SIGSLOT_DEFAULT_MT_POLICY       - Where thread support is enabled, this defaults to multi_threaded_global.\r
+//                                                                               Otherwise, the default is single_threaded. #define this yourself to\r
+//                                                                               override the default. In pure ISO mode, anything other than\r
+//                                                                               single_threaded will cause a compiler error.\r
+//\r
+//             PLATFORM NOTES\r
+//\r
+//                     Win32                                           - On Win32, the WIN32 symbol must be #defined. Most mainstream\r
+//                                                                               compilers do this by default, but you may need to define it\r
+//                                                                               yourself if your build environment is less standard. This causes\r
+//                                                                               the Win32 thread support to be compiled in and used automatically.\r
+//\r
+//                     Unix/Linux/BSD, etc.            - If you're using gcc, it is assumed that you have Posix threads\r
+//                                                                               available, so they are used automatically. You can override this\r
+//                                                                               (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using\r
+//                                                                               something other than gcc but still want to use Posix threads, you\r
+//                                                                               need to #define SIGSLOT_USE_POSIX_THREADS.\r
+//\r
+//                     ISO C++                                         - If none of the supported platforms are detected, or if\r
+//                                                                               SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,\r
+//                                                                               along with any code that might cause a pure ISO C++ environment to\r
+//                                                                               complain. Before you ask, gcc -ansi -pedantic won't compile this \r
+//                                                                               library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of\r
+//                                                                               errors that aren't really there. If you feel like investigating this,\r
+//                                                                               please contact the author.\r
+//\r
+//             \r
+//             THREADING MODES\r
+//\r
+//                     single_threaded                         - Your program is assumed to be single threaded from the point of view\r
+//                                                                               of signal/slot usage (i.e. all objects using signals and slots are\r
+//                                                                               created and destroyed from a single thread). Behaviour if objects are\r
+//                                                                               destroyed concurrently is undefined (i.e. you'll get the occasional\r
+//                                                                               segmentation fault/memory exception).\r
+//\r
+//                     multi_threaded_global           - Your program is assumed to be multi threaded. Objects using signals and\r
+//                                                                               slots can be safely created and destroyed from any thread, even when\r
+//                                                                               connections exist. In multi_threaded_global mode, this is achieved by a\r
+//                                                                               single global mutex (actually a critical section on Windows because they\r
+//                                                                               are faster). This option uses less OS resources, but results in more\r
+//                                                                               opportunities for contention, possibly resulting in more context switches\r
+//                                                                               than are strictly necessary.\r
+//\r
+//                     multi_threaded_local            - Behaviour in this mode is essentially the same as multi_threaded_global,\r
+//                                                                               except that each signal, and each object that inherits has_slots, all \r
+//                                                                               have their own mutex/critical section. In practice, this means that\r
+//                                                                               mutex collisions (and hence context switches) only happen if they are\r
+//                                                                               absolutely essential. However, on some platforms, creating a lot of \r
+//                                                                               mutexes can slow down the whole OS, so use this option with care.\r
+//\r
+//             USING THE LIBRARY\r
+//\r
+//                     See the full documentation at http://sigslot.sourceforge.net/\r
+//\r
+//\r
+\r
+#ifndef SIGSLOT_H__\r
+#define SIGSLOT_H__\r
+\r
+#include <set>\r
+#include <list>\r
+\r
+#define SIGSLOT_USE_POSIX_THREADS\r
+#define SIGSLOT_DEFAULT_MT_POLICY  multi_threaded_local\r
+\r
+#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))\r
+#      define _SIGSLOT_SINGLE_THREADED\r
+#elif defined(WIN32)\r
+#      define _SIGSLOT_HAS_WIN32_THREADS\r
+#      include <windows.h>\r
+#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)\r
+#      define _SIGSLOT_HAS_POSIX_THREADS\r
+#      include <pthread.h>\r
+#else\r
+#      define _SIGSLOT_SINGLE_THREADED\r
+#endif\r
+\r
+#ifndef SIGSLOT_DEFAULT_MT_POLICY\r
+#      ifdef _SIGSLOT_SINGLE_THREADED\r
+#              define SIGSLOT_DEFAULT_MT_POLICY single_threaded\r
+#      else\r
+#              define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local\r
+#      endif\r
+#endif\r
+\r
+\r
+namespace sigslot {\r
+\r
+       class single_threaded\r
+       {\r
+       public:\r
+               single_threaded()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual ~single_threaded()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual void lock()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual void unlock()\r
+               {\r
+                       ;\r
+               }\r
+       };\r
+\r
+#ifdef _SIGSLOT_HAS_WIN32_THREADS\r
+       // The multi threading policies only get compiled in if they are enabled.\r
+       class multi_threaded_global\r
+       {\r
+       public:\r
+               multi_threaded_global()\r
+               {\r
+                       static bool isinitialised = false;\r
+\r
+                       if(!isinitialised)\r
+                       {\r
+                               InitializeCriticalSection(get_critsec());\r
+                               isinitialised = true;\r
+                       }\r
+               }\r
+\r
+               multi_threaded_global(const multi_threaded_global&)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual ~multi_threaded_global()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual void lock()\r
+               {\r
+                       EnterCriticalSection(get_critsec());\r
+               }\r
+\r
+               virtual void unlock()\r
+               {\r
+                       LeaveCriticalSection(get_critsec());\r
+               }\r
+\r
+       private:\r
+               CRITICAL_SECTION* get_critsec()\r
+               {\r
+                       static CRITICAL_SECTION g_critsec;\r
+                       return &g_critsec;\r
+               }\r
+       };\r
+\r
+       class multi_threaded_local\r
+       {\r
+       public:\r
+               multi_threaded_local()\r
+               {\r
+                       InitializeCriticalSection(&m_critsec);\r
+               }\r
+\r
+               multi_threaded_local(const multi_threaded_local&)\r
+               {\r
+                       InitializeCriticalSection(&m_critsec);\r
+               }\r
+\r
+               virtual ~multi_threaded_local()\r
+               {\r
+                       DeleteCriticalSection(&m_critsec);\r
+               }\r
+\r
+               virtual void lock()\r
+               {\r
+                       EnterCriticalSection(&m_critsec);\r
+               }\r
+\r
+               virtual void unlock()\r
+               {\r
+                       LeaveCriticalSection(&m_critsec);\r
+               }\r
+\r
+       private:\r
+               CRITICAL_SECTION m_critsec;\r
+       };\r
+#endif // _SIGSLOT_HAS_WIN32_THREADS\r
+\r
+#ifdef _SIGSLOT_HAS_POSIX_THREADS\r
+       // The multi threading policies only get compiled in if they are enabled.\r
+       class multi_threaded_global\r
+       {\r
+       public:\r
+               multi_threaded_global()\r
+               {\r
+                       pthread_mutex_init(get_mutex(), NULL);\r
+               }\r
+\r
+               multi_threaded_global(const multi_threaded_global&)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual ~multi_threaded_global()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               virtual void lock()\r
+               {\r
+                       pthread_mutex_lock(get_mutex());\r
+               }\r
+\r
+               virtual void unlock()\r
+               {\r
+                       pthread_mutex_unlock(get_mutex());\r
+               }\r
+\r
+       private:\r
+               pthread_mutex_t* get_mutex()\r
+               {\r
+                       static pthread_mutex_t g_mutex;\r
+                       return &g_mutex;\r
+               }\r
+       };\r
+\r
+       class multi_threaded_local\r
+       {\r
+       public:\r
+               multi_threaded_local()\r
+               {\r
+                       pthread_mutex_init(&m_mutex, NULL);\r
+               }\r
+\r
+               multi_threaded_local(const multi_threaded_local&)\r
+               {\r
+                       pthread_mutex_init(&m_mutex, NULL);\r
+               }\r
+\r
+               virtual ~multi_threaded_local()\r
+               {\r
+                       pthread_mutex_destroy(&m_mutex);\r
+               }\r
+\r
+               virtual void lock()\r
+               {\r
+                       pthread_mutex_lock(&m_mutex);\r
+               }\r
+\r
+               virtual void unlock()\r
+               {\r
+                       pthread_mutex_unlock(&m_mutex);\r
+               }\r
+\r
+       private:\r
+               pthread_mutex_t m_mutex;\r
+       };\r
+#endif // _SIGSLOT_HAS_POSIX_THREADS\r
+\r
+       template<typename mt_policy>\r
+       class lock_block\r
+       {\r
+       public:\r
+               mt_policy *m_mutex;\r
+\r
+               lock_block(mt_policy *mtx)\r
+                       : m_mutex(mtx)\r
+               {\r
+                       m_mutex->lock();\r
+               }\r
+\r
+               ~lock_block()\r
+               {\r
+                       m_mutex->unlock();\r
+               }\r
+       };\r
+\r
+       template<typename mt_policy>\r
+       class has_slots;\r
+\r
+       template<typename mt_policy>\r
+       class _connection_base0\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit() = 0;\r
+               virtual _connection_base0* clone() = 0;\r
+               virtual _connection_base0* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<typename arg1_type, typename mt_policy>\r
+       class _connection_base1\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type) = 0;\r
+               virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class mt_policy>\r
+       class _connection_base2\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type) = 0;\r
+               virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>\r
+       class _connection_base3\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type) = 0;\r
+               virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>\r
+       class _connection_base4\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;\r
+               virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class mt_policy>\r
+       class _connection_base5\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type) = 0;\r
+               virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class mt_policy>\r
+       class _connection_base6\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\r
+                       arg6_type) = 0;\r
+               virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class mt_policy>\r
+       class _connection_base7\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\r
+                       arg6_type, arg7_type) = 0;\r
+               virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>\r
+       class _connection_base8\r
+       {\r
+       public:\r
+               virtual has_slots<mt_policy>* getdest() const = 0;\r
+               virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,\r
+                       arg6_type, arg7_type, arg8_type) = 0;\r
+               virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone() = 0;\r
+               virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;\r
+       };\r
+\r
+       template<typename mt_policy>\r
+       class _signal_base : public mt_policy\r
+       {\r
+       public:\r
+               virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;\r
+               virtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;\r
+       };\r
+\r
+       template<typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class has_slots : public mt_policy \r
+       {\r
+       private:\r
+               typedef typename std::set<_signal_base<mt_policy> *> sender_set;\r
+               typedef typename sender_set::const_iterator const_iterator;\r
+\r
+       public:\r
+               has_slots()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               has_slots(const has_slots& hs)\r
+                       : mt_policy(hs)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = hs.m_senders.begin();\r
+                       const_iterator itEnd = hs.m_senders.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->slot_duplicate(&hs, this);\r
+                               m_senders.insert(*it);\r
+                               ++it;\r
+                       }\r
+               } \r
+\r
+               void signal_connect(_signal_base<mt_policy>* sender)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       m_senders.insert(sender);\r
+               }\r
+\r
+               void signal_disconnect(_signal_base<mt_policy>* sender)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       m_senders.erase(sender);\r
+               }\r
+\r
+               virtual ~has_slots()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_senders.begin();\r
+                       const_iterator itEnd = m_senders.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->slot_disconnect(this);\r
+                               ++it;\r
+                       }\r
+\r
+                       m_senders.erase(m_senders.begin(), m_senders.end());\r
+               }\r
+\r
+       private:\r
+               sender_set m_senders;\r
+       };\r
+\r
+       template<typename mt_policy>\r
+       class _signal_base0 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base0<mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+               _signal_base0()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base0(const _signal_base0& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = s.m_connected_slots.begin();\r
+                       const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base0()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_connected_slots.begin();\r
+                       const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class mt_policy>\r
+       class _signal_base1 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base1<arg1_type, mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base1()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base1(const _signal_base1<arg1_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = s.m_connected_slots.begin();\r
+                       const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base1()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_connected_slots.begin();\r
+                       const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                           iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class mt_policy>\r
+       class _signal_base2 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>\r
+                       connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base2()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = s.m_connected_slots.begin();\r
+                       const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base2()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_connected_slots.begin();\r
+                       const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+       template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>\r
+       class _signal_base3 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>\r
+                       connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+               \r
+        _signal_base3()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base3(const _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = s.m_connected_slots.begin();\r
+                       const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base3()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_connected_slots.begin();\r
+                       const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>\r
+       class _signal_base4 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base4<arg1_type, arg2_type, arg3_type,\r
+                       arg4_type, mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base4()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = s.m_connected_slots.begin();\r
+                       const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base4()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       const_iterator it = m_connected_slots.begin();\r
+                       const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       iterator it = m_connected_slots.begin();\r
+                       iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+#if 0\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class mt_policy>\r
+       class _signal_base5 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base5<arg1_type, arg2_type, arg3_type,\r
+                       arg4_type, arg5_type, mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base5()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = s.m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base5()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               connections_list::iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class mt_policy>\r
+       class _signal_base6 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base6<arg1_type, arg2_type, arg3_type, \r
+                       arg4_type, arg5_type, arg6_type, mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base6()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base6(const _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = s.m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base6()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               connections_list::iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class mt_policy>\r
+       class _signal_base7 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base7<arg1_type, arg2_type, arg3_type, \r
+                       arg4_type, arg5_type, arg6_type, arg7_type, mt_policy> *>  connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base7()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base7(const _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = s.m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base7()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               connections_list::iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>\r
+       class _signal_base8 : public _signal_base<mt_policy>\r
+       {\r
+       public:\r
+               typedef typename std::list<_connection_base8<arg1_type, arg2_type, arg3_type, \r
+                       arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>\r
+                       connections_list;\r
+        typedef typename connections_list::const_iterator const_iterator;\r
+        typedef typename connections_list::iterator iterator;\r
+\r
+               _signal_base8()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               _signal_base8(const _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)\r
+                       : _signal_base<mt_policy>(s)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = s.m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = s.m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_connect(this);\r
+                               m_connected_slots.push_back((*it)->clone());\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == oldtarget)\r
+                               {\r
+                                       m_connected_slots.push_back((*it)->duplicate(newtarget));\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               ~_signal_base8()\r
+               {\r
+                       disconnect_all();\r
+               }\r
+\r
+               void disconnect_all()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               (*it)->getdest()->signal_disconnect(this);\r
+                               delete *it;\r
+\r
+                               ++it;\r
+                       }\r
+\r
+                       m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());\r
+               }\r
+\r
+               void disconnect(has_slots<mt_policy>* pclass)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               if((*it)->getdest() == pclass)\r
+                               {\r
+                                       delete *it;\r
+                                       m_connected_slots.erase(it);\r
+                                       pclass->signal_disconnect(this);\r
+                                       return;\r
+                               }\r
+\r
+                               ++it;\r
+                       }\r
+               }\r
+\r
+               void slot_disconnect(has_slots<mt_policy>* pslot)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::iterator it = m_connected_slots.begin();\r
+                       connections_list::iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               connections_list::iterator itNext = it;\r
+                               ++itNext;\r
+\r
+                               if((*it)->getdest() == pslot)\r
+                               {\r
+                                       m_connected_slots.erase(it);\r
+                                       //                      delete *it;\r
+                               }\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+       protected:\r
+               connections_list m_connected_slots;   \r
+       };\r
+\r
+#endif\r
+\r
+       template<typename dest_type, typename mt_policy>\r
+       class _connection0 : public _connection_base0<mt_policy>\r
+       {\r
+       public:\r
+               _connection0()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection0(dest_type* pobject, void (dest_type::*pmemfun)())\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base0<mt_policy>* clone()\r
+               {\r
+                       return new _connection0<dest_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit()\r
+               {\r
+                       (m_pobject->*m_pmemfun)();\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)();\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class mt_policy>\r
+       class _connection1 : public _connection_base1<arg1_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection1()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base1<arg1_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection1<dest_type, arg1_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class mt_policy>\r
+       class _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection2()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type, class mt_policy>\r
+       class _connection3 : public _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection3()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type,\r
+       class arg4_type, class mt_policy>\r
+       class _connection4 : public _connection_base4<arg1_type, arg2_type,\r
+               arg3_type, arg4_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection4()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, \r
+                       arg4_type a4)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3, a4);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type,\r
+                       arg4_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type,\r
+       class arg4_type, class arg5_type, class mt_policy>\r
+       class _connection5 : public _connection_base5<arg1_type, arg2_type,\r
+               arg3_type, arg4_type, arg5_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection5()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type,\r
+       class arg4_type, class arg5_type, class arg6_type, class mt_policy>\r
+       class _connection6 : public _connection_base6<arg1_type, arg2_type,\r
+               arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection6()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type,\r
+       class arg4_type, class arg5_type, class arg6_type, class arg7_type, class mt_policy>\r
+       class _connection7 : public _connection_base7<arg1_type, arg2_type,\r
+               arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection7()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, arg7_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, arg7_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, arg7_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type);\r
+       };\r
+\r
+       template<class dest_type, class arg1_type, class arg2_type, class arg3_type,\r
+       class arg4_type, class arg5_type, class arg6_type, class arg7_type, \r
+       class arg8_type, class mt_policy>\r
+       class _connection8 : public _connection_base8<arg1_type, arg2_type,\r
+               arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>\r
+       {\r
+       public:\r
+               _connection8()\r
+               {\r
+                       m_pobject = NULL;\r
+                       m_pmemfun = NULL;\r
+               }\r
+\r
+               _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, \r
+                       arg7_type, arg8_type))\r
+               {\r
+                       m_pobject = pobject;\r
+                       m_pmemfun = pmemfun;\r
+               }\r
+\r
+               virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()\r
+               {\r
+                       return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(*this);\r
+               }\r
+\r
+               virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type, \r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)\r
+               {\r
+                       return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, \r
+                               arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);\r
+               }\r
+\r
+               virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\r
+               {\r
+                       (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8);\r
+               }\r
+\r
+               virtual has_slots<mt_policy>* getdest() const\r
+               {\r
+                       return m_pobject;\r
+               }\r
+\r
+       private:\r
+               dest_type* m_pobject;\r
+               void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type);\r
+       };\r
+\r
+       template<typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal0 : public _signal_base0<mt_policy>\r
+       {\r
+       public:\r
+               signal0()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal0(const signal0<mt_policy>& s)\r
+                       : _signal_base0<mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<typename desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)())\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection0<desttype, mt_policy>* conn = \r
+                               new _connection0<desttype, mt_policy>(pclass, pmemfun);\r
+                       _signal_base0<mt_policy>::m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+            typename _signal_base0<mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+            //::sigslot::_signal_base0<mt_policy>::const_iterator itNext, it = m_connected_slots.begin();\r
+                       typename _signal_base0<mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit();\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()()\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base0<mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base0<mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit();\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+       template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal1 : public _signal_base1<arg1_type, mt_policy>\r
+       {\r
+       public:\r
+               signal1()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal1(const signal1<arg1_type, mt_policy>& s)\r
+                       : _signal_base1<arg1_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection1<desttype, arg1_type, mt_policy>* conn = \r
+                               new _connection1<desttype, arg1_type, mt_policy>(pclass, pmemfun);\r
+                       this->m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base1<arg1_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base1<arg1_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base1<arg1_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base1<arg1_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+    \r
+       template<typename arg1_type, typename arg2_type, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>\r
+       {\r
+       public:\r
+               signal2()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)\r
+                       : _signal_base2<arg1_type, arg2_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<typename desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new\r
+                               _connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);\r
+                       this->m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base2<arg1_type,arg2_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base2<arg1_type,arg2_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base2<arg1_type,arg2_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base2<arg1_type,arg2_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal3 : public _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>\r
+       {\r
+       public:\r
+               signal3()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal3(const signal3<arg1_type, arg2_type, arg3_type, mt_policy>& s)\r
+                       : _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* conn = \r
+                               new _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>(pclass,\r
+                               pmemfun);\r
+                       this->m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base3<arg1_type,arg2_type,arg3_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base3<arg1_type,arg2_type,arg3_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base3<arg1_type,arg2_type,arg3_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base3<arg1_type,arg2_type,arg3_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal4 : public _signal_base4<arg1_type, arg2_type, arg3_type,\r
+               arg4_type, mt_policy>\r
+       {\r
+       public:\r
+               signal4()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal4(const signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)\r
+                       : _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*\r
+                               conn = new _connection4<desttype, arg1_type, arg2_type, arg3_type,\r
+                               arg4_type, mt_policy>(pclass, pmemfun);\r
+                       this->m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base4<arg1_type,arg2_type,arg3_type,arg4_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base4<arg1_type,arg2_type,arg3_type,arg4_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base4<arg1_type,arg2_type,arg3_type,arg4_type,mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base4<arg1_type,arg2_type,arg3_type,arg4_type,mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+#if 0\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal5 : public _signal_base5<arg1_type, arg2_type, arg3_type,\r
+               arg4_type, arg5_type, mt_policy>\r
+       {\r
+       public:\r
+               signal5()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal5(const signal5<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, mt_policy>& s)\r
+                       : _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\r
+                               arg5_type, mt_policy>* conn = new _connection5<desttype, arg1_type, arg2_type,\r
+                               arg3_type, arg4_type, arg5_type, mt_policy>(pclass, pmemfun);\r
+                       m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       typename _signal_base0<mt_policy>::const_iterator itNext, it = this->m_connected_slots.begin();\r
+                       typename _signal_base0<mt_policy>::const_iterator itEnd = this->m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal6 : public _signal_base6<arg1_type, arg2_type, arg3_type,\r
+               arg4_type, arg5_type, arg6_type, mt_policy>\r
+       {\r
+       public:\r
+               signal6()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal6(const signal6<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, mt_policy>& s)\r
+                       : _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\r
+                               arg5_type, arg6_type, mt_policy>* conn = \r
+                               new _connection6<desttype, arg1_type, arg2_type, arg3_type,\r
+                               arg4_type, arg5_type, arg6_type, mt_policy>(pclass, pmemfun);\r
+                       m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal7 : public _signal_base7<arg1_type, arg2_type, arg3_type,\r
+               arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>\r
+       {\r
+       public:\r
+               signal7()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal7(const signal7<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, mt_policy>& s)\r
+                       : _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, \r
+                       arg7_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\r
+                               arg5_type, arg6_type, arg7_type, mt_policy>* conn = \r
+                               new _connection7<desttype, arg1_type, arg2_type, arg3_type,\r
+                               arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>(pclass, pmemfun);\r
+                       m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6, a7);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6, a7);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+\r
+       template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,\r
+       class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>\r
+       class signal8 : public _signal_base8<arg1_type, arg2_type, arg3_type,\r
+               arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>\r
+       {\r
+       public:\r
+               signal8()\r
+               {\r
+                       ;\r
+               }\r
+\r
+               signal8(const signal8<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)\r
+                       : _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,\r
+                       arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(s)\r
+               {\r
+                       ;\r
+               }\r
+\r
+               template<class desttype>\r
+                       void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,\r
+                       arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, \r
+                       arg7_type, arg8_type))\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       _connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type,\r
+                               arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* conn = \r
+                               new _connection8<desttype, arg1_type, arg2_type, arg3_type,\r
+                               arg4_type, arg5_type, arg6_type, arg7_type, \r
+                               arg8_type, mt_policy>(pclass, pmemfun);\r
+                       m_connected_slots.push_back(conn);\r
+                       pclass->signal_connect(this);\r
+               }\r
+\r
+               void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+\r
+               void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,\r
+                       arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)\r
+               {\r
+                       lock_block<mt_policy> lock(this);\r
+                       connections_list::const_iterator itNext, it = m_connected_slots.begin();\r
+                       connections_list::const_iterator itEnd = m_connected_slots.end();\r
+\r
+                       while(it != itEnd)\r
+                       {\r
+                               itNext = it;\r
+                               ++itNext;\r
+\r
+                               (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);\r
+\r
+                               it = itNext;\r
+                       }\r
+               }\r
+       };\r
+#endif\r
+}; // namespace sigslot\r
+\r
+#endif // SIGSLOT_H__\r
+\r
diff --git a/gsm/CMakeLists.txt b/gsm/CMakeLists.txt
new file mode 100644 (file)
index 0000000..443238f
--- /dev/null
@@ -0,0 +1,99 @@
+PROJECT(gsm-rrc)
+
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt GSMMODULES)
+
+FOREACH(ITEM ${GSMMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(GSMRRCSRC ${GSMRRCSRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(GSMRRCHDR ${CSTAV1HDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h"
+    )
+
+ENDFOREACH(ITEM)
+
+SET(GSM_PARSER_INC -I ${asn1-data-models_SOURCE_DIR}/gsm/) 
+#SET(GSM_PARSER_OPT ${GSM_PARSER_INC} -fConstant-definitions.asn1)
+SET(GSM_PARSER_OPT ${GSM_PARSER_INC} -fpdu_cd.asn1)
+#SET(GSM_PARSER_OPT1 ${GSM_PARSER_OPT} -fInformationElements.asn1)
+SET(GSM_PARSER_OPT1 ${GSM_PARSER_OPT} -fpdu_ie.asn1)
+SET(GSM_PARSER_OPT2 ${GSM_PARSER_OPT1} -fpdu.asn1)
+SET(GSM_PARSER_OPT4 ${GSM_PARSER_OPT2} -frrc.asn1)
+#SET(GSM_PARSER_OPT3 ${GSM_PARSER_OPT2} -fInternode-definitions.asn1)
+SET(GSM_PARSER_OPT3 ${GSM_PARSER_OPT2} -fpdu_ind.asn1)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+IF(WITH_GSM)
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Constant-definitions.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/Constant_definitions.h
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p 
+    ARGS ${GSM_PARSER_OPT} -o Constant-definitions
+    DEPENDS  ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  ConstantDefinitions.h and .cpp"
+)
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/InformationElements.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/InformationElements.h
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p 
+    ARGS ${GSM_PARSER_OPT1} -o InformationElements
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  InformationElements.h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/PDU_definitions.h
+      ${CMAKE_CURRENT_BINARY_DIR}/PDU-definitions.cpp
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p 
+    ARGS ${GSM_PARSER_OPT2} -o PDU-definitions
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  PDU-definitions.h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Internode-definitions.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/Internode_definitions.h
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p 
+    ARGS ${GSM_PARSER_OPT3} -o Internode-definitions
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  Internode-definitions.h and .cpp"
+    )
+
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Class_definitions.h
+      ${CMAKE_CURRENT_BINARY_DIR}/Class-definitions.cpp
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p 
+    ARGS ${GSM_PARSER_OPT4} -o Class-definitions
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  Class-definitions.h and .cpp"
+    )
+
+ADD_LIBRARY(gsmrrc
+      ${GSMRRCSRC}
+    )
+
+#ADD_EXECUTABLE(test_cstav1
+#    main.cpp
+#    )
+
+#TARGET_LINK_LIBRARIES(test_cstav1 cstav1 asn1)
+ENDIF(WITH_GSM)
diff --git a/gsm/modules.txt b/gsm/modules.txt
new file mode 100644 (file)
index 0000000..b1d1673
--- /dev/null
@@ -0,0 +1,5 @@
+Constant-definitions
+InformationElements
+Class-definitions
+Internode-definitions
+PDU-definitions
diff --git a/gsmmap/CMakeLists.txt b/gsmmap/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2584a61
--- /dev/null
@@ -0,0 +1,50 @@
+PROJECT(gsmmap)
+
+
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+SET(GSMMAPDIR ${CMAKE_SOURCE_DIR}/../../../data-models/asn1/gsmmpa CACHE
+    STRING "GSMMAP ASN1 Source DIR")
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt GSMMAPMODULES)
+
+FOREACH(ITEM ${GSMMAPMODULES})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(GSMMAPSRC ${GSMRRCSRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(GSMMAPHDR ${CSTAV1HDR} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.h)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.h"
+    )
+
+ENDFOREACH(ITEM)
+
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/DummyMap.cpp
+    COMMAND cat
+    ${GSMMAPDIR}/GSMMAP.asn1
+    ARGS | ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build  InformationElements.h and .cpp"
+    )
+
+
+
+ADD_LIBRARY(gsmmmap
+      ${GSMMAPSRC}
+    )
+
+#ADD_EXECUTABLE(test_cstav1
+#    main.cpp
+#    )
+
+#TARGET_LINK_LIBRARIES(test_cstav1 cstav1 asn1)
diff --git a/gsmmap/module.txt b/gsmmap/module.txt
new file mode 100644 (file)
index 0000000..887d1b6
--- /dev/null
@@ -0,0 +1,4 @@
+DummyMAP
+MAP-CommonDataTypes
+MAP-ExtensionDataTypes
+MAP-CH-DataTypes
diff --git a/h248/CMakeLists.txt b/h248/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bbd6d95
--- /dev/null
@@ -0,0 +1,156 @@
+PROJECT(h248)
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${rules_SOURCE_DIR}/")
+
+OPTION(H248_ASN1_NESTED  "Generated H248 nested code or not" ON)
+OPTION(H248_ASN1_COMMENT "Generate H248 with comment in source" OFF)
+
+FIND_PACKAGE(PCAP REQUIRED)
+INCLUDE_DIRECTORIES(${PCAP_INCLUDE_DIRS})
+
+FIND_PACKAGE(Sqlite3)
+FIND_PACKAGE(Fcgi)
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt H248MODULES)
+
+FOREACH(ITEM ${H248MODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.lds GENERATED)
+ SET(H248SRC ${H248SRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(H248HDR ${H248HDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+ SET(H248LDS ${H248LDS} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.lds)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h"
+    )
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.lds"
+    )
+
+ENDFOREACH(ITEM)
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/MEDIA-GATEWAY-CONTROL.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/main.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND cat
+    ${asn1-data-models_SOURCE_DIR}/cstav1/Remote-Operations-Information-Objects.asn1
+    ARGS | ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build ROIO .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp
+    GENERATED)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${H248SRC}
+      ${H248HDR}
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS  -n ${H248_ASN1_NESTED} -c ${H248_ASN1_COMMENT} 
+          -I ${asn1-data-models_SOURCE_DIR}/h323/ -f h248v3.asn1 -o MEDIA-GATEWAY-CONTROL
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build H248 V3 library .h and .cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${H248LDS}
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS  -n ${H248_ASN1_NESTED} -c ${H248_ASN1_COMMENT} 
+          -I ${asn1-data-models_SOURCE_DIR}/h323/ -l lds -f h248v3.asn1 -o MEDIA-GATEWAY-CONTROL
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build H248 V3 library lds"
+    )
+
+
+
+ADD_LIBRARY(h248
+      ${H248SRC}
+      ${H248LDS}
+    )
+
+ADD_EXECUTABLE(test_h248
+    main.cpp
+    )
+
+TARGET_LINK_LIBRARIES(test_h248 h248 asn1)
+
+
+IF(APPLE)
+    #SET_TARGET_PROPERTIES(cstaspy PROPERTIES LINKER_FLAGS "-framework Cocoa")
+#Missing and don't know why
+#TARGET_LINK_LIBRARIES(cstaspy /usr/local/lib/libfltk_png.a)
+ENDIF(APPLE)
+
+IF(UNIX AND NOT APPLE)
+    #TARGET_LINK_LIBRARIES(cstaspy Ui X11 Xft Xinerama fltk_images)
+ENDIF()
+
+IF(WIN32)
+    #TARGET_LINK_LIBRARIES(cstaspy Ui ws2_32)
+ENDIF()
+
+#TARGET_LINK_LIBRARIES(cstaspy ${FLTK_LIBRARIES})
+#TARGET_LINK_LIBRARIES(cstaspy cstav1)
+#TARGET_LINK_LIBRARIES(cstaspy asn1)
+#TARGET_LINK_LIBRARIES(cstaspy ${PCAP_LIBRARIES})
+
+#
+# Install stuff
+#
+#INSTALL(TARGETS cstaspy DESTINATION bin)
+
+#
+# Ok start working with Packaging stuff
+#
+INCLUDE(InstallRequiredSystemLibraries)
+
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Graphical user interface to visualize
+csta phase 2 and sip messages from pcap files")
+SET(CPACK_PACKAGE_VENDOR "Aeb")
+#SET(CPACK_PACKAGE_DESCRIPTION_FILE "")
+#SET(CPACK_RESOURCE_FILE_LICENSE "")
+SET(CPACK_PACKAGE_VERSION_MAJOR "1")
+SET(CPACK_PACKAGE_VERSION_MINOR "0")
+SET(CPACK_PACKAGE_VERSION_PATCH "0")
+
+SET(CPACK_PACKAGE_FILE_NAME "CstaSpyInstaller")
+SET(CPACK_PACKAGE_NAME "CstaSpy")
+
+IF(WIN32)
+  SET(CPACK_GENERATOR "NSIS")
+ENDIF()
+
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
+  SET(CPACK_GENERATOR "RPM")
+ENDIF()
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy")
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy" "CSTA Spy")
+INCLUDE(CPack)
diff --git a/h248/main.cpp b/h248/main.cpp
new file mode 100644 (file)
index 0000000..ae30c33
--- /dev/null
@@ -0,0 +1,41 @@
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <typeinfo>
+#include <stdlib.h>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "MEDIA_GATEWAY_CONTROL.h"
+
+using namespace MEDIA_GATEWAY_CONTROL;
+
+void test_message() {
+    asn1::streams::ber ctx;
+    asn1::streams::ber ctx1;
+    ::asn1::types::debug_level = 8;  
+    IP4Address ip4;
+    Message m;
+    m.version = 2;
+    ip4.address     = std::string("0345");
+    ip4.portNumber  =  asn1::intrusive_ptr<INTEGER>(new INTEGER(asn1::prim::types::Integer(1045)));
+    //m.mId.ip4Address =  ip4;
+    //m.mId.kind_         = Mid::typeof_ip4Address;
+    //m.mId.set_tag(asn1::tag(asn1::types::CONTEXT_SPECIFIC,Mid::typeof_ip4Address));
+    m.mId.set_tag(asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+    //m.mId.set_ip4Address (  ip4 );
+    m.mId.get_ip4Address() =  ip4 ;
+    std::cout<<m<<std::endl;
+    std::cout<<"IP4=\n"<<m.mId.get_ip4Address()<<std::endl;
+    m.encode(ctx1);
+    
+    m.encode(ctx);
+}
+
+
+int main(int argc,char **argv)
+{
+    test_message();
+}
+
diff --git a/h248/modules.txt b/h248/modules.txt
new file mode 100644 (file)
index 0000000..7be8352
--- /dev/null
@@ -0,0 +1 @@
+MEDIA-GATEWAY-CONTROL
diff --git a/h323/CMakeLists.txt b/h323/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a63904a
--- /dev/null
@@ -0,0 +1,95 @@
+PROJECT(h323-lib)
+
+
+#SET(WITH_H323 TRUE CACHE TYPE BOOLEAN)
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+IF (WITH_H323)
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt H323MODULES)
+
+FOREACH(ITEM ${H323MODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+ SET(H323SRC ${H323SRC} ${ITEM}.cpp)
+ SET(H323HDR ${H323HDR} ${HITEM}.h)
+ ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h 
+    ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS -I ${asn1-data-models_SOURCE_DIR}/h323/
+    -f h2250v7.asn
+    -f H245v15.asn
+    -f h235-security-messages.asn1
+    -o  ${ITEM}
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+#      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMENT "Build ${ITEM}  .h and .cpp"
+ )
+
+ENDFOREACH(ITEM)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${H323SRC} ${H323HDR}"
+    )
+
+SET(ROSE_PARSER_INC -I ${asn1-data-models_SOURCE_DIR}/) 
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_INC} -fRemote-Operations-Generic-ROS-PDUs.asn1)
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_OPT} -fRemote-Operations-Information-Objects.asn1)
+SET(ROSE_PARSER_OPT ${ROSE_PARSER_OPT}
+    -fRemote-Operations-Useful-Definitions.asn1)
+#
+#Remote-Operations-Generic-ROS-PDUs {joint-iso-itu-t remote-operations(4)
+#
+IF (FALSE)
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Generic_ROS_PDUs.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Generic-ROS-PDUs
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build Remote-Operations-Generic-ROS-PDUs .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Useful_Definitions.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Useful-Definitions
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Generic-ROS-PDUs.cpp
+    COMMENT "Build Remote-Operations-Usful-Definitions .h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.h
+    GENERATED)
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS  ${ROSE_PARSER_OPT} -o Remote-Operations-Information-Objects
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Useful-Definitions.cpp
+    COMMENT "Build Remote-Operations-Informations-Objects .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h
+    GENERATED)
+ENDIF(FALSE)
+
+ADD_LIBRARY(h323
+      ${H323SRC}
+    )
+
+ENDIF(WITH_H323)
diff --git a/h323/modules.txt b/h323/modules.txt
new file mode 100644 (file)
index 0000000..8671fde
--- /dev/null
@@ -0,0 +1,3 @@
+H323-MESSAGES
+MULTIMEDIA-SYSTEM-CONTROL
+H235-SECURITY-MESSAGES
diff --git a/ledger/CMakeLists.txt b/ledger/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f9a2e83
--- /dev/null
@@ -0,0 +1,150 @@
+PROJECT(ledger-lib)
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${rules_SOURCE_DIR}/")
+
+FIND_PACKAGE(PCAP REQUIRED)
+INCLUDE_DIRECTORIES(${PCAP_INCLUDE_DIRS})
+
+FIND_PACKAGE(Sqlite3)
+FIND_PACKAGE(Fcgi)
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt LEDGERMODULES)
+SET(LEDGER_MODEL ${asn1-data-models_SOURCE_DIR}/ledger/ CACHE STRING "Ledger datamodel source directory")
+
+FOREACH(ITEM ${LEDGERMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(LEDGERSRC ${LEDGERSRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(LEDGERHDR ${LEDGERHDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+
+ SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+
+ SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h"
+    )
+  ADD_CUSTOM_COMMAND(
+    OUTPUT 
+    ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp
+    ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h
+    COMMAND ${asn1p_EXE}
+    ARGS  -e ber
+     -I ${asn1-data-models_SOURCE_DIR}/
+     -f cstav1/Remote-Operations-Information-Objects.asn1
+    -f /ledger/Ledger-definitions.asn1
+    -f /ledger/Ledger-bookkeeping.asn1
+    -f /ledger/Ledger-lifecycle.asn1
+    -f /ledger/Ledger-retrieve.asn1
+    -f /ledger/Ledger-error.asn1
+    -f /ledger/Ledger.asn1
+    -o ${ITEM} 
+    DEPENDS ${asn1p_EXE}
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+    COMMENT "Build Ledger .h and .cpp"
+    )
+
+  SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h 
+    ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+  )
+ENDFOREACH(ITEM)
+
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${asn1p_EXE}
+    ARGS  -e ber 
+     -I ${asn1-data-models_SOURCE_DIR}/cstav1/
+     -f Remote-Operations-Information-Objects.asn1
+     -o Remote-Operations-Information-Objects
+    DEPENDS ${asn1p_EXE}
+    COMMENT "Build ROIO .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp
+    GENERATED)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp"
+    )
+
+ADD_LIBRARY(ledger
+      ${LEDGERSRC}
+    )
+
+ADD_EXECUTABLE(test_ledger
+    main.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    )
+
+TARGET_LINK_LIBRARIES(test_ledger ledger asn1)
+
+
+IF(APPLE)
+    #SET_TARGET_PROPERTIES(cstaspy PROPERTIES LINKER_FLAGS "-framework Cocoa")
+#Missing and don't know why
+#TARGET_LINK_LIBRARIES(cstaspy /usr/local/lib/libfltk_png.a)
+ENDIF(APPLE)
+
+IF(UNIX AND NOT APPLE)
+    #TARGET_LINK_LIBRARIES(cstaspy Ui X11 Xft Xinerama fltk_images)
+ENDIF()
+
+IF(WIN32)
+    #TARGET_LINK_LIBRARIES(cstaspy Ui ws2_32)
+ENDIF()
+
+#TARGET_LINK_LIBRARIES(cstaspy ${FLTK_LIBRARIES})
+#TARGET_LINK_LIBRARIES(cstaspy cstav1)
+#TARGET_LINK_LIBRARIES(cstaspy asn1)
+#TARGET_LINK_LIBRARIES(cstaspy ${PCAP_LIBRARIES})
+
+#
+# Install stuff
+#
+#INSTALL(TARGETS cstaspy DESTINATION bin)
+
+#
+# Ok start working with Packaging stuff
+#
+INCLUDE(InstallRequiredSystemLibraries)
+
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Graphical user interface to visualize
+csta phase 2 and sip messages from pcap files")
+SET(CPACK_PACKAGE_VENDOR "Aeb")
+#SET(CPACK_PACKAGE_DESCRIPTION_FILE "")
+#SET(CPACK_RESOURCE_FILE_LICENSE "")
+SET(CPACK_PACKAGE_VERSION_MAJOR "1")
+SET(CPACK_PACKAGE_VERSION_MINOR "0")
+SET(CPACK_PACKAGE_VERSION_PATCH "0")
+
+SET(CPACK_PACKAGE_FILE_NAME "CstaSpyInstaller")
+SET(CPACK_PACKAGE_NAME "CstaSpy")
+
+IF(WIN32)
+  SET(CPACK_GENERATOR "NSIS")
+ENDIF()
+
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
+  SET(CPACK_GENERATOR "RPM")
+ENDIF()
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy")
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy" "CSTA Spy")
+INCLUDE(CPack)
diff --git a/ledger/main.cpp b/ledger/main.cpp
new file mode 100644 (file)
index 0000000..b247053
--- /dev/null
@@ -0,0 +1,60 @@
+
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <typeinfo>
+#include <stdlib.h>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+#include "Ledger_Apdu.h"
+#include "Ledger_retrieve.hpp"
+#include "Ledger_lifecycle.hpp"
+#include "Ledger_Book_Keeping.hpp"
+
+/**
+ */
+
+void test()
+{
+    Ledger_Book_Keeping::postTransaction p;
+    Ledger_Book_Keeping::PostTransactionArgument arg;
+    Ledger_definitions::Date d;
+    Ledger_definitions::Entry e1,e2;
+    Ledger_definitions::AccountId a;
+    std::string s("Test entry");
+    asn1::prim::types::String s1("Jones");
+    asn1::prim::types::UTCTime tx("1307120000Z");  
+    d.is_set = true;
+    d.time   = asn1::prim::types::UTCTime(std::string("1212050000Z"));
+    p.get_ArgumentType(arg);
+    
+    a = s1;
+    e1.acc_id = a;
+    e1.entry_date = d;
+    e1.description= s1;
+    e1.op = Ledger_definitions::DebitOrCredit::credit;
+    std::cout<<"Date:"<<d<<std::endl;
+    std::cout<<"Entry:"<<e1<<std::endl;
+    std::cout<<"postTransaction:";
+    p.printf(std::cout);
+}
+
+int main(int argc,char **argv)
+{
+
+  //CSTA_event_report_definitions::cSTAEventReport report; 
+  //asn1::context ctx;
+  
+  if (argc > 1) {
+    // Try to decode a stream ....
+      std::ifstream is;
+    is.open(argv[1],std::ios::binary);
+    int len = 0;
+    char bl[2];
+  }   
+  std::cout<<"Hello world"<<std::endl;
+  test();
+}
diff --git a/ledger/modules.txt b/ledger/modules.txt
new file mode 100644 (file)
index 0000000..8b4b64e
--- /dev/null
@@ -0,0 +1,6 @@
+Ledger-lifecycle
+Ledger-definitions
+Ledger-Book-Keeping
+Ledger-retrieve
+Ledger-error
+Ledger-Apdu
diff --git a/libgen/CMakeLists.txt b/libgen/CMakeLists.txt
new file mode 100644 (file)
index 0000000..aae32be
--- /dev/null
@@ -0,0 +1,69 @@
+PROJECT(libgen)
+
+SET(OPT_GEN_SRC "")
+
+CONFIGURE_FILE(asn1_gen_config.h.in asn1_gen_config.h)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+IF (WITH_ASN1_GEN_UML)
+  SET(OPT_GEN_SRC ${OPT_GEN_SRC} uml/asn1_gen_uml.cpp)
+ENDIF(WITH_ASN1_GEN_UML)
+
+IF (WITH_ASN1_GEN_JS)
+  SET(OPT_GEN_SRC ${OPT_GEN_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/js/asn1_gen_js.cpp)
+ENDIF(WITH_ASN1_GEN_JS)
+
+  SET(OPT_GEN_SRC ${OPT_GEN_SRC} lds/asn1_gen_lds.cpp)
+
+ADD_LIBRARY(libgen
+    asn1_gen_constraints.cpp
+    asn1_generator.cpp
+    asn1_gen_hpp.cpp
+    ${OPT_GEN_SRC}
+    asn1_gen_cpp.cpp
+    asn1_gen_codec_cpp.cpp
+    asn1_gen_auto_tag.cpp
+    asn1_gen_optimizer.cpp
+    cpp/cgcpp_helper.cpp
+    cpp/cgcpph_bitstring.cpp
+    cpp/cgcpph_enumerated.cpp
+    cpp/cgcpph_integer.cpp
+    cpp/cgcpph_octetstring.cpp
+    cpp/cgcpph_sequence.cpp
+    cpp/cgcpph_set.cpp
+    cpp/cgcpph_choice.cpp
+    cpp/cgcpph_typeref.cpp
+    cpp/cgcpph_object.cpp
+    cpp/cgcpph_import.cpp
+    cpp/cgcpph_boolean.cpp
+    cpp/cgcpph_oid.cpp
+    cpp/cgcpph_string.cpp
+    cpp/cgcpph_primitive.cpp
+    cpp/cgcpph_sequenceof.cpp
+    cpp/cgcpph_setof.cpp
+    cpp/cgcpph_real.cpp
+    cpp/cgh_object.cpp
+    cpp/cgh_construct.cpp
+
+    cpp/cghpp_helper.cpp
+    cpp/cgh_hconstruct.cpp
+    cpp/cghpph_bitstring.cpp
+    cpp/cghpph_classdef.cpp
+    cpp/cghpph_enumerated.cpp
+    cpp/cghpph_integer.cpp
+    cpp/cghpph_octetstring.cpp
+    cpp/cghpph_sequence.cpp
+    cpp/cghpph_choice.cpp
+    cpp/cghpph_set.cpp
+    cpp/cghpph_typeref.cpp
+    cpp/cghpph_object.cpp
+    cpp/cghpph_import.cpp
+    cpp/cghpph_oid.cpp
+    cpp/cghpph_boolean.cpp
+    cpp/cghpph_string.cpp
+    cpp/cghpph_primitive.cpp
+    cpp/cghpph_real.cpp
+    cpp/cghpph_sequenceof.cpp
+    cpp/cghpph_setof.cpp
+    )
diff --git a/libgen/asn1_gen_auto_tag.cpp b/libgen/asn1_gen_auto_tag.cpp
new file mode 100644 (file)
index 0000000..2640621
--- /dev/null
@@ -0,0 +1,393 @@
+
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include "asn1_generator.h"
+
+#include "asn1_gen_auto_tag.h"
+
+namespace asn1
+{
+/**
+ *  Default Cosntructor
+ */
+gen_auto_tag::gen_auto_tag(asn1::module *n) : asn1::generator(n) 
+{}
+
+gen_auto_tag::gen_auto_tag(asn1::module *n,asn1::module::modules_type &m) 
+  : asn1::generator(n,m)
+{
+}
+
+
+void 
+gen_auto_tag::gen_typeref(std::ostream &os,typeref  *type) 
+{
+  GEN_LOG_DEBUG("type %s\n",type->name().c_str());
+}
+
+void 
+gen_auto_tag::gen_seq(std::ostream &os,std::string &scope,asn1::sequence *type,bool priv)
+{
+  asn1::node *n= type->identifier();
+  asn1::node::iterator lit;
+  asn1::constructed  *params = n->parameters();
+  int i = 0;
+
+  os<<scope<<"struct /*SEQUENCE */ "<<n->cpp_name()<<" {\n";
+  // default constructor 
+  // I should probaly push optionnal attributes and OBEJECTS in a stack and add a initializer here.
+  for (asn1::node::iterator it = type->begin(); it != type->end() ; it++,i++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    asn1::node *attr_type = f->get_type();
+    //TODO: is this correct ?
+    if (f->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+    {
+        os<<scope<<"\t// Extensible marker strange this is the ..."<<std::endl;
+        i--;
+    } 
+    if (attr_type != NULL)
+    {
+        asn1::node::tag_type     tag;
+        tag.m_mode = asn1::node::tag_type::TM_IMPLICIT;
+        tag.m_class = asn1::node::tag_type::TC_CONTEXT_SPECIFIC;
+        tag.m_value = i;
+        switch (attr_type->type_id()())
+        {
+          case asn1::type::ASN1_SEQUENCE:
+              {
+                  std::string s = scope+"\t";
+                  attr_type->tag(tag);
+                  gen_seq(os,s,attr_type->as_sequence());
+              }
+              break;
+          case asn1::type::ASN1_SET:
+              {
+                  std::string s = scope+"\t";
+                  attr_type->tag(tag);
+                  gen_set(os,s,attr_type->as_set());
+              }
+              break;
+          case asn1::type::ASN1_CHOICE:
+              {
+                  std::string s = scope+"\t";
+                  tag.m_mode = asn1::node::tag_type::TM_EXPLICIT;
+                  attr_type->tag(tag);
+                  gen_choice(os,s,attr_type->as_choice());
+              }
+              break;
+          default:
+              attr_type->tag(tag);
+              ;
+        }
+    }
+  } // end for
+  os<<scope<<"};\n";
+}
+
+void 
+gen_auto_tag::gen_set(std::ostream &os,std::string &scope,asn1::set *type,bool priv)
+{
+  asn1::node *n = type->identifier();
+  asn1::node::iterator lit;
+  asn1::node  *params = n->parameters();
+  int i = 0;
+  /*
+   * Try to handler sequence of sequence 
+   */
+#if 0
+  if ( type == NULL)
+  {
+      os<<scope<<"SET TYPE is NULL"<<std::endl;
+      type = n->as_set();
+  }
+#endif
+
+  os<<scope<<"struct /*SET */ "<<(n)->cpp_name()<<" {\n";
+  // default constructor 
+  // I should probaly push optionnal attributes and OBEJECTS in a stack and add a initializer here.
+  for ( asn1::node::iterator it = type->begin()
+      ; it != type->end() ; it++,i++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    asn1::node *attr_type = f->get_type();
+    if ((*it)->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+    {
+        os<<scope<<"\t// Extensible marker strange this is the ..."<<std::endl;
+        i--;
+    } 
+    if (attr_type != NULL)
+    {
+        asn1::node::tag_type     tag;
+        tag.m_mode = asn1::node::tag_type::TM_IMPLICIT;
+        tag.m_class = asn1::node::tag_type::TC_CONTEXT_SPECIFIC;
+        tag.m_value = i;
+        switch (attr_type->type_id()())
+        {
+          case asn1::type::ASN1_SEQUENCE:
+              {
+                  std::string s = scope+"\t";
+                  attr_type->tag(tag);
+                  gen_seq(os,s,attr_type->as_sequence());
+              }
+              break;
+          case asn1::type::ASN1_SET:
+              {
+                  std::string s = scope+"\t";
+                  attr_type->tag(tag);
+                  gen_set(os,s,attr_type->as_set());
+              }
+              break;
+          case asn1::type::ASN1_CHOICE:
+              {
+                  std::string s = scope+"\t";
+                  tag.m_mode = asn1::node::tag_type::TM_EXPLICIT;
+                  attr_type->tag(tag);
+                  gen_choice(os,s,attr_type->as_choice());
+              }
+              break;
+          default:
+                  attr_type->tag(tag);
+              ;
+        }
+    }
+  } // end for
+  os<<scope<<"};\n";
+}
+
+void 
+gen_auto_tag::gen_choice(std::ostream &os,std::string &scope,asn1::choice *type,bool priv )
+{
+  asn1::node *n = type->identifier();
+  asn1::node::iterator it;
+  int i = 0;
+
+  it = type->begin();
+  asn1::node::iterator lit = type->begin();
+  os<<scope<<"struct /*CHOICE */ "<<(n)->cpp_name()<<" {\n";
+  // Parameter stuff here
+  // switch case 
+  for (; lit != type->end() ; ++lit,i++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+    asn1::node *attr_type = f->get_type();
+               if ((*lit)->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+               {
+                       os<<scope<<"\t// Extensible marker strange this is the ..."<<std::endl;
+                       i--;
+               } 
+               if  (attr_type != NULL)
+               {
+                       asn1::node::tag_type     tag;
+                       tag.m_mode = asn1::node::tag_type::TM_IMPLICIT;
+                       tag.m_class = asn1::node::tag_type::TC_CONTEXT_SPECIFIC;
+                       tag.m_value = i;
+                       os<<scope<<"\t"<<(*lit)->cpp_name()<<" ["<<i<<"] "<<attr_type->name();
+                       os<<std::endl;
+                       switch (attr_type->type_id()())
+                       {
+                               case asn1::type::ASN1_SEQUENCE:
+        {
+                                                               std::string s = scope+"\t";
+                                                               attr_type->tag(tag);
+                                                               gen_seq(os,s,attr_type->as_sequence());
+        }
+                                               break;
+                               case asn1::type::ASN1_SET:
+                                               {
+                                                               std::string s = scope+"\t";
+                                                               attr_type->tag(tag);
+                                                               gen_set(os,s,attr_type->as_set());
+                                               }
+                                               break;
+                               case asn1::type::ASN1_CHOICE:
+                                               {
+                                                               std::string s = scope+"\t";
+                                                               tag.m_mode = asn1::node::tag_type::TM_EXPLICIT;
+                                                               attr_type->tag(tag);
+                                                               gen_choice(os,s,attr_type->as_choice());
+                                               }
+                                               break;
+                               default:
+                                               attr_type->tag(tag);
+                                               ;
+                       } // End switch
+               }
+  } //end for
+}
+
+
+void gen_auto_tag::gen_typedef(std::ostream &os,asn1::typenode *type)
+{
+
+  if (type != NULL)
+    switch (type->type_id()())
+    {
+      case asn1::type::ASN1_REFERENCE:
+      {
+        std::cout<<"__FUNCTION__"<<" ERROR "<<type->cpp_name()<<std::endl;
+        exit(0);
+       asn1::node *ns = NULL;
+       if (type->tag().m_value != -1)
+       {
+          if (type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+          {
+          } 
+       } 
+
+      }
+      break;
+      case asn1::type::ASN1_INTEGER:
+        {
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          std::string scope("");
+          gen_seq(os,scope,type->as_sequence());
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE_OF:
+        {
+          asn1::node *ns = NULL;
+               asn1::typenode *seqof_type  = type->get_eltype();
+          if (type_in_imports(seqof_type,&ns) ) {
+          } else {
+            switch (seqof_type->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+              {
+                std::string scope("\t");
+                seqof_type->name(type->identifier_cpp_name()+"_type");
+                gen_seq(os,scope,seqof_type->as_sequence());
+              }
+              break;
+              case asn1::type::ASN1_CHOICE:
+              case asn1::type::ASN1_SET:
+              default:
+              ;
+            }
+          }
+        }
+        break;
+      case asn1::type::ASN1_SET:
+        {
+          std::string scope("\t");
+          gen_set(os,scope,type->as_set());
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SET_OF:
+        {
+        }
+        break;
+      case asn1::type::ASN1_CHOICE:
+        {
+          std::string scope("\t");
+          gen_choice(os,scope,type->as_choice());
+           return;
+        }
+        break;
+      default:
+      ;
+    };
+
+  
+}
+
+
+
+
+/**
+ *
+ */
+void gen_auto_tag::gen_module(std::ostream &os,asn1::module *n)
+{
+  asn1::import_list *imports = n->imports();
+  // Add include for external dependencies
+  asn1::node::tag_type t = n->tag();
+  
+  if (imports != NULL)
+  {
+    for (asn1::node::iterator it = imports->begin(); it!= imports->end(); it++)
+    {
+      /**/
+      // Loop over items and check if OPERATION is imported
+    }
+
+  }
+
+  
+  n->sort_childs();
+  asn1::node::iterator it = (n)->begin();
+  
+  if (t.m_mode == asn1::node::tag_type::TM_AUTOMATIC)
+  {
+      for (; it != (n)->end() ; it++)
+      {
+        asn1::assignment *a = (*it)->as_assignment();
+        std::cout<<"gen_auto_tag::"<<__FUNCTION__<<" process "<<(*it)->name();
+        std::cout.flush();
+        if (a->get_type() != NULL)
+        {
+         if ( (*it)->is_generated())
+         {
+           std::cout<<" ALREADY PROCESSED "<<std::endl; 
+           continue;
+         }
+         switch ( (*it)->meta_id()() )
+         {
+           case asn1::meta::VALUE:
+             {
+             }
+             break;
+           case asn1::meta::VALUESET:
+             {
+             }
+             break;
+           case asn1::meta::TYPE:
+             {
+               gen_typedef(os,a->get_type());
+             }
+             break;
+           case asn1::meta::TYPEREF:
+             {
+               gen_typeref(os,a->get_type()->as_typeref());
+             } 
+             break;
+           case asn1::meta::OBJECT:
+             {
+               // gen_object(os,*it);
+             } 
+             break;
+           case asn1::meta::OBJECTCLASS:
+             {
+               std::cout<<"gen_uto_tag::"<<__FUNCTION__<<"gen object_class OBJECT CLASS "<<(*it)->cpp_name()<<std::endl;
+               // gen_object_class(os,*it);
+             } 
+             break;         
+           default:
+             std::cerr<<"gen_auto_tag::"<<__FUNCTION__<<"undefinded  meta for node: "<<(*it)->name()<<std::endl;
+             ;
+         }
+         os<<std::endl;
+         //(*it)->set_generated(true);
+         // No coloration for this 
+         //(*it)->set_color(asn1::node::CL_RED);
+        } else 
+        {
+             std::cout<<" no type "<<(*it)->name();
+        }
+        std::cout<<std::endl; 
+      }
+  } else {
+      GEN_LOG_DEBUG("NO AUTOMATIC TAG for module %s\n",n->name().c_str());
+  }
+}
+
+
+}
diff --git a/libgen/asn1_gen_auto_tag.h b/libgen/asn1_gen_auto_tag.h
new file mode 100644 (file)
index 0000000..f1e29bd
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef ASN1_GENERATOR_AUTO_TAG_H__
+#define ASN1_GENERATOR_AUTO_TAG_H__
+#include <iostream>
+#include "asn1_generator.h"
+
+namespace  asn1
+{
+
+class gen_auto_tag : public asn1::generator
+{
+  public:
+    gen_auto_tag(module *n = NULL) ;
+    
+    gen_auto_tag(module *root_m,asn1::module::modules_type &m_)  ;
+    
+    virtual ~gen_auto_tag() {};
+
+    // Tells if a the structure should be in the form of templale
+    // or not
+
+    virtual void gen_const(std::ostream &os,node  *) {} ;
+    
+    virtual void gen_typedef(std::ostream &os,typenode  *) ;
+    
+    virtual void gen_typeref(std::ostream &os,typeref  *) ;
+    
+    virtual void gen_object(std::ostream &os,node  *) {};
+    
+    virtual void gen_module(std::ostream &os,module  *) ;
+    
+    void gen_seq(std::ostream &os,std::string &scope,asn1::sequence *n,bool priv = false);
+    
+    void gen_set(std::ostream &os,std::string &scope,asn1::set *n,bool priv = false);
+    
+    void gen_choice(std::ostream &os,std::string &scope,asn1::choice *n,bool priv = false);
+    
+    /* Usefull object functions */
+  protected:
+};
+
+}
+
+/*
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libgen/asn1_gen_codec_cpp.cpp b/libgen/asn1_gen_codec_cpp.cpp
new file mode 100644 (file)
index 0000000..73d42dd
--- /dev/null
@@ -0,0 +1,1517 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include <fstream>
+
+#include "asn1_gen_config.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+
+#include "asn1_generator.h"
+
+
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+// helper classes to split 
+#include "asn1_generator_helper.h" 
+#include "cpp/cgcpp_helper.h" 
+#include "cpp/cgh_construct.h"
+#include "cpp/cgcpph_sequence.h"
+#include "cpp/cgcpph_set.h"
+#include "cpp/cgcpph_choice.h"
+#include "cpp/cgcpph_primitive.h"
+#include "cpp/cgcpph_enumerated.h"
+#include "cpp/cgcpph_octetstring.h"
+#include "cpp/cgcpph_bitstring.h"
+#include "cpp/cgcpph_integer.h"
+#include "cpp/cgcpph_typeref.h"
+#include "cpp/cgh_object.h"
+#include "cpp/cgcpph_object.h"
+#include "cpp/cgcpph_import.h"
+#include "cpp/cgcpph_boolean.h"
+#include "cpp/cgcpph_oid.h"
+#include "cpp/cgcpph_string.h"
+#include "cpp/cgcpph_sequenceof.h"
+#include "cpp/cgcpph_setof.h"
+#include "adt/asn1_visitor.h"
+
+
+generate_codec_cpp::generate_codec_cpp(asn1::module *n,asn1::module::modules_type &m,gen_constraints &c)
+  : generate_cpp(n,m),m_gen_constraints(c)
+{
+
+}
+/**
+ * generate template instantiation in .hpp file
+ *
+ */ 
+struct gen_include_hpp
+{
+  gen_include_hpp(std::ostream &os,generate_codec_cpp &g)
+    : m_os(os), m_Gen(g)
+  {
+  }
+
+  void operator ()(asn1::module *n)
+  {
+    if (!std::string("Remote-Operations-Useful-Definitions")
+      .compare(n->name()))
+    {
+      m_os<<"#include \""<<n->cpp_name()<<".h\"\n";
+    }
+    m_os<<"#include \""<<n->cpp_name()<<".hpp\"\n";
+  }
+  protected:
+    std::ostream       &m_os;
+    generate_codec_cpp &m_Gen;
+};
+
+class do_gencpp_assignment : public assignment_visitor<do_gencpp_assignment>
+{
+  protected:
+    generate_codec_cpp &m_gen;
+    std::ostream       &m_os;
+    std::fstream       &m_sep_os; /* separe file for each assignment */
+    std::fstream       &m_log;
+  public:
+    do_gencpp_assignment( generate_codec_cpp &_h
+                      , std::ostream &os
+                      , std::fstream &sos
+     )
+      : m_os(os),m_gen(_h),m_log(_h.logger())
+        , m_sep_os(sos)
+    {};
+    // Main processing function per assignment
+    void operator ()(asn1::node *n)
+    {
+      asn1::typenode *type = n->as_assignment()->get_type();
+      std::string     path = n->cpp_name()+".cpp";
+      GEN_LOG_DEBUG( "Process  item=%s meta=%d\n"
+                 , n->name().c_str()
+                 , n->meta_id()());
+      if ( ! type)
+        return;
+      
+      if ( n->is_generated())
+      {
+        GEN_LOG_DEBUG("%s already generated\n",n->name().c_str());
+        return;
+      }
+      if (m_gen.with_split_cpp())
+      {
+        m_gen.open_assignment_stream(m_sep_os,n->as_assignment());
+        m_gen.gen_include_header(m_sep_os);
+      }
+      visit(n->as_assignment());
+      if (m_sep_os.is_open())
+        m_sep_os.close();
+
+      n->set_color(asn1::node::CL_RED);
+    }
+#define ASSIGNMENT(Ty,Code) \
+    void visit_##Ty(asn1::Ty##_assignment *a) Code
+
+    ASSIGNMENT(typeref,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is TYPEREF parameterized: %d\n"
+                  , a->name().c_str(),params);
+      if (m_sep_os.is_open())
+      {
+        m_gen.gen_typeref(m_sep_os,a->get_type()->as_typeref());
+      } else
+        m_gen.gen_typeref(m_os,a->get_type()->as_typeref());
+    })
+    ASSIGNMENT(type,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is TYPE parameterized: %d\n"
+                  , a->name().c_str(),params);
+      if (m_sep_os.is_open())
+      {
+        m_gen.gen_typedef(m_sep_os,a->get_type());
+      } else
+        m_gen.gen_typedef(m_os,a->get_type());
+    })
+    ASSIGNMENT(value,{
+      GEN_LOG_DEBUG("meta of %s is VALUE\n",a->name().c_str());
+      m_gen.gen_const(m_os,a->get_type());
+    })
+    ASSIGNMENT(valueset,{
+      GEN_LOG_DEBUG( "meta of %s is VALUESET do nothing ?\n"
+                , a->name().c_str());
+      m_gen.gen_const(m_os,a->get_type());
+    })
+    ASSIGNMENT(object,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is OBJECT parameterized: %d\n"
+                  , a->name().c_str(),params);
+      if (m_sep_os.is_open())
+      {
+        m_gen.gen_object(m_sep_os,a);
+      } else
+        m_gen.gen_object(m_os,a);
+    })
+    ASSIGNMENT(objectclass,{
+    })
+    ASSIGNMENT(objectset,{
+      GEN_LOG_DEBUG("meta of %s is OBJECT SET\n",a->name().c_str());
+      m_gen.gen_objectset(m_os,*a->get_objectset());
+    })
+    ASSIGNMENT(objectfield,{})
+
+};
+
+
+/**
+ * Create directory for cpp files.
+ *   current dir"/" module cpp_name
+ */
+bool 
+generate_codec_cpp::make_module_dir(asn1::module *_module)
+{
+  struct stat st;
+  
+  if (stat(m_module_path.c_str(),&st) == -1) {
+#ifdef WIN32
+    _mkdir(m_module_path.c_str());
+#else
+    mkdir(m_module_path.c_str(),0777);
+#endif
+  }
+  return true;
+}
+
+
+bool 
+generate_codec_cpp::open_assignment_stream(std::fstream &_stream,asn1::assignment *_a)
+{
+  std::string f (m_module_path);
+  f+= "/" + _a->cpp_name()+".cpp";
+  _stream.open(f.c_str(),std::fstream::out);
+  return _stream.is_open();
+}
+
+
+void 
+generate_codec_cpp::generate_constraints(std::ostream &os)
+{
+  gen_constraints::constraintSetIterator it = m_gen_constraints.begin();
+  os<<"static asn1::types::constraint_desc gConstraints[] = {\n";
+  os<<"\t  { asn1::types::un_constrained ,0 ,0 }\n";
+  for (; it != m_gen_constraints.end()
+       ; ++it)
+  {
+    asn1::constraint &_constraint(*(*it).m_constraint);
+
+    switch ( _constraint.type())
+    {
+      case asn1::constraint::CT_SIZE:
+      {
+        asn1::ctype_size *cts = _constraint.as_constraint_size();
+        assert((cts != NULL) && "cts is NULL not good");
+        if (asn1::celt_value *cv = cts->get_value())
+        {
+          assert(cv->get_valuetype() && "get_valuetype returned NULL");
+          os<<"\t, { asn1::types::partial_constrained ,"<<cv->get_valuetype()->value_long()<<" ,0 }\n";
+        } else if (asn1::constraint_range *cr = cts->get_range())
+        {
+          long _min,_max;
+          if (! cr->get_min_max(_min,_max))
+          {
+            std::cerr<<"generate_constraints size get_min_max error !!! "<<cr->name()<<std::endl;
+          }
+          os<<"\t, /*size*/{ asn1::types::fixed_constrained ,"<<_min<<" ,"<<_max<<" }\n";
+        }
+      }
+      break;
+      case asn1::constraint::EL_RANGE:
+      case asn1::constraint::EL_LLRANGE:
+      case asn1::constraint::EL_RLRANGE:
+      case asn1::constraint::EL_ULRANGE:
+      {
+        if (asn1::constraint_range *cr = _constraint.as_constraint_range())
+        {
+          long _min,_max;
+          if (! cr->get_min_max(_min,_max))
+          {
+            std::cerr<<"generate_constraints get_min_max error !!! "<<cr->name()<<std::endl;
+          }
+          os<<"\t, { asn1::types::fixed_constrained ,"<<_min<<" ,"<<_max<<" }\n";
+        }
+      }
+      break;
+      case asn1::constraint::EL_TYPE:
+      {
+        os<<"\t, { asn1::types::un_constrained ,1 ,0 }\n";
+      }
+      default: 
+        os<<"\t, { asn1::types::un_constrained ,2 ,"<<_constraint.type()<<"}\n";
+      ;
+    }
+  }
+  os<<"};\n";
+}
+
+/**
+ *
+ */
+void generate_codec_cpp::gen_include_header(std::ostream &os)
+{
+  asn1::module::modules_type  modules_with_objects;
+  asn1::import_list *imports = m_module->imports();
+  os<<"//\n// Automatic c++ generated code by asn1p copyright @ Andre EBERSOLD 2018 - 2022\n";
+  os<<"// using namespace "<<m_module->cpp_name()<<""<<std::endl;
+  os<<"// Do NOT MODIFY\n//"<<std::endl;
+  os<<"#include \"assert.h\""<<std::endl;
+  os<<"#include \"rtasn1/asn1_config.h\""<<std::endl;
+  os<<"#include \"rtasn1/asn1.h\""<<std::endl;
+  os<<"#include \"rtasn1/asn1_codec.h\""<<std::endl;
+  os<<"#include \"rtasn1/asn1_codec_ber.h\""<<std::endl;
+
+  if (with_jer())
+    os<<"#include \"rtasn1/asn1_codec_jer.h\""<<std::endl;
+  if (with_oer())
+    os<<"#include \"rtasn1/asn1_codec_oer.h\""<<std::endl;
+  if (with_per())
+    os<<"#include \"rtasn1/asn1_codec_per.h\""<<std::endl;
+  os<<"\n\n";
+
+  if (imports != NULL)
+  {
+    for (asn1::node::iterator it = imports->begin()
+        ; it!= imports->end(); it++)
+    {
+      asn1::import *import = dynamic_cast<asn1::import *>( *it);
+      if (import)
+      {
+        cgcpph_import imp_gen(*this,os,*import);
+        imp_gen.generate();
+        // Keep modules with objects
+        asn1::module *mi = m_resolver.module(import->identifier()->name());
+        if (mi && mi->has_objects())
+        {
+          modules_with_objects.push_back(mi);
+        } else
+        {
+          os<<"// Module "<<import->name()<<" no objects"<<std::endl;
+        }
+      }
+    }
+  }
+
+
+  os<<"#include \""<<m_module->cpp_name()<<".h\""<<std::endl;
+  os<<"\n\n";
+  // Include template header implementation here
+  std::for_each( modules_with_objects.begin()
+               , modules_with_objects.end()
+               , gen_include_hpp(os,*this)
+          );
+  if (m_module->has_objects())
+    os<<"#include \""<<m_module->cpp_name()<<".hpp\""<<std::endl;
+
+}
+/**
+ *
+ */
+void generate_codec_cpp::gen_module(std::ostream &os,asn1::module *n)
+{
+  asn1::module::modules_type  modules_with_objects;
+  asn1::import_list *imports = n->imports();
+#ifdef WIN32
+  char              *cd      = _getcwd(NULL,0);
+#else
+  char              *cd      = getcwd(NULL,0);
+#endif
+  std::string        cdir(cd);
+  m_module_path = cdir+"/"+m_module->cpp_name();
+  delete cd;
+
+  GEN_LOG_DEBUG("MODULE %s path=%s\n"
+               , n->name().c_str()
+               , m_module_path.c_str()
+               );
+  std::cout<<"gen_codec_cpp module "<<n->name()<<std::endl;
+  if (with_split_cpp())
+  {
+    make_module_dir(n);
+  } else {
+  }
+  
+  if (with_codec())
+  {
+    m_Streams.open(m_module_path,with_jer(),with_per(),with_oer());
+    m_Streams.m_os_codec_hpp<<"namespace asn1 {\n";
+    gen_include_header(m_Streams.m_os_codec_cpp);
+    m_Streams.m_os_codec_cpp<<"#include \""<<m_module->cpp_name()<<"_codec.hpp\""<<std::endl;
+    m_Streams.m_os_codec_cpp<<"namespace asn1 {\n";
+  }
+  gen_include_header(os);
+  generate_constraints(os);
+  os<<"using namespace asn1;"<<std::endl;
+  os<<"namespace "<<n->cpp_name()<<" {\n"<<std::endl;
+
+  n->sort_childs();
+  // Go through assignments and generate 
+  std::fstream       sos;
+  do_gencpp_assignment dogen(*this,os,sos);
+
+  std::for_each( n->begin()
+             , n->end()
+             , dogen
+            );
+
+  os<<"}"<<std::endl;
+  os<<"/** "<<std::endl;
+  os<<" * vim: sw=2 ts=2:"<<std::endl;
+  os<<" */"<<std::endl;
+  if (with_codec())
+  {
+    m_Streams.m_os_codec_hpp<<"}\n";
+    m_Streams.m_os_codec_cpp<<"}\n";
+    m_Streams.close();
+  }
+}
+
+/**
+ *  gen_typeref
+ */
+void generate_codec_cpp::gen_typeref(std::ostream &os,asn1::typeref *type)
+{
+    std::string scope;
+
+    asn1::typeref *ref = dynamic_cast<asn1::typeref *>(type);
+    assert(type->identifier() != NULL);
+    os<<"// gen_typeref "<<type->name()<<std::endl;
+    cgcpph_typeref gen_ref(*this,os,*ref);
+
+    gen_ref.generate(scope);
+}
+/**
+ * gen_bitstring.
+ *   calls helper class to generate the appropriate code
+ */ 
+void
+generate_codec_cpp::gen_bitstring( std::ostream &os
+                                 , const std::string &scope
+                                 , asn1::bit_string  &bits
+                                 , bool priv)
+{
+  cgcpph_bit_string set_gen(*this,os,bits);
+  set_gen.generate(scope); 
+}
+
+/**
+ *
+ */
+void
+generate_codec_cpp::gen_primitive(std::ostream &os,asn1::typenode &type)
+{
+  if (with_source_comment())
+    os<<"// gen_primitive "<<type.name()<<std::endl;
+  switch (type.type_id()())
+  {
+    case asn1::type::ASN1_OCTET_STRING:
+    {
+      asn1::octet_string &o = dynamic_cast<asn1::octet_string &>(type);
+      cgcpph_octet_string o_gen(*this,os,o);
+      o_gen.generate(); 
+    }
+    break;
+    case asn1::type::ASN1_NULL:
+    {
+      asn1::primitive &i = dynamic_cast<asn1::primitive &>(type);
+      cgcpph_primitive p_gen(*this,os,i);
+      p_gen.generate(); 
+    }
+    break;
+    case asn1::type::ASN1_STRING:
+    case asn1::type::ASN1_STRING_UniversalString:
+    break;
+    case asn1::type::ASN1_STRING_UTF8String  :
+    case asn1::type::ASN1_STRING_GeneralString:
+    case asn1::type::ASN1_STRING_T61String:
+    case asn1::type::ASN1_STRING_VideotexString:
+    case asn1::type::ASN1_STRING_ObjectDescriptor:
+    break;
+    case asn1::type::ASN1_STRING_GraphicString:
+    case asn1::type::ASN1_STRING_BMPString:
+    case asn1::type::ASN1_STRING_IA5String:
+    case asn1::type::ASN1_STRING_VisibleString:
+    case asn1::type::ASN1_STRING_ISO646String:    /* aka VisibleString */
+    case asn1::type::ASN1_STRING_PrintableString:
+    case asn1::type::ASN1_STRING_NumericString:
+    case asn1::type::ASN1_STRING_TeletexString:
+    {
+      asn1::primitive &i = dynamic_cast<asn1::primitive &>(type);
+      cgcpph_string i_gen(*this,os,i);
+      i_gen.generate(); 
+    }
+    break;
+    //case asn1::type::ASN1_UNIVERSAL: { } break;
+    case asn1::type::ASN1_INTEGER:
+    {
+      asn1::integer &i = dynamic_cast<asn1::integer &>(type);
+      cgcpph_integer i_gen(*this,os,i);
+      i_gen.generate();
+    }
+    break;
+    case asn1::type::ASN1_BIT_STRING:
+    {
+      asn1::bit_string &bs = dynamic_cast<asn1::bit_string &>(type);
+      gen_bitstring(os,"",bs,false);
+    }
+    break;
+    case asn1::type::ASN1_BOOLEAN:
+    {
+      asn1::boolean &i = dynamic_cast<asn1::boolean &>(type);
+      cgcpph_boolean i_gen(*this,os,i);
+      i_gen.generate(); 
+    }
+    break;
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    {
+      asn1::object_identifier &i = dynamic_cast<asn1::object_identifier &>(type);
+      cgcpph_oid i_gen(*this,os,i);
+      i_gen.generate(); 
+    }
+    break;
+    default:
+      GEN_LOG_ERROR("type  %s default case BAD path=%s\n"
+               , type.name().c_str()
+               , m_module_path.c_str()
+      );
+      ;
+  };
+}
+
+/**
+ * gen_typedef 
+ *
+ */
+void generate_codec_cpp::gen_typedef(std::ostream &os,asn1::typenode *type)
+{
+
+  if (type->identifier() != NULL)
+  {
+    GEN_LOG_DEBUG( "identifier_name=%s type_id=%d\n"
+                 , type->identifier_name().c_str()
+                 , type->type_id()());
+  } else {
+    GEN_LOG_WARN( "ANONYMOUS name=%s type_id=%d\n"
+                , type->name().c_str()
+                , type->type_id()());
+  }
+  switch (type->type_id()())
+  {
+    case asn1::type::INVALID:
+      {
+        std::cerr<<"ERROR UNDEFINED TYPE "<<type->name();
+        std::cerr<<" ident:"<<type->identifier_name()<<std::endl;
+        assert(0);
+      }
+      break;
+    case asn1::type::ASN1_REFERENCE:
+      {
+        //assert(0 && "Should not be possible but is");
+        gen_typeref(os,type->as_typeref());
+      }
+      break;
+    case asn1::type::ASN1_NULL:
+    case asn1::type::ASN1_BIT_STRING:
+    case asn1::type::ASN1_OCTET_STRING:
+    case asn1::type::ASN1_STRING:
+    case asn1::type::ASN1_STRING_VisibleString:
+    case asn1::type::ASN1_STRING_ISO646String:    /* aka VisibleString */
+    case asn1::type::ASN1_STRING_UniversalString:
+    case asn1::type::ASN1_STRING_BMPString:
+    case asn1::type::ASN1_STRING_UTF8String  :
+    case asn1::type::ASN1_STRING_GeneralString:
+    case asn1::type::ASN1_STRING_GraphicString:
+    case asn1::type::ASN1_STRING_T61String:
+    case asn1::type::ASN1_STRING_VideotexString:
+    case asn1::type::ASN1_STRING_ObjectDescriptor:
+    case asn1::type::ASN1_STRING_IA5String:
+    case asn1::type::ASN1_STRING_PrintableString:
+    case asn1::type::ASN1_STRING_NumericString:
+    case asn1::type::ASN1_STRING_TeletexString:
+    //case asn1::type::ASN1_UNIVERSAL:
+    case asn1::type::ASN1_INTEGER:
+    case asn1::type::ASN1_BOOLEAN:
+    case asn1::type::ASN1_REAL:
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    case asn1::type::ASN1_RELATIVE_OID:
+      {
+        gen_primitive(os,*type);
+      }
+      break;
+    case asn1::type::ASN1_SEQUENCE:
+      {
+         asn1::node *params = type->parameters();
+         GEN_LOG_DEBUG("identifier_name=%s type_id=%d params=%d \n"
+                         ,type->identifier_name().c_str()
+                         ,type->type_id()()
+                         ,(params == NULL)?0:1
+                         );
+         
+         std::string scope("");
+         if (params == NULL) {
+             gen_seq(os,scope,type,false);
+         } else {
+           GEN_LOG_WARN("%s has parameters don't generate implementation \n"
+                       ,type->identifier_name().c_str());
+         }
+
+      }
+      break;
+    case asn1::type::ASN1_SEQUENCE_OF:
+      {
+        asn1::typenode *seqof_type = type->get_eltype();
+        std::cout.flush();
+        if ( seqof_type->type_id()() == asn1::type::ASN1_SEQUENCE
+             || seqof_type->type_id()() == asn1::type::ASN1_CHOICE
+                )
+        {
+          // Generate codec for (private class)
+          // which does not exists in this case
+          if (with_source_comment())  
+            os<<"//private /*SEQUENCE_OF "<<seqof_type->cpp_name()<<" */"<<std::endl;
+          os.flush();
+          // Not sure if this is nice
+          gen_typedef(os,seqof_type->as_typenode());
+        }
+        std::string scope("");
+        cgcpph_sequenceof gseqof(*this,os,*dynamic_cast<asn1::sequence_of *>(type));
+        gseqof.generate();
+      }
+      break;
+    case asn1::type::ASN1_SET:
+      {
+        asn1::set *settype = type->as_set();
+        std::string scope("");
+        gen_set(os,scope,settype);
+      }
+      break;
+    case asn1::type::ASN1_SET_OF:
+      {
+        asn1::typenode *setof_type = type->get_eltype();
+        if (with_source_comment())  
+          os<<"//typedef /*SET_OF*/ "<<type->identifier_cpp_name()<<std::endl;
+        GEN_LOG_DEBUG("SET OF identifier_name=%s type_id=%d is_priv=%d \n"
+                         ,type->identifier_name().c_str()
+                         ,type->type_id()()
+                         ,type->is_private()
+                         );
+        if ( setof_type->type_id()() == asn1::type::ASN1_SEQUENCE
+             || setof_type->type_id()() == asn1::type::ASN1_CHOICE
+            )
+        {
+          GEN_LOG_DEBUG("SET OF type id_name=%s type_id=%d is_priv=%d \n"
+                         ,setof_type->identifier_name().c_str()
+                         ,setof_type->type_id()()
+                         ,setof_type->is_private()
+          );
+          // Generate codec for (private class)
+          // which does not exists in this case
+          if (with_source_comment())  
+          os<<"//private /*SET_OF "<<setof_type->cpp_name()<<" is private: "<<setof_type->is_private()<<"*/"<<std::endl;
+          os.flush();
+          // Not sure if this is nice
+          gen_typedef(os,setof_type);
+        }
+
+        cgcpph_setof gensetof(*this,os,*dynamic_cast<asn1::set_of *>(type));
+        gensetof.generate();
+    }
+    break;
+  case asn1::type::ASN1_CHOICE:
+    {
+       std::string scope("");
+       gen_choice(os,scope,type);
+    }
+    break;
+  case asn1::type::ASN1_ENUMERATED:
+    {
+        std::string scope("");
+        gen_enumerated(os,scope,type);
+    }
+    break;
+  case asn1::type::ASN1_ANY:
+  break;
+  default:
+      GEN_LOG_ERROR("UNHANDLED type id_name=%s type_id=%d is_priv=%d \n"
+                       ,type->identifier_name().c_str()
+                         ,type->type_id()()
+                         ,type->is_private()
+          );
+      //exit(0);
+  };
+  os<<"\n";
+  
+}
+
+
+/**
+ *
+ */ 
+void
+generate_codec_cpp::
+gen_attribute_constrained_nencode( std::ostream &os
+                                 , const std::string &scope
+                                 , const std::string &indent
+                                 , asn1::field *attribute)
+{
+  asn1::typenode *attribute_type = (attribute)->get_type();
+  asn1::constraint *c = *(attribute_type->constraint_begin());
+  if (c->type() == asn1::constraint::CA_CRC) {
+      asn1::constraint::const_iterator it = c->begin();
+      asn1::constraint *val = *it; ++it;
+      asn1::constraint *at  = *it;
+      if (with_source_comment())  
+      {
+        os<<indent<<"//"<<val->value()->cpp_name();
+        os<<" @ "<<at->value()->cpp_name()<<" Type="<<attribute_type->cpp_name()<<"\n";
+      }
+
+      if (attribute_type->as_typeref() && attribute_type->as_typeref()->is_complex())
+      {
+          asn1::node *imp = NULL;
+          asn1::reference *r = attribute_type->as_typeref()->get_reference();
+          std::string lr = r->back().m_identifier;
+          lr[0]='_';
+          std::string lname(r->front().m_identifier);
+          std::string cls; 
+          cls.resize(lname.size());
+          std::transform(lname.begin(),lname.end(),cls.begin(),asn1::op_substitute);
+          // Check if pointer exists
+          os<<indent<<"if ( ! "<<attribute->cpp_name()<<".is_nul() )\n";
+          os<<indent<<"{\n";
+          if (type_in_imports(r->front().m_identifier,&imp))
+          {
+            os<<indent<<attribute->cpp_name()<<"->encode"<<lr<<"(ctx); /* constrained CA CRC*/"<<std::endl;
+          } else
+          {
+            os<<""<<attribute->cpp_name()<<"->";
+            os<<"encode"<<lr<<"(ctx); /* constrained CA CRC 1*/"<<std::endl;
+          }
+          os<<indent<<"} else\n"<<indent<<"{\n";
+          os<<indent<<"\tASN1_BER_LOG_ERROR(\"ENCODING ERROR "<<attribute->cpp_name()<<" is NULL\");\n";
+          os<<indent<<"}\n";
+      } else {
+          os<<indent<<"\t"<<val->value()->cpp_name()<<"[i]->";
+          os<<"encode(ctx); /* constrained CA CRC*/"<<std::endl;
+      }
+  } else if (c->type() == asn1::constraint::CT_SIZE)
+  {
+    os<<indent<<"ASN1_BER_LOG_INFO(\"encoding of ";
+    os<<attribute->cpp_name() <<" size constrained to be checked\");\n";
+    os<<""<<indent<<""<<""<<(attribute)->cpp_name();
+    os<<".encode(ctx); /* constrained*/"<<std::endl;
+  } else if (c->type() == asn1::constraint::EL_RANGE)
+  {
+    os<<indent<<"ASN1_BER_LOG_INFO(\"encoding of ";
+    os<<attribute->cpp_name() <<" range constrained to be checked\");\n";
+    os<<""<<indent<<""<<""<<(attribute)->cpp_name();
+    os<<".encode(ctx); /* constrained*/"<<std::endl;
+  }else
+  {
+    os<<indent<<"ASN1_BER_LOG_INFO(\"encode of ";
+    os<<attribute->cpp_name() <<" other constrained to be checked\");\n";
+    os<<""<<indent<<""<<""<<(attribute)->cpp_name();
+    os<<".encode(ctx); /* constrained*/"<<std::endl;
+  }
+}
+
+/**
+ *
+ */ 
+void
+generate_codec_cpp::
+gen_attribute_constrained_ndecode(std::ostream &os
+                                 , const std::string &scope
+                                 , const std::string &indent
+                                 , asn1::field *attribute)
+{
+  asn1::typenode *attribute_type = attribute->get_type();
+  asn1::constraint *c = *(attribute_type->constraint_begin());
+  if (c->type() == asn1::constraint::CA_CRC)
+  {
+      std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" WARN "<<attribute->name()<<" has CRC"<<std::endl;
+      asn1::constraint::const_iterator it = c->begin();
+      asn1::celt_type  *val = (*it)->as_celt_type();
+      asn1::typeref    *vtr = val->get_type();
+      ++it;
+      asn1::constraint *at  = *it;
+      assert(val && "gen_attribute_constraint_ndecode should needs evolution");
+      std::string setname;
+      if ( vtr->is_imported(setname))
+      {
+        setname = asn1::cpp_name(setname);
+        setname.append("::");
+        setname.append(vtr->cpp_name());
+      } else
+        setname = vtr->cpp_name();
+      os<<indent<<"\t//"<<setname;
+      os<<" @ "<<at->value()->cpp_name()<<"\n";
+      os<<indent<<"\tint i = 0;\n";
+      os<<indent<<"\tfor ( i = 0 ; "<<setname<<"[i] != NULL;i++)\n";
+      os<<indent<<"\t{\n";
+      os<<indent<<"\t\tif ( ";
+      // Find attribute at->value() Then get the type to figure out
+      // which attribute in object to use.
+      {
+        asn1::constructed *ccontainer  = attribute->get_parent()
+                                                  ->as_constructed();
+        asn1::node::iterator itt =
+                    std::find_if( ccontainer->begin()
+                                , ccontainer->end()
+                                , asn1::find_node(at->value()->name()));
+        assert(itt != ccontainer->end());
+        asn1::field   *f      = dynamic_cast<asn1::field *>(*itt);
+        asn1::typeref *at_ref = dynamic_cast<asn1::typeref *>(f->get_type());
+        // Not always true
+        std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" at_ref "<<at_ref->name();
+        std::cerr<<" Simple: "<<at_ref->is_simple()<<std::endl;
+        asn1::objectclass_reference &ocref = at_ref->get_objectclass();
+        // This is wierd, I don't think the resolver is required here.
+        // I only need the last field
+        std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" at_ref "<<at_ref->name();
+        std::cerr<<std::endl;
+        std::string   fieldn  = ocref.field().substr(1);
+        os<<setname<<"[i]->"<<fieldn<<"Equals(";
+      }
+      os<<"  "<<at->value()->cpp_name()<<"))\n";
+      os<<indent<<"\t\t{\n";
+      if (attribute_type->as_typeref() && attribute_type->as_typeref()->is_complex())
+      {
+          asn1::reference *r = attribute_type->as_typeref()->get_reference();
+          std::string lr = r->back().m_identifier;
+          lr[0]='_';
+          os<<indent<<"\t\t\t"<<(attribute)->cpp_name()<<" = ";
+          os<<setname<<"[i]->"<<"clone();\n";
+          os<<indent<<"\t\t\t"<<(attribute)->cpp_name()<<"->decode"<<lr<<"(ctx); "<<std::endl;
+      } else
+      {
+          os<<indent<<"\t\t"<<val->value()->cpp_name()<<"[i]->"<<"codec(ctx,"<<(attribute)->cpp_name()<<",CODEC_DECODE); /* constrained CA CRC*/"<<std::endl;
+      }
+      os<<indent<<"\t\t\tbreak;\n";
+      os<<indent<<"\t\t}\n";
+      os<<indent<<"\t}\n"; // end for
+      os<<indent<<"\tif ("<<setname<<"[i] == NULL)\n";
+      os<<indent<<"\t{\n";
+      os<<indent<<"\t\tASN1_BER_LOG_DEBUG(\"DECODE CONSTRAINT type "<<attribute->cpp_name()<<" Not FOUND\");\n";
+      os<<indent<<"\t}\n";
+  } else
+  {
+    os<<indent<<"\t"<<(attribute)->cpp_name()<<".decode(ctx);";
+    os<<"/* constrained "<<c->type()<<" */"<<std::endl;
+  }
+}
+
+
+void
+generate_codec_cpp::gen_composite_attribute_printf( std::ostream &os
+                                                  , const std::string &scope
+                                                  , asn1::field &attribute
+                                                  , asn1::node *params)
+{
+    asn1::typenode *attr_type = attribute.get_type();
+    int strlen = 4;
+    if (attr_type != NULL)
+    {
+      switch (attr_type->type_id()() )
+      {
+        case asn1::type::ASN1_REFERENCE:
+          {
+            asn1::typeref *tref      = dynamic_cast<asn1::typeref *>(attr_type);
+            asn1::node    *real_type = m_resolver.resolve(*tref);
+            // New way to handle reference
+            // gen_composite_attribute_ref(os,scope,attr_type);
+            if (tref->is_complex() && !tref->is_external())
+            {
+              os<<"std::setw(indent+"<<attribute.cpp_name().size()+strlen;
+              os<<")<<std::setprecision(indent)<<\""<<attribute.cpp_name()<<" : \";\n";
+              switch( real_type->type_id()())
+              {
+                case asn1::type::ASN1_CLASSFIELD_TF:
+                  os<<"\tif ( ! s."<<attribute.cpp_name()<<".is_nul())\n";
+                  os<<"\t{\n";
+                  os<<"\t\ts."<<attribute.cpp_name()<<"->printf(os); /**/\n";
+                  os<<"\t}\n";
+                  os<<"\tos<<std::endl;\n";
+                  break;
+                case asn1::type::ASN1_CLASSFIELD_FTVF: 
+                  {
+                    os<<"\ts."<<attribute.cpp_name()<<".printf(os);\n";
+                    os<<"\tos<<std::endl;\n";
+                  }
+                  break;
+                case asn1::type::ASN1_REFERENCE: 
+                case asn1::type::ASN1_INTEGER: 
+                case asn1::type::ASN1_OBJECT_IDENTIFIER:
+                    os<<"\tos<<s."<<attribute.cpp_name()<<"<<std::endl;\n";
+                  break;
+                default:
+                  os<<"\tif ( ! s."<<attribute.cpp_name()<<".is_nul())\n";
+                  os<<"\t{\n";
+                  os<<"\t\ts."<<attribute.cpp_name()<<"->printf(os);\n";
+                  os<<"\t}\n";
+                  os<<"\tos<<std::endl;\n";
+                  break;
+              }
+                
+            } else 
+            {
+              os<<"std::setw(indent+"<<attribute.cpp_name().size()+strlen;
+              os<<")<<\""<<attribute.cpp_name();
+              os<<" : \"<<std::setprecision(indent)<<s."<<attribute.cpp_name();
+              os<<"<<std::endl;\n";
+            }
+          }
+        break;
+        default:
+            os<<"std::setw(indent+"<<attribute.cpp_name().size()+strlen;
+            os<<")<<\""<<attribute.cpp_name();
+            os<<" : \"<<std::setprecision(indent)<<s."<<attribute.cpp_name();
+            os<<"<<std::endl;\n";
+        ;
+      }
+    }
+}  
+
+
+/**
+ * TODO: Remove
+ */ 
+void 
+generate_codec_cpp::gen_composite_attribute_ref(std::ostream &os
+                      ,const std::string &scope
+                      ,asn1::field *attribute
+                      ,asn1::node  *params)
+{
+  generate_cpp::gen_composite_attribute_ref(os,scope,attribute,params);
+}
+
+
+
+void generate_codec_cpp::gen_seq(std::ostream &os
+                      , const std::string &scope
+                      , asn1::node *_type
+                      , bool priv
+                      )
+{
+  std::string structName;  
+  asn1::sequence *type = _type->as_sequence();
+  assert(type != NULL);  
+  asn1::node *ident = type->identifier();
+  asn1::node::iterator lit = (type)->begin();
+  GEN_LOG_DEBUG("gen_seq: \n");
+  assert(type->type_id()() == asn1::type::ASN1_SEQUENCE);
+  // try new helper
+  // New way to handle and isolate sequence code generation 
+  asn1::sequence *seq = dynamic_cast<asn1::sequence *>(type);
+  assert(seq != NULL);
+  assert(ident != NULL);
+  GEN_LOG_ERROR("gen_seq:  %s\n",ident->cpp_name().c_str());
+  assert(seq->is_private() == priv);
+  // compute strutName
+  struct_name(type,structName);
+
+  if (ident)
+  {
+    GEN_LOG_DEBUG("scope=%s ident= %s type=%s parameters=%d\n",scope.c_str(),
+            ident->cpp_name().c_str(),
+            type->cpp_name().c_str(),
+        (   ident->parameters() == NULL)?0:1
+    );
+  } 
+  os<<"//generate_codec_cpp::"<<__FUNCTION__<<" "<<scope<<structName<<" priv="<<priv<<std::endl;
+  gen_private(os,scope,seq);
+  cgcpph_sequence seq_gen(*this,os,*seq);
+  seq_gen.generate(scope); 
+}
+
+
+
+static 
+char  lop_substitute(char c)
+{
+    return (c == ':')?'_':c;
+}
+
+
+/**
+ *
+ *
+ */
+void generate_codec_cpp::gen_choice(std::ostream &os,const std::string &scope,asn1::node *type,bool priv)
+{
+  std::string structName;
+  asn1::choice *choice  = dynamic_cast<asn1::choice *>(type);
+  // Pre condition. 
+  //   - type should not have a type node
+  //   - type should not null
+  //   - type should be of type choice
+  //
+  assert( (type != NULL) && (type->type_id()() == asn1::type::ASN1_CHOICE));
+  assert( choice != NULL );
+
+  GEN_LOG_DEBUG("type %s scope=%s priv=%d\n",type->cpp_name().c_str(),scope.c_str(),priv);
+
+  os<<"//"<<__FUNCTION__<<" "<<scope<<type->cpp_name()<<" type_id="<<type->type_id()();
+  os<<" ident="<<type->identifier_cpp_name()<<std::endl;
+
+  struct_name(type,structName);
+
+  cgcpph_choice choice_gen(*this,os,*choice);
+
+  choice_gen.generate();
+}
+
+/**
+ *
+ *
+ */
+void generate_codec_cpp::gen_set( std::ostream &os
+                                , const std::string &scope
+                                , asn1::set *type)
+{
+  bool priv = false;
+  asn1::set *set = dynamic_cast<asn1::set *>(type);
+  assert(set != NULL);
+  // This is the right test that should be performed
+  assert(dynamic_cast<asn1::set *>(type)  != NULL);
+
+  cgcpph_set set_gen(*this,os,*set);
+  set_gen.generate(scope);
+}
+
+/**
+ * Dead code below.
+ */
+void generate_codec_cpp::gen_set_of(std::ostream &os,asn1::node *type)
+{
+  assert(0);
+}
+
+/**
+ * const object set is an elemnt_set_spec
+ * which are contraints
+ *
+ */
+void generate_codec_cpp::gen_objectset(std::ostream &os,asn1::objectset &objs)
+{
+    GEN_LOG_ERROR( "generate_codec_cpp:%s %s type=%s\n"
+                 , __FUNCTION__
+                 , objs.name().c_str()
+                 , objs.type_id().name());
+    asn1::typeref *tref = objs.get_classref();
+    std::string otype = tref->get_reference()->name();
+    asn1::node *ns;
+    os<<"\n// "<<__FUNCTION__<<" start "<<objs.name()<<" "<<std::endl;
+    if (objs.has_constraints())
+    {
+      asn1::constraint::const_iterator values = objs.constraint_begin();
+      for (; values != objs.constraint_end(); ++values)
+      {
+          switch( (*values)->type())
+          {
+            case asn1::constraint::EL_VALUE:
+              {
+                std::string type_name((*values)->value()->name());
+                asn1::node::iterator ref = std::find_if(m_module->begin(),
+                                         m_module->end(),
+                                         asn1::find_node(type_name));
+                if (ref != m_module->end())
+                {
+                  asn1::node *ntype = *ref; 
+                  std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" "<<ntype->name()<<std::endl;
+                  if (ntype->parameters())
+                  {
+                    std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" ";
+                    std::cerr<<ntype->name()<<" has parameters"<<std::endl;
+                    os<<"// "<<__FUNCTION__<<" "<<ntype->name()<<" has parameters NO GEN YET"<<std::endl;
+                    return;
+                  } else 
+                    gen_object(os,(*ref)->as_assignment());
+                }
+              }
+            break;
+            default:
+              ;
+          };
+       }
+    } else {
+      GEN_LOG_ERROR( "generate_codec_cpp:%s EMPTY v %s type=%s\n"
+                   , __FUNCTION__
+                   , objs.name().c_str()
+                   , objs.type_id().name());
+    }
+    if (objs.get_assignment()->parameters())
+    {
+      std::cerr<<"generate_codec_cpp::"<<__FUNCTION__<<" "<<objs.name();
+      std::cerr<<" has parameters 1"<<std::endl;
+      os<<"//generate_codec_cpp::"<<__FUNCTION__<<" "<<objs.name();
+      os<<" has parameters NO GEN YET 1"<<std::endl;
+      return;
+    } 
+    // begin of definition
+    if (type_in_imports(otype,&ns) )
+    {
+      os<<ns->cpp_name()<<"::I"<<tref->get_reference()->cpp_name()<<" *"<<objs.cpp_name()<<"[] = {";
+    } else {
+      os<<"I"<<tref->get_reference()->cpp_name()<<" *"<<objs.cpp_name()<<"[] = {";
+    }
+
+    // gen code
+    if ( objs.has_constraints()  && (*objs.constraint_begin())->type() == asn1::constraint::CA_UNI)
+    {
+      asn1::constraint *first = (*objs.constraint_begin());
+      asn1::constraint::const_iterator values = first->begin();
+      for (; values != first->end(); ++values)
+      {
+        if (values != first->begin())
+            os<<",";
+        switch( (*values)->type())
+        {
+          case asn1::constraint::EL_VALUE:
+            {
+              asn1::node *ns;
+              if (type_in_imports((*values)->value()->name(),&ns)) {
+                os<<" new "<<ns->cpp_name()<<"::"<<(*values)->value()->cpp_name()<<"()\n";
+              } else
+                os<<" new "<<(*values)->value()->cpp_name()<<"()\n";
+            }
+            break;
+          default:
+            ;
+        };
+        os<<"\t";
+      }
+      os<<", NULL\n";
+    }
+    os<<"};";
+}
+
+/**
+ * const encoding and decoding
+ *
+ */
+void generate_codec_cpp::gen_const( std::ostream &os
+                                  , asn1::node *type)
+{
+  if (with_source_comment())
+    os<<"// generate_codec_cpp::"<<__FUNCTION__<<"\n";
+
+  switch(type->type_id()())
+  {
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    {
+      if (with_source_comment())
+        os<<"// const OID "<<" "<<type->identifier_cpp_name();
+    }
+    break;
+    case asn1::type::ASN1_VALUESET:
+    {
+      GEN_LOG_ERROR("generate_codec_cpp: %s type=%s\n",type->name().c_str(),type->type_id().name());
+      std::cerr<<__FUNCTION__<<" "<<type->name()<<std::endl;
+      assert(0);
+    }
+    break;
+    case asn1::type::ASN1_REFERENCE:
+    {
+      gen_const_reference(os,type);
+    }
+    break;
+    default:
+      if (type->identifier() ) {
+        os<<"//const "<<type->cpp_name()<<"\t\t= "<<type->identifier_cpp_name()<<";";
+      } else {
+        os<<"//const "<<type->cpp_name()<<"\t\t= ? no identifier"<<";";
+      }
+        ;
+  }
+  os<<std::endl;
+
+}
+
+/**
+ *
+ */
+void generate_codec_cpp::gen_const_reference(std::ostream &os,asn1::node *type)
+{
+  asn1::node *ident = type->identifier();
+  asn1::node *real_type = 
+      m_resolver.resolve(dynamic_cast<asn1::typeref &>(*type));
+  if (dynamic_cast<asn1::typeref *>(type))
+  {
+    os<<"// ValueSet ref "<<type->name()<<std::endl;
+    return;
+  }
+  os<<ident->cpp_name()<<"::"<<ident->cpp_name()<<"()\n";
+
+  switch (real_type->type_id()())
+  {
+    case asn1::type::ASN1_CHOICE:
+    {
+      os<<"{\n}\n";
+    }
+    break;
+    case asn1::type::ASN1_BOOLEAN:
+      os<<"{\n}\n";
+    break;
+    case asn1::type::ASN1_INTEGER:
+      os<<"{\n}\n";
+    break;
+    default:
+     std::cerr<<"gen_const_reference not handled type"<<std::endl;
+      os<<"{\n}\n";
+  }
+}
+
+/*
+ * Ros generation Code
+ */
+void generate_codec_cpp::gen_object(std::ostream &os,asn1::assignment *n)
+{
+    asn1::typenode *type = n->get_type();
+    
+    // New way
+    asn1::node *real_type = 
+      m_resolver.resolve(dynamic_cast<asn1::typeref &>(*type));
+    if (real_type != NULL)
+    {
+      asn1::object   *obj  = dynamic_cast<asn1::object *>(type->get_eltype());
+      asn1::classdef *cdef = dynamic_cast<asn1::classdef *>(real_type);
+      assert( obj  != NULL);
+      assert( cdef != NULL);
+      
+      cgcpph_object obj_gen(*this,os,*obj,*cdef);
+      if ( ! n->is_generated())
+        obj_gen.generate();
+      
+    } else
+    {
+      std::cerr<<"OBJECT CLASS not found "<<type->name()<<std::endl;
+    }
+    n->set_generated(true);
+
+    n->set_color(asn1::node::CL_RED);
+
+}
+
+
+void 
+generate_codec_cpp::gen_enumerated(std::ostream &os,const std::string  &scope,asn1::node *type )
+{
+  std::string lname;
+  assert(type->type_id()() == asn1::type::ASN1_ENUMERATED );
+
+  asn1::enumerated *enumerated = dynamic_cast<asn1::enumerated *>(type);
+  assert(enumerated != NULL);
+
+  cgcpph_enumerated set_gen(*this,os,*enumerated);
+  set_gen.generate(scope); 
+
+}
+
+//
+//
+//
+void generate_codec_cpp::gen_template_params( std::ostream &os
+                                            , asn1::constructed *params)
+{
+    asn1::node::node_list nl;
+
+    os<<"<";
+    for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+    {
+      if (nl.size()>0)
+      {
+        asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+        if (it != nl.end() )
+        {
+          //
+        } else {
+         if (p != params->begin()) os<<",";
+         os<<" "<<(*p)->cpp_name();
+         nl.push_back(*p);       
+        }
+      } else {
+        if (p != params->begin()) os<<",";
+        os<<" "<<(*p)->cpp_name();
+        nl.push_back(*p);
+      }
+    }
+   os<<"> ";
+}
+
+//
+//
+//
+void generate_codec_cpp::gen_template_signature(std::ostream &os,asn1::node *type)
+{
+    asn1::node::node_list nl;
+    asn1::node            *ident  = NULL;
+    asn1::constructed     *params = NULL;
+    assert(type != NULL);
+
+    ident = type->identifier();
+    if (ident == NULL)
+    {
+      os<<"// no ident not a template"<<std::endl;
+      return;
+    }
+    if (ident && ident->parameters() && is_template(ident->parameters()) )
+    {
+      params = ident->parameters();
+      os<<"template ";
+    } else {
+      return ;
+    }
+
+    os<<"<";
+    for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+    {
+      if (nl.size()>0)
+      {
+        asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+        if (it != nl.end() )
+        {
+          //
+        } else {
+         if (p != params->begin()) os<<",";
+         os<<" typename "<<(*p)->cpp_name();
+         nl.push_back(*p);       
+        }
+      } else {
+        if (p != params->begin()) os<<",";
+        os<<" typename "<<(*p)->cpp_name();
+        nl.push_back(*p);
+      }
+    }
+   os<<"> ";
+   os<<std::endl;
+}
+
+//
+//
+//
+void generate_codec_cpp::gen_template_signature_class(std::ostream &os,asn1::node *type)
+{
+    asn1::node::node_list nl;
+    asn1::node            *ident  = NULL;
+    asn1::constructed     *params = NULL;
+    assert(type != NULL);
+    
+    ident = type->identifier();
+    if (ident == NULL)
+    {
+      return;
+    }
+    if (ident && ident->parameters() && is_template(ident->parameters()) )
+    {
+      params = ident->parameters();
+    } else {
+      return ;
+    }
+
+    os<<"<";
+    for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+    {
+      if (nl.size()>0)
+      {
+        asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+        if (it != nl.end() )
+        {
+          //
+        } else {
+         if (p != params->begin()) os<<",";
+         os<<" "<<(*p)->cpp_name();
+         nl.push_back(*p);       
+        }
+      } else {
+        if (p != params->begin()) os<<",";
+        os<<" "<<(*p)->cpp_name();
+        nl.push_back(*p);
+      }
+    }
+   os<<">";
+}
+
+/**
+ *
+ */ 
+void generate_codec_cpp::gen_private( std::ostream &os
+                                    , const std::string &scope
+                                    , asn1::constructed *_type)
+{
+  asn1::constructed *type = _type->as_constructed();
+  std::string structName;
+  asn1::node::iterator attr_it;
+
+  assert( (type != NULL )
+          &&
+          ( (type->type_id()() == asn1::type::ASN1_CHOICE)
+            || (type->type_id()() == asn1::type::ASN1_SET)
+            || (type->type_id()() == asn1::type::ASN1_SEQUENCE)
+              )
+      );
+
+  struct_name(type,structName);
+
+  for ( attr_it = type->begin()
+        ; attr_it != type->end() 
+        ; ++attr_it)
+  {
+    asn1::field            *f = dynamic_cast<asn1::field *>(*attr_it);
+    asn1::typenode *attr_type = f->get_type();
+    // Extension markers don't have a type
+    // assert( attr_type != NULL);
+    if (attr_type != NULL)
+    {
+      switch (attr_type->type_id()())
+      {
+        case asn1::type::ASN1_SEQUENCE_OF:
+        case asn1::type::ASN1_SET_OF:
+        {
+          asn1::node *softype = attr_type->get_eltype();
+          GEN_LOG_DEBUG("call private seq of %s\n",(*attr_it)->cpp_name().c_str());
+          if (softype->type_id()() >= asn1::type::ASN1_SEQUENCE &&
+              softype->type_id()() <= asn1::type::ASN1_SET_OF)
+          {
+            gen_private_attribute(os,scope,attr_type->get_eltype());
+          }
+        }
+        break;
+        case asn1::type::ASN1_SEQUENCE:
+        case asn1::type::ASN1_SET:
+        case asn1::type::ASN1_ENUMERATED:
+        case asn1::type::ASN1_CHOICE:
+            if (type->identifier() != NULL)
+            {
+              GEN_LOG_DEBUG("call private seq of %s\n",(*attr_it)->cpp_name().c_str());
+              gen_private_attribute(os,scope,attr_type);
+            } else {
+              GEN_LOG_ERROR("did not call private seq of %s\n",(*attr_it)->cpp_name().c_str());
+              assert(0);
+            }
+            break;
+        defatult:
+              GEN_LOG_DEBUG("default not call private seq of %s\n",(*attr_it)->cpp_name().c_str());
+          ;
+      }
+    }
+
+  }
+}
+
+
+/**
+ *
+ * called for each attribute in sequence , choice or set.
+ * n can be of any type ....
+ * I'm missing the function that loops over the attributes.
+ * This function should be called gen private attribute
+ */
+void generate_codec_cpp::gen_private_attribute( std::ostream &os
+                                              , const std::string &scope
+                                              , asn1::typenode *n)
+{
+  asn1::node *params = NULL;
+  assert(n!=NULL);
+  if (n)
+  {
+    params = n->parameters();
+    GEN_LOG_DEBUG(" scope=%s node=%s  params: %d typeid=%d\n",
+            scope.c_str()
+            ,n->cpp_name().c_str()
+            ,(params==NULL)?0:1
+            ,n->type_id()()
+            );
+   os<<"//generate_codec_cpp::"<<__FUNCTION__<<" "<<scope<<n->cpp_name()<<std::endl;
+  }
+
+  switch (n->type_id()())
+  {
+      case asn1::type::ASN1_CHOICE:
+          gen_choice(os,scope,n,true);
+          break;
+      case asn1::type::ASN1_SEQUENCE:
+          gen_seq(os,scope,n,true);
+          break;
+      case asn1::type::ASN1_SET:
+          gen_set(os,scope,n->as_set());
+          break;
+      case asn1::type::ASN1_SET_OF:
+      case asn1::type::ASN1_SEQUENCE_OF:
+          {
+            asn1::typenode *type = n;
+            asn1::typenode *subtype = type->get_eltype();
+            assert(subtype != NULL); 
+            os<<"// gen_private_attribute type SEQUENCE_OF ... \n";
+            if (type->has_constraints())
+            {
+              os<<"// I have constraints\n";
+            }
+            switch (subtype->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+                os<<"// gen_private_attribute type SEQUENCE_OF ... launch gen_seq \n";
+                gen_seq(os,scope,subtype,true);
+                os<<"\n//end\n";
+                break;
+              case asn1::type::ASN1_CHOICE:
+                os<<"// gen_private_attribute type SEQUENCE_OF ... launch gen_choice \n";
+                gen_choice(os,scope,subtype,true);
+                os<<"\n//end\n";
+                break;
+              default:
+                os<<"// gen_private_attribute type SEQ or SET OF ... type to be code \n";
+                ;
+            }
+          }
+      break;
+      case asn1::type::ASN1_ENUMERATED :
+          gen_enumerated(os,scope,n);
+          break;
+      default:
+          GEN_LOG_DEBUG("Did not do anything for %s%s type_id=%d\n",scope.c_str(),n->cpp_name().c_str(),n->type_id()());
+          ;
+  }
+}
+
+
+void 
+generate_codec_cpp::struct_name(asn1::node *type,std::string &structName)
+{
+  assert(type != NULL);
+
+  if (type->is_private())
+  {
+    structName =  type->cpp_name();
+  } else
+  {
+    structName = type->identifier_cpp_name();
+  }
+}
+/*
+ *  vim:et sw=2 ts=2 list:
+ */ 
diff --git a/libgen/asn1_gen_codec_cpp.h b/libgen/asn1_gen_codec_cpp.h
new file mode 100644 (file)
index 0000000..8ad7160
--- /dev/null
@@ -0,0 +1,158 @@
+#ifndef GEN_CODEC_CPP_H__
+#define GEN_CODEC_CPP_H__
+#include <iostream>
+#include <string>
+#include <algorithm>
+
+#include "libparser/asn1_parser_listener.h"
+#include "asn1_gen_constraints.h"
+
+
+/**
+ *
+ */
+class generate_codec_cpp :  public generate_cpp
+{
+  protected:
+    generate_codec_cpp(const generate_codec_cpp &c) :
+      generate_cpp(c) 
+      , m_gen_constraints(c.m_gen_constraints)
+    { std::cout<<"copy generate_codec_cpp\n"; }
+  public:
+
+    generate_codec_cpp(asn1::module *n,gen_constraints &c) : generate_cpp(n) , m_gen_constraints(c) {};
+    generate_codec_cpp(asn1::module *n,asn1::module::modules_type &m,gen_constraints &c);   
+
+    /**/
+    void gen_attribute_constrained_ndecode( std::ostream &os
+                                          , const std::string &scope
+                                          , const std::string &indent
+                                          , asn1::field *attr);
+    
+    void gen_attribute_constrained_nencode( std::ostream &os
+                                          , const std::string &scope
+                                          , const std::string &indent
+                                          ,asn1::field *attr);
+    
+    /**
+     *
+     */
+    void gen_decode_set(std::ostream &os,asn1::node *attribute);
+
+    /**
+     *
+     */
+    void gen_const(std::ostream &os,asn1::node *n);
+    /**
+     *
+     */
+    void gen_objectset(std::ostream &os,asn1::objectset &n);
+    /**
+     *
+     */
+    void gen_const_reference(std::ostream &os,asn1::node *n);
+    
+    /**
+     *
+     */
+    void gen_enumerated(std::ostream &os,const std::string &scope,asn1::node *enum_node);
+    
+    //
+    //
+    //
+    void gen_typedef(std::ostream &os,asn1::typenode *n);
+    void gen_typeref(std::ostream &os,asn1::typeref *n);
+    /**
+     * generate structure for primitive typedefs Type ::= INTGER
+     * because integer is under constructed. That's a bit wierd 
+     */ 
+    void gen_primitive(std::ostream &os,asn1::typenode &n);
+    
+    void 
+    gen_composite_attribute_printf( std::ostream &os
+                                  , const std::string &scope
+                                  , asn1::field &attribute
+                                  , asn1::node *params=NULL);
+    void gen_composite_attribute_ref(std::ostream &os
+                                  , const std::string &scope
+                                  , asn1::field *attribute
+                                  , asn1::node  *params = NULL);
+    
+    void gen_template_params(std::ostream &os,asn1::constructed *type);
+    void gen_template_signature(std::ostream &os,asn1::node *type);
+    void gen_template_signature_class(std::ostream &os,asn1::node *type);
+    /**
+     *
+     */
+    void gen_seq(std::ostream &os,const std::string &scope,asn1::node *n,bool priv=false);
+    
+    // Choice 
+    
+    void gen_choice(std::ostream &os,const std::string &scope,asn1::node *n,bool priv = false);
+    
+    /**
+     *
+     */
+    void gen_set( std::ostream &os
+                , const std::string &scope
+                , asn1::set *n);
+
+    void gen_set_of(std::ostream &os,asn1::node *n);
+    /**
+     * SEQUENCE,CHOICE,SET might contain private SEQUENCE CHOICE or SET.
+     * I need to generate special codecs for these structures
+     *   therefore gen_private node is either SEQ, SET, CHOICE container
+     *   that loops over each attribute
+     *   
+     */
+    void gen_private( std::ostream &os
+                    , const std::string &scope
+                    , asn1::constructed *n);
+    /**
+     * called within gen_private
+     */ 
+    void gen_private_attribute( std::ostream &os
+                              , const std::string &scope
+                              , asn1::typenode *n);
+    // bit string
+    void gen_bitstring( std::ostream &os
+                      , const std::string &scope
+                      , asn1::bit_string &n,bool priv=false);
+    /*
+     * Ros generation Code
+     */
+    void gen_object(std::ostream &os,asn1::assignment *n); 
+
+    void gen_module(std::ostream &os,asn1::module *n);
+    /**
+     *
+     */ 
+    void gen_include_header(std::ostream &os);
+    // Will be used by helper classes
+    void struct_name(asn1::node *type,std::string &structName);
+    /**
+     * _a      (IN)   : assignment
+     * _stream (INOUT): opened stream based on m_module_path and assignment cpp_name
+     * return true if stream is open
+     */ 
+     bool open_assignment_stream(std::fstream &_stream,asn1::assignment *_a);
+     /**
+      *
+      */
+     inline const std::string &get_module_path() const
+     { return m_module_path; }
+  protected:
+     void generate_constraints(std::ostream &os);
+    /**
+     * Create current dir + module cpp_name dir.
+     */
+    bool make_module_dir(asn1::module *_module);
+  protected:
+    std::string     m_module_path;
+    gen_constraints &m_gen_constraints;
+};
+
+/**
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libgen/asn1_gen_config.h.in b/libgen/asn1_gen_config.h.in
new file mode 100644 (file)
index 0000000..b7e0ab5
--- /dev/null
@@ -0,0 +1,9 @@
+#cmakedefine HAVE_UNISTD_H
+#cmakedefine HAVE_STDLIB_H
+#cmakedefine HAVE_PTHREAD_H
+#cmakedefine HAVE_DIRECT_H
+#cmakedefine HAVE_STDINT_H
+/* system function check*/
+#cmakedefine HAVE_GETCWD
+#cmakedefine HAVE_MKDIR
+
diff --git a/libgen/asn1_gen_constraints.cpp b/libgen/asn1_gen_constraints.cpp
new file mode 100644 (file)
index 0000000..46bb9f0
--- /dev/null
@@ -0,0 +1,57 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <assert.h>
+
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_generator.h"
+
+#include "libparser/asn1_parser_listener.h"
+#include "asn1_gen_constraints.h"
+
+
+gen_constraints::gen_constraints()
+{
+    ;
+}
+
+gen_constraints::~gen_constraints()
+{
+  std::cout<<"gen_constraints::~gen_contraints"<<std::endl;  
+  for (   moduleMapIterator mit = m_map.begin()
+        ; mit != m_map.end()
+        ; ++mit)
+  {
+    std::cout<<"Module "<<mit->first<<" has "<<mit->second.size();
+    std::cout<<" constraints"<<std::endl;
+    for (constraintSetIterator cit = mit->second.begin();
+             cit != mit->second.end();
+              ++cit)
+    {
+      std::cout<<"\t"<<cit->m_count<<" "<<cit->m_constraint->name()<<std::endl;  
+    }
+  }
+}
+
+void 
+gen_constraints::onConstraint(asn1::constraint *c) 
+{
+  constraintSetIterator it;  
+  std::pair<gen_constraints::constraintSetIterator,bool >  ret; 
+  local_constraint lc(c);
+  m_constraints.insert(lc);
+  ret = m_map[m_current_module].insert(lc);
+  if (ret.second == false)
+  {
+    it = ret.first;  
+    (*it).m_count++;
+  }
+}
+
+void 
+gen_constraints::onModule(asn1::module *m) 
+{
+  m_current_module = m->name();
+}
diff --git a/libgen/asn1_gen_constraints.h b/libgen/asn1_gen_constraints.h
new file mode 100644 (file)
index 0000000..77bcf52
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef ASN1_GEN_CONSTRAINTS_H
+#define ASN1_GEN_CONSTRAINTS_H
+
+/**
+ * @brief Constraint collector class
+ *   Collect all constrains to generate a unique constraint table.
+ */ 
+class gen_constraints : public asn1::parser_listener
+{
+  public:
+    /**
+     *
+     *
+     */ 
+    struct local_constraint
+    {
+      public:  
+      local_constraint(asn1::constraint *c = NULL) : m_count(1), m_constraint(c) {}; 
+
+      bool operator ==(local_constraint &lc)
+      {
+        return !m_constraint->name().compare(lc.m_constraint->name());  
+      }
+      
+      bool operator ==(asn1::constraint &lc) 
+      {
+        return !m_constraint->name().compare(lc.name());  
+      }
+
+      bool operator <(const local_constraint &lc) const
+      {
+        return m_constraint->name().compare(lc.m_constraint->name()) > 0 ;  
+      }
+
+      void inc() { m_count++; } ; 
+      asn1::constraint *m_constraint;  
+      mutable long      m_count;  
+    };
+    //
+    typedef std::set<local_constraint>      constraintSet;
+    typedef constraintSet::iterator         constraintSetIterator;
+    typedef constraintSet::const_iterator   const_constraintSetIterator;
+
+    typedef std::map<std::string,constraintSet> moduleMap;
+    typedef moduleMap::iterator                 moduleMapIterator;
+
+    // Default constructor
+    gen_constraints();
+    // Destructor
+    ~gen_constraints();
+
+    void onConstraint(asn1::constraint *c); 
+    
+    void onModule(asn1::module *m); 
+    //
+    inline constraintSetIterator begin() 
+    { return m_constraints.begin() ; }
+    //
+    inline constraintSetIterator end() 
+    { return m_constraints.end() ; }
+   
+    //
+    inline const_constraintSetIterator begin() const
+    { return m_constraints.begin() ; }
+    //
+    inline const_constraintSetIterator end() const
+    { return m_constraints.end() ; }
+
+  protected:
+    std::string   m_current_module;
+    constraintSet m_constraints;
+    moduleMap     m_map;
+};
+
+#endif /*ASN1_GEN_CONSTRAINTS_H*/
diff --git a/libgen/asn1_gen_cpp.cpp b/libgen/asn1_gen_cpp.cpp
new file mode 100644 (file)
index 0000000..68c7830
--- /dev/null
@@ -0,0 +1,572 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <list>
+#include <assert.h>
+
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+
+
+codecstreams::codecstreams()
+{
+}
+//
+void 
+codecstreams::open(const std::string &name,bool jer,bool per,bool oer)
+{
+  std::string filename = name + "_codec.hpp";
+  m_os_codec_hpp.open(filename.c_str(),std::fstream::out);
+  m_os_codec_hpp<<"// Generated do not modifie"<<std::endl;
+  filename = name + "_codec.cpp";
+  m_os_codec_cpp.open(filename.c_str(),std::fstream::out);
+  m_os_codec_cpp<<"// Generated do not modifie"<<std::endl;
+  if (jer)
+  {
+    filename = name + "_codec_jer.cpp";
+    m_os_jer.open(filename.c_str(),std::fstream::out);
+  }
+  if (per)
+  {
+    filename = name + "_codec_per.cpp";
+    m_os_per.open(filename.c_str(),std::fstream::out);
+  }
+  if (oer)
+  {
+    filename = name + "_codec_oer.cpp";
+    m_os_oer.open(filename.c_str(),std::fstream::out);
+  }
+}
+
+void 
+codecstreams::close()
+{
+  if (m_os_codec_hpp.is_open())
+    m_os_codec_hpp.close();
+  if (m_os_codec_cpp.is_open())
+    m_os_codec_cpp.close();
+  if (m_os_jer.is_open())
+    m_os_jer.close();
+  if (m_os_per.is_open())
+    m_os_per.close();
+  if (m_os_oer.is_open())
+    m_os_oer.close();
+}
+
+codecstreams::~codecstreams()
+{
+  close();
+}
+
+/**
+ *
+ */
+generate_cpp::generate_cpp(asn1::module *n)
+    : asn1::generator(n)
+{
+}
+
+generate_cpp::generate_cpp(asn1::module *n,asn1::module::modules_type &m)
+  : asn1::generator(n,m)
+{
+
+}
+
+
+generate_cpp::~generate_cpp()
+{
+}
+
+
+void 
+generate_cpp::
+gen_template_params(std::ostream &os,asn1::node *_params)
+{
+  asn1::constructed    *params     = _params->as_constructed();
+  asn1::node::node_list nl;
+
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+  os<<"> ";
+}
+
+
+void generate_cpp::gen_composite_attribute_ref(  std::ostream &os
+                                 , const std::string  &scope
+                                 , asn1::field  *attribute
+                                 , asn1::node   *_params )
+{
+  asn1::constructed    *params     = _params->as_constructed();
+  asn1::typeref *attr_type = dynamic_cast<asn1::typeref *>(attribute->get_type());
+  assert( attr_type != NULL);
+  asn1::reference *ref = attr_type->get_reference();
+  
+  assert(ref != NULL);
+
+  if ( ref && (ref->size() > 1)) 
+  {
+      gen_comp_attr_complex_ref(os,scope,*attr_type,params);
+  } else
+  {
+    gen_comp_attr_simple_ref(os,scope,*attr_type,params);
+  }
+}
+
+/**
+ *
+ */ 
+void 
+generate_cpp::gen_comp_attr_ref_tplt(std::ostream &os
+                                 , asn1::typeref *attr_type
+                                 , asn1::node    *real_type
+                                 , asn1::node    *params)
+{
+  // check if attribute has parameters
+  if(attr_type->act_parameters() != NULL 
+     && (real_type) 
+     && is_template(real_type->identifier()->parameters()) 
+    )
+  {
+    os << "<";
+    for(asn1::node::iterator it = attr_type->act_parameters()->begin(); 
+                             it != attr_type->act_parameters()->end(); ++it) 
+    {
+      asn1::node* ns1 = NULL;
+      if(it != attr_type->act_parameters()->begin())
+        os << ",";
+      // check namespace
+      if(type_in_imports((*it)->name(), &ns1)) {
+        os << ns1->cpp_name() << "::" << (*it)->cpp_name();
+      } else
+        os << (*it)->cpp_name();
+    }
+    os << ">";
+  }
+}
+
+/**
+ * Simple reference attribute. No object or complex reference
+ *
+ */ 
+void
+generate_cpp::gen_comp_attr_simple_ref(std::ostream        &os
+                                       , const std::string &scope
+                                         , asn1::typeref     &_ref
+                                         , asn1::node        *_params)
+{
+  asn1::constructed    *params     = _params->as_constructed();
+  asn1::typeref        *attr_type  = &_ref; 
+  asn1::node           *attribute  = _ref.identifier();  
+  asn1::reference      *ref        = _ref.get_reference();
+  asn1::node::iterator refm        = std::find_if(m_module->begin(),
+              m_module->end(),
+              asn1::find_node(ref->name()));
+  asn1::node *real_type            = m_resolver.resolve(*attr_type);
+
+  if (refm != m_module->end())
+  {
+    // Here Type in current module I have the type definition. I should add
+      if ( ((*refm)->get_color() == 2) 
+           || attribute->flags().is_optional()
+           || ! attribute->get_parent()->identifier()->name().compare(_ref.name())
+         ) 
+        os<<"ASN1_ATTRIBUTE_OPTIONAL(";
+      
+      os<<ref->cpp_name();
+
+      gen_comp_attr_ref_tplt(os,attr_type,real_type,params);
+
+      if ( ((*refm)->get_color() == 2 )
+           || attribute->flags().is_optional()
+           || ! attribute->get_parent()->identifier()->name().compare(_ref.name())
+         ) 
+        os<<" )";
+      if (with_source_comment())
+      {
+        os<<" /*NR c="<<(*refm)->get_color();
+        os<<" opt="<<attribute->flags().is_optional();
+        os<<" param="<<params<<" */ ";
+      }
+  } else 
+  {
+     // Type in import
+     asn1::node *ns = NULL;
+     if (type_in_imports(ref->name(),&ns) )
+     {
+       asn1::reference::component_const_iterator compit = ref->begin();
+       // Simple external Reference 
+       if (attribute->flags().is_optional() )
+       {
+         os<<"ASN1_ATTRIBUTE_OPTIONAL("<<ns->cpp_name()<<"::"<<ref->cpp_name()<<")";
+         if (with_source_comment())
+             os<<"/*NR 2 optional="<<attribute->flags().is_optional()<<" */ ";
+       } else
+       {
+           os<<ns->cpp_name()<<"::"<<ref->cpp_name();
+           if (with_source_comment())
+             os<<" /*NR 2 optional="<<attribute->flags().is_optional()<<" */ ";
+       }
+       // check if attribute has parameters
+
+       gen_comp_attr_ref_tplt(os,attr_type,real_type,params);
+
+     } else if (params) // reference in parameters of definition
+     {
+        // Wierd case 
+        bool found = false;
+        for ( asn1::node::iterator it = params->begin()
+            ; it != params->end(); ++it)
+        {
+          if (ref->name().compare((*it)->name())== 0)
+          {
+             os<<" "<<(*it)->cpp_name();
+             found = true;
+          }
+          if (!found) {
+           GEN_LOG_ERROR("Parameter %s\n",(*it)->name().c_str());
+           os<<" ERRORNOTPARAMS ";
+          }
+
+        }
+
+     } else
+     {
+       os<<" ERROR ";
+     }
+  }
+}
+
+/**
+ *
+ */ 
+void 
+generate_cpp::gen_comp_attr_complex_ref(std::ostream      &os
+                                    , const std::string   &scope
+                                    , asn1::typeref       &_ref
+                                    , asn1::node          *params)
+{
+  asn1::typeref         *attr_type  = &_ref; 
+  asn1::node            *attribute  = _ref.identifier();  
+  asn1::node            *real_type  = m_resolver.resolve(*attr_type);
+  asn1::node::node_list nl;
+  if (real_type)
+  {
+    real_type->path2module(nl);
+    asn1::module *t_module = m_module;
+    if (!nl.empty())
+    {
+      t_module = dynamic_cast<asn1::module *>(nl.front()->get_parent());
+    } else
+    {
+    }      
+
+    if (t_module && ! t_module->name().compare(m_module->name()))
+    {
+      std::string scope("");
+      gen_attr_field_type(os,scope,real_type);
+    } else if (t_module)
+    { 
+      // Type in other module
+      //os<<" /* t_module "<<real_type->name()<<" */ ";
+      std::string scope("");
+      scope = t_module->cpp_name() +"::";
+      if (_ref.is_external())
+      {
+        os<<scope<<real_type->identifier()->cpp_name() ;  
+      }else
+        gen_attr_field_type(os,scope,real_type);
+    } else
+    { // Error 
+      assert(0);
+    }
+  }
+}    
+/**
+ * @brief Build the name of the type when is choice or sequence. 
+ */ 
+void generate_cpp::private_attribute_type(asn1::node *type,std::string &structName)
+{
+  asn1::node::node_list lst;
+  assert(type != NULL);
+  assert(type->get_parent() != NULL);
+  std::string ss = type->cpp_name()+"_t";
+  type->path2module(lst);
+
+  for (asn1::node::const_iterator nit = lst.begin()
+       ; nit != lst.end()
+       ; ++nit )
+  {
+    if ( (*nit)->is_private() )
+    {
+      std::string tmp = (*nit)->cpp_name() + "_";
+      ss.insert(0,tmp);
+    } else
+    {
+      std::string tmp = (*nit)->identifier()->cpp_name() + "_";
+      ss.insert(0,tmp);
+    }
+  }
+  structName = ss;
+}
+
+/**
+* @brief
+*   Generate field type attribute depending on scope
+*     If field is not in current module, 
+*     scope = modle_cpp_name +"::" 
+*/ 
+void 
+generate_cpp::gen_attr_field_type( std::ostream &os
+                                 , std::string   &scope
+                                 , asn1::node    *field_type
+                                 )
+{
+  // Type in current module
+  // Wow attribute found in class Now I can decide what to do
+  switch( field_type->type_id()())
+  {
+  case asn1::type::ASN1_CLASSFIELD_TF:
+    os<<"asn1::intrusive_ptr<";
+    os<<scope<<"I";
+    os<<field_type->get_parent()->identifier_cpp_name()<<"> ";
+    if (with_source_comment())
+    {  
+      os<<"/* CF ";
+      os<<field_type->get_parent()->identifier_cpp_name();
+      os<<" TF "<<field_type->name();
+      //" optional="; os<<attribute->flags().is_optional();
+      os<<" */ ";
+    }
+    break;
+  case asn1::type::ASN1_CLASSFIELD_FTVF: 
+    {
+      asn1::classfield_ftvf *f = dynamic_cast<asn1::classfield_ftvf *>(field_type);
+      asn1::typenode *rnode = f->get_type();
+      os<<""<<scope<<rnode->cpp_name();
+      if (with_source_comment())
+      {
+        os<<" /* CF FTVF "<<field_type->name();
+        //os<<" optional:"<<attribute->flags().is_optional();
+        os<<" */ ";
+      }
+    }
+    break;
+  case asn1::type::ASN1_REFERENCE: 
+  case asn1::type::ASN1_INTEGER: 
+  case asn1::type::ASN1_CHOICE: 
+  case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    os<<scope<<field_type->cpp_name()<<" /* "<<field_type->name()<<"*/";
+    break;
+  default:
+    os<<"/* tyid="<<field_type->type_id()();
+    os<<" Field "<<field_type->name()<<"*/";
+    break;
+  }
+}
+
+
+/**
+ *
+ * This function should be used to compute the names of the structures with and without scope.
+ * In order to facilitate nested / unnested 
+ *   -> ASN1_ENUMERATED  returns either cpp_name or indentifier_cpp_name if private or not
+ *   -> ASN1_NULL        returns Null
+ *   -> ASN1_SEQUENCE_OF
+ *   -> ASN1_SET_OF
+ *   -> ASN1_CHOICE
+ *   -> ASN1_SET
+ *   -> ASN1_SEQUENCE
+ *   TOBE COMPLETED 
+ *   -> ASN1_REFERNCE
+ *    default not working properly
+ */ 
+bool generate_cpp::type2cppstring( asn1::typenode *type 
+                                 , std::string &strtype
+                                 , const std::string &scope)
+{
+  asn1::node *ns;
+  
+  assert(type != NULL);
+  
+  if (type == NULL) 
+  {
+    GEN_LOG_ERROR("type2cppstring failes type is nul \n");
+    return false;
+  }
+  switch (type->type_id()() )
+  {
+    case asn1::type::ASN1_SEQUENCE_OF:
+      {
+          asn1::node  *seqof_type = type->get_eltype();
+          if (type_in_imports(seqof_type,&ns )) {
+            strtype = type->cpp_name()+"<"+ns->cpp_name()+"::"+seqof_type->cpp_name()+">";
+          } else {
+            switch (seqof_type->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+              {
+                asn1::node::node_list lst;
+                std::string ss;
+                type->path2module(lst);
+                for (asn1::node::const_iterator nit = lst.begin()
+                     ; nit != lst.end()
+                     ; ++nit )
+                {
+                  if ( (*nit)->is_private() )
+                  {
+                    ss += (*nit)->cpp_name() + "::";
+                  } else
+                    ss += (*nit)->identifier()->cpp_name() + "::";
+                }
+                //TODO compute namespace if type is private or else clang complains  
+                strtype="SEQUENCE_OF</*t2cs */ "+ seqof_type->cpp_name()+"> ";
+              }
+              break;
+              default:
+                if (asn1::typeref *tref = seqof_type->as_typeref())
+                {
+                  strtype="SEQUENCE_OF</*t2cs2 */"+tref->get_reference()->cpp_name()+"> ";
+                } else
+                {
+                  if (seqof_type->is_private())
+                  {
+                    strtype="SEQUENCE_OF</*t2cs3p*/ ";
+                    strtype+=type->get_parent()->identifier()->cpp_name()+"::";
+                    strtype+=seqof_type->cpp_name()+"> ";
+                  } else
+                    strtype="SEQUENCE_OF</*t2cs3*/ "+seqof_type->cpp_name()+"> ";
+                }
+            }
+          }
+      }
+    break;
+    case asn1::type::ASN1_SET_OF:
+      {
+        asn1::node  *setof_type = type->get_eltype();
+        if (type_in_imports(setof_type,&ns ))
+        {
+          strtype = type->cpp_name()+"<"+ns->cpp_name()+"::"+setof_type->cpp_name()+">";
+        } else
+        {
+          switch (setof_type->type_id()())
+          {
+            case asn1::type::ASN1_SEQUENCE:
+            {
+              strtype="SET_OF<"+scope+setof_type->cpp_name()+"> ";
+            }
+            break;
+            default:
+              if (
+                asn1::typeref *tref = 
+                  dynamic_cast<asn1::typeref *>(setof_type)
+                  //setof_type->get_reference()
+                  )
+              {
+                if (tref->is_objectclass())
+                {
+                  asn1::node *rt = m_resolver.resolve(*tref);
+                  if (rt->type_node())
+                  {
+                    strtype = rt->type_node()->cpp_name();
+                    return true;
+                  }
+                }
+                else if (tref->is_simple())
+                {
+                  asn1::node *rt = m_resolver.resolve(*tref);
+                  strtype="SET_OF</*t3cs2r*/";
+                  strtype +=rt->get_parent()->cpp_name();
+                  strtype +="::" +tref->get_reference()->cpp_name()+"> ";
+                  return true;
+                }
+                strtype="SET_OF</*t3cs2*/";
+                strtype+= tref->get_reference()->cpp_name()+"> ";
+              } else
+              {
+                strtype="SET_OF</*t3cs3*/"+setof_type->cpp_name()+"> ";
+              }
+          }
+        }
+      }
+    break;
+  case asn1::type::ASN1_NULL:
+      strtype= "Null";
+    break;
+  case asn1::type::ASN1_ENUMERATED:  
+  case asn1::type::ASN1_SET:  
+      // THIS NEEDS TO BE VALIDATED  
+      if (type->is_private())
+      {
+        private_attribute_type(type->identifier(),strtype);
+      } else   
+        strtype = type->identifier_cpp_name();
+    break;
+  case asn1::type::ASN1_SELECTION:
+    {
+       strtype = "INTEGER";
+       return true;
+    }
+    break;
+#if defined(_WINDOWS)
+  case asn1::type::ASN1_BOOLEAN:
+    {
+       strtype = std::string("asn1::") + type->cpp_name();
+       return true;
+    }
+#endif
+    break;
+  case asn1::type::ASN1_REFERENCE:
+    {
+      asn1::typeref *tref = dynamic_cast<asn1::typeref *>(type);
+      if (tref->is_objectclass())
+      {
+        asn1::node *rt = m_resolver.resolve(*tref);
+        if (rt->type_node())
+        {
+          strtype = rt->type_node()->cpp_name();
+          return true;
+        }
+        if (!rt)
+        {
+          std::cerr<<"type2cppstring "<<tref->name()<<" Failed"<<std::endl;
+          assert(0);
+        }
+        // important for complex...
+        type = rt->as_typenode();
+      }
+    }
+    //break;
+  default:
+    if (type_in_imports(type->name(),&ns ))
+    {
+      strtype = ns->cpp_name()+ "::"+type->cpp_name();
+    } else 
+    {
+      strtype = type->cpp_name();
+    }
+  }
+
+  return true;
+}
+
+/*
+ * vim: et sw=2 ts=2 list
+ */
diff --git a/libgen/asn1_gen_cpp.h b/libgen/asn1_gen_cpp.h
new file mode 100644 (file)
index 0000000..a6f8bdd
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef ASN1_GEN_CPP_H__
+#define ASN1_GEN_CPP_H__
+
+
+/**
+ * Generate code in deferent files for simplicity
+ *   os_codec_hpp <name>_codec.hpp
+ *   os_codec_cpp <name>_codec.cpp
+ *   os_jer       <name>_codec_jer.cpp
+ *   os_per       <name>_codec_per.cpp
+ *   os_oer       <name>_codec_oer.cpp
+ *    When created, also create the associated streams
+ */ 
+struct codecstreams
+{
+  protected:
+    codecstreams(const codecstreams &c) 
+    { std::cout<<"codecstreams copy\n";}
+    ;
+  public:
+    codecstreams() ;
+    void open(const std::string &name,bool jer,bool per,bool oer) ;
+    void close() ;
+    ~codecstreams();
+    std::fstream m_os_codec_hpp;
+    std::fstream m_os_codec_cpp;
+    std::fstream m_os_jer;
+    std::fstream m_os_per;
+    std::fstream m_os_oer;
+};
+/**
+ * Common generation function that can be used in header and cpp files has well
+ *
+ * Forseen usage : 
+ *   - attribute_ref resolution
+ *   - value_from object
+ *   - constraints
+ *   - template signatures
+ */
+class generate_cpp : public asn1::generator
+{
+  protected:
+    generate_cpp(const generate_cpp &g) 
+      : asn1::generator(g)  
+    {
+      std::cout<<"copy generate_cpp "<<std::endl;
+    };
+  protected:  
+    codecstreams m_Streams;   
+  public:
+      
+    generate_cpp(asn1::module *n);
+    generate_cpp(asn1::module *n,asn1::module::modules_type &m);   
+
+    virtual ~generate_cpp();
+
+    inline codecstreams &get_streams() { return m_Streams; };
+    //
+    void gen_template_params(std::ostream &os,asn1::node *params);
+    /**
+     *
+     */ 
+    void gen_composite_attribute_ref(  std::ostream &os
+                                     , const std::string  &scope
+                                     , asn1::field  *attribute
+                                     , asn1::node   *params = NULL);
+    /**
+     * TODO: Needs to be moved to asn1_gen_cpp.cpp
+     */ 
+    bool type2cppstring( asn1::typenode *type 
+                      , std::string    &strtype
+                      , const std::string &scope = "");
+
+  protected:
+    void gen_comp_attr_simple_ref(std::ostream &os
+                                    , const std::string   &scope
+                                    , asn1::typeref       &_ref
+                                    , asn1::node          *params);
+    /**
+     * @brief 
+     *   Handle the complex case with object class references and
+     *   so on.
+     * @param os
+     * @param scope
+     * @param _ref
+     * @param params
+     */
+    void gen_comp_attr_complex_ref(std::ostream &os
+                                    , const std::string   &scope
+                                    , asn1::typeref       &_ref
+                                    , asn1::node          *params);
+    /**
+     * @brief 
+     *   Output template signature for eventual template parameters
+     *   
+     * @param os
+     * @param attr_type
+     * @param real_type
+     * @param params
+     */
+    void gen_comp_attr_ref_tplt(std::ostream &os
+                                 , asn1::typeref *attr_type
+                                 , asn1::node    *real_type
+                                 , asn1::node    *params);
+    /**
+     * @brief
+     *   Generate field type attribute depending on scope
+     *     If field is not in current module, 
+     *     scope = modle_cpp_name +"::" 
+     */ 
+    void gen_attr_field_type( std::ostream &os
+                            , std::string   &scope
+                            , asn1::node    *field_type
+                            );
+  public:
+    /**
+     * @brief
+     *   Compute private attribute cpp struct name for attribute
+     *    that use defined types like choice, enum, set sequence...
+     *    example Toto ::= SEQUENCE {
+     *      x CHOICE { a INTEGER,
+     *                 b BOOLEAN}
+     *      y SET { ab BIT STRING }
+     *      }
+     *
+     *  type for x should be Toto_x_t
+     */      
+     void private_attribute_type(asn1::node *attr,std::string &structName);
+};
+
+#endif
diff --git a/libgen/asn1_gen_hpp.cpp b/libgen/asn1_gen_hpp.cpp
new file mode 100644 (file)
index 0000000..df25b9a
--- /dev/null
@@ -0,0 +1,1691 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#if defined(__APPLE__) || (GCC_VERSION > 40800)
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+#if defined(_WIN32)
+#include <io.h>
+#include <stdlib.h>
+#include <direct.h>
+#define  getcwd _getcwd
+#define  mkdir  _mkdir
+#endif
+#include "asn1_resolver.h"
+#include "asn1_generator_helper.h"
+#include "cpp/cghpp_helper.h"
+#include "cpp/cgh_hconstruct.h"
+#include "cpp/cghpph_primitive.h"
+#include "cpp/cghpph_bitstring.h"
+#include "cpp/cghpph_octetstring.h"
+#include "cpp/cghpph_classdef.h"
+#include "cpp/cghpph_enumerated.h"
+#include "cpp/cghpph_integer.h"
+#include "cpp/cghpph_sequence.h"
+#include "cpp/cghpph_sequenceof.h"
+#include "cpp/cghpph_setof.h"
+#include "cpp/cghpph_choice.h"
+#include "cpp/cghpph_set.h"
+#include "cpp/cghpph_typeref.h"
+#include "cpp/cgh_object.h"
+#include "cpp/cghpph_object.h"
+#include "cpp/cghpph_import.h"
+#include "cpp/cghpph_string.h"
+#include "cpp/cghpph_boolean.h"
+#include "cpp/cghpph_oid.h"
+#include "asn1_visitor.h"
+
+/**
+ * generate template instantiation in .hpp file
+ *
+ */ 
+struct gen_tplt
+{
+  gen_tplt(std::ostream &os,generate_header &g)
+    : m_os(os), m_Gen(g)
+  {
+  }
+
+  void operator ()(asn1::node *n)
+  {
+    asn1::typenode *type = n->as_assignment()->get_type();
+    
+    assert(type->type_id()() == asn1::type::ASN1_REFERENCE);
+    asn1::node *real_type = 
+      m_Gen.resolver().resolve(dynamic_cast<asn1::typeref &>(*type));
+    if (real_type != NULL)
+    {
+      asn1::object   *obj  = dynamic_cast<asn1::object *>(type->get_eltype()); 
+      asn1::classdef *cdef = dynamic_cast<asn1::classdef *>(real_type);
+      assert( obj  != NULL);
+      assert( cdef != NULL);
+     
+      cghpph_object obj_gen(m_Gen,m_os,*obj,*cdef);
+      obj_gen.generate_hpp();     
+    } else
+    {
+      std::cerr<<"gen_tplt::OBJECT CLASS not found "<<type->name()<<std::endl;
+    }
+  }
+  protected:
+    std::ostream &m_os;
+    generate_header &m_Gen;
+};
+
+/**
+ *  Default Constructor
+ */
+generate_header::generate_header(asn1::module *n) : generate_cpp(n) 
+{}
+
+generate_header::generate_header(asn1::module *n,asn1::module::modules_type &m) 
+  : generate_cpp(n,m)
+{
+}
+
+/**
+ * Helper function to look for missing prototypes
+ * Most complicated function that needs to be reworked.
+ * n is either an assignment or a typenode
+ */
+void  generate_header::gen_missing(std::ostream &os,asn1::node *n)
+{
+  asn1::node::iterator it;
+  
+  switch (n->type_id()())
+  {
+    case asn1::type::ASN1_SEQUENCE_OF:
+    case asn1::type::ASN1_SET_OF:
+      {
+#ifdef DEBUG
+        GEN_LOG_DEBUG("find sequence of or set of %s\n",n->name().c_str());
+#endif
+        asn1::node *type = n->as_typenode()->get_eltype();
+        assert( (n->identifier() != NULL) && (type != NULL)); 
+        if ( ! type->is_primitive() )
+          type->name(n->identifier()->cpp_name()+std::string("_type"));
+        
+        if (asn1::typeref *tref = type->as_typeref()) 
+        {
+          it = std::find_if(m_module->begin(),
+               m_module->end(),
+               asn1::find_node(tref->get_reference()->name()));
+        } else {
+          it = std::find_if(m_module->begin(),
+               m_module->end(),
+               asn1::find_node(type->name()));
+        }
+        // might be true if it's a private sequence or choice
+        if (it == m_module->end())
+        {
+          os<<"//generate_header::"<<__FUNCTION__;
+          os<<" WARNING Found sequence of or set of:";
+          os<<n->name()<<" private element \n";
+          gen_missing(os,type);
+
+        }
+      
+      } 
+      break;
+    case asn1::type::ASN1_ENUMERATED:
+    {  
+      assert(n->identifier() != NULL);
+      asn1::node * attribute = n->identifier();
+      n->name(attribute->cpp_name()+"_t");     
+      os<<"//gen_missing not nested ENUM "<<n->name();
+      os<<" "<<attribute->name()<<std::endl;
+      
+      gen_enumerated(os,n,attribute->cpp_name()+"_t");
+      
+      os<<";\n";
+      // TODO MAY BE SET it to m_module->end(); 
+      // There is nothing to generated behind enumerated
+      it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+    }
+    break;
+    case asn1::type::ASN1_SEQUENCE:
+    case asn1::type::ASN1_CHOICE:
+    case asn1::type::ASN1_SET:
+      {
+        asn1::constructed *cons = dynamic_cast<asn1::constructed *>(n);
+        asn1::node::iterator lit = cons->begin();
+        assert(0);
+        GEN_LOG_DEBUG("gen_missing::found sequence or choice, set %s\n"
+                     ,n->name().c_str());
+        // Loop over the children and lookup for missing
+        for (; lit != cons->end() ; lit++)
+        {
+          asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+          if ( asn1::typenode *tn = f->get_type()) 
+          {
+                gen_missing(os,tn);
+          } 
+        }
+      }
+      return;
+      break;
+    case asn1::type::ASN1_NULL:
+        return;
+    case asn1::type::ASN1_REFERENCE:
+    {
+      asn1::typeref *tref = n->as_typeref();
+       // Try to check references
+       if (tref->act_parameters() != NULL)
+       {
+         asn1::constructed *params = tref->act_parameters();
+         GEN_LOG_DEBUG("%s have parameters\n",tref->name().c_str());
+         //os<<"//generate_header::"<<__FUNCTION__<<" "<<n->name()<<" Have parameters\n";
+         for( asn1::node::iterator p = params->begin()
+            ; p != params->end() 
+            ; ++p)
+         {
+           GEN_LOG_DEBUG( "%s have parameter : %s\n"
+                        , tref->name().c_str()
+                        , (*p)->name().c_str());
+           it = std::find_if( m_module->begin()
+                            , m_module->end()
+                            , asn1::find_node((*p)->name()));
+                
+           if (it != m_module->end())
+           {
+             // yes in h323
+             //assert(0 && " is this used ?");
+             gen_missing(os,(*it));
+           }
+         }
+       }
+       //
+       if (tref->get_reference())
+       {
+         GEN_LOG_DEBUG( "Ref %s color=%d\n"
+                      , tref->get_reference()->name().c_str()
+                      , n->get_color());
+         if (std::string("TYPE-IDENTIFIER::&Type").compare(tref->get_reference()->name()) == 0)
+         {
+           std::cerr<<"TYPE-IDENTIFIER types shall OCTET STREAMS or open Types. I'm going too far here"<<std::endl;
+           asn1::constraint::iterator c = tref->constraint_begin();
+           if ((*c)->type() == asn1::constraint::EL_TYPE)
+           {
+                    asn1::node *ctype = (*c)->value();
+                    it = std::find_if(m_module->begin(),
+                                    m_module->end(),
+                                    asn1::find_node(ctype->name()));
+           }
+         } else 
+         {
+           it = std::find_if(m_module->begin(),
+                             m_module->end(),
+                             asn1::find_node(tref->get_reference()->name()));
+           if ( it == m_module->end() )
+           {
+             GEN_LOG_WARN( "Reference %s not found use lookup ?\n"
+                         , tref->get_reference()->name().c_str());
+           } else
+           {
+             GEN_LOG_INFO("Reference %s found in current module. node %s\n"
+                    ,tref->get_reference()->name().c_str()
+                    , (*it)->name().c_str());
+           }
+         }
+       } else 
+       {
+         it = std::find_if( m_module->begin()
+                          , m_module->end()
+                          , asn1::find_node(n->name()));
+       }
+    }
+    break;    
+    case asn1::type::ASN1_BOOLEAN: // Do nothing for primary types
+       it = std::find_if( m_module->begin()
+                        , m_module->end()
+                        , asn1::find_node(n->name()));
+       break;    
+    default:
+       //os<<"//generate_header::"<<__FUNCTION__<<" WAR def case Ref "<<n->name()<<" type="<<n->type_id()()<<"not found\n";
+       it = std::find_if( m_module->begin()
+                        , m_module->end()
+                        , asn1::find_node(n->name()));
+  }
+  // Found a element to be generated  
+  if ( it != m_module->end())
+  {
+    asn1::assignment *ltype = (*it)->as_assignment();
+    if ( (ltype->is_generated() != true))
+    {
+      if (ltype->get_color() == asn1::node::CL_GREEN) 
+      {
+        ltype->set_generated(true);
+        GEN_LOG_DEBUG( "do gen missing for %s color=%d\n"
+                     , ltype->name().c_str()
+                     , ltype->get_color());
+        switch(ltype->get_type()->type_id()())
+        {
+          case asn1::type::ASN1_REFERENCE:
+            gen_typeref(os,ltype->get_type()->as_typeref());
+          break;
+          default:
+          {
+            gen_typedef(os,ltype->get_type()->as_typenode());
+          }
+        }
+        ltype->set_color(asn1::node::CL_RED);
+      } else if (ltype->get_color() == asn1::node::CL_ORANGE) 
+      {
+        GEN_LOG_WARN( "gen_missing type %s of color=%d\n"
+                    , ltype->name().c_str()
+                    , ltype->get_color());
+        if (ltype->get_type()->type_id()() == asn1::type::ASN1_SEQUENCE ||
+            ltype->get_type()->type_id()() == asn1::type::ASN1_CHOICE
+        ) 
+        os<<"struct "<<ltype->cpp_name()<<";"<<std::endl;
+        ltype->set_color(asn1::node::CL_REENTRANT);
+      }else 
+      {
+        GEN_LOG_DEBUG( "gen_missing type %s of color=%d\n"
+                     , ltype->name().c_str()
+                     , ltype->get_color());
+        ltype->set_color(asn1::node::CL_REENTRANT);
+      }
+    } 
+  }
+}
+/**
+ * This is only valid for OID where we use 7 bits for each octet.
+ */
+void generate_header::encode_integer(long value,std::vector<unsigned char> &v)
+{
+  long integer = value;
+  long intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+#ifdef DEBUG
+  GEN_LOG_DEBUG("encode %ld\n",value);
+#endif
+  while ( (((integer & mask) == 0) || ((integer & mask) == mask)) 
+          && (intsize > 1)) {
+      intsize--;
+      integer <<=7;
+#ifdef DEBUG
+  GEN_LOG_DEBUG("is: integer = %ld\n",integer);
+#endif
+  }
+#ifdef DEBUG
+  GEN_LOG_DEBUG("integer size = %ld\n",intsize);
+#endif
+  mask = (0x7f << ((intsize-1)*7));
+  long decal = (intsize -1)*7;
+  while ((value & mask  ) != 0) 
+  {
+      long treat = ((value & mask)>>decal);
+      v.push_back (( treat   & 0x7F) |0x80 );
+#ifdef DEBUG
+      std::cout<<"\tpushed :";
+      std::cout<<std::hex<<(int)v.back()<<" integer was:"<<value;
+      std::cout<<" Mask=0x"<<mask<<" treat="<<treat;
+      std::cout<<std::dec<<std::endl;
+#endif
+      value<<=7;
+  }
+  v.back() = v.back() & 0x7F;
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_oid_value(std::ostream &os,asn1::object_identifier *tp)
+{
+#ifdef DEBUG
+  GEN_LOG_DEBUG("node name %s\n",tp->identifier()->name().c_str());
+#endif
+  asn1::object_identifier::arcsType v;
+  tp->arcs(v);
+  os<<"\tinline "<<tp->identifier()->cpp_name()<<"(int s="<<v.size()<<",const char *v=";
+  tp->print_strhex(os,v);
+  os<<")\n\t\t\t : OBJECT_IDENTIFIER(s,v)\n\t{};\n";
+  os<<std::dec;
+}
+
+/**
+ * @brief generate constant definition in header
+ *   TODO : function needs to be reworked. The value information
+ *   should be process not the type !!!
+ *
+ */
+void  generate_header::gen_const(std::ostream &os,asn1::node *n)
+{
+  asn1::typenode *type = n->as_assignment()->get_type();
+  assert(   n->meta_id()() == asn1::meta::VALUE
+         || n->meta_id()() == asn1::meta::VALUESET
+         );
+  switch(type->type_id()())
+  {
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    {
+      os<<"struct "<<type->identifier_cpp_name();
+      os<<"\t : public OBJECT_IDENTIFIER\n{\n";
+      gen_oid_value(os,type->as_object_identifier());
+      os<<"\n};\n";
+    }
+    break;
+    case asn1::type::ASN1_OBJECTSET:
+    {
+      asn1::objectset *objs = dynamic_cast<asn1::objectset *>(type);
+      assert(0); // Is this called ! No only is CPP
+      GEN_LOG_DEBUG("in OBJECTSET type=%s ident name=%s:\n"
+                   ,type->name().c_str()
+                   ,type->identifier_name().c_str());
+    }
+    break;
+    case asn1::type::ASN1_VALUESET:
+    {
+      GEN_LOG_DEBUG("in VALUESET type=%s ident name=%s:\n"
+                   ,type->name().c_str()
+                   ,type->identifier_name().c_str());
+      assert(0); // Is this called ? No Only in CPP
+    }
+    break;
+    case asn1::type::ASN1_INTEGER:
+    {
+      GEN_LOG_DEBUG( "value integer %s\n"
+                   , type->identifier_name().c_str());
+      os<<"#define "<<type->identifier_cpp_name();
+      os<<"\t "<<n->value()->cpp_name()<<"";
+    }
+    break;
+    case asn1::type::ASN1_REFERENCE:
+      GEN_LOG_DEBUG( "value reference %s\n"
+                   , type->identifier_name().c_str());
+      gen_missing(os,type);
+
+      os<<"struct "<<type->identifier()->cpp_name()<<" : public ";
+      os<<type->cpp_name()<<"\n{\n";
+      os<<"\t"<<type->identifier()->cpp_name()<<"();\n";
+      os<<"};";
+    break;
+    default:
+    {
+      asn1::value *v = n->value();
+      GEN_LOG_DEBUG("default case %s\n",type->identifier_name().c_str());
+      assert(v != NULL);
+      switch (v->type)
+      {
+        case asn1::value::VT_INTEGER:
+          os<<"const "<<type->cpp_name()<<" "<<type->identifier_cpp_name()<<"\t\t= ";
+          os<<v->cpp_name();
+          os<<";";
+          break;
+        case asn1::value::VT_COLON:
+        default:
+          ;
+      }
+    }
+  }
+  os<<std::endl;
+
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_bitstring(std::ostream &os,asn1::bit_string &bs )
+{
+  cghpph_bit_string ebs(*this,os,bs);
+  ebs.generate();
+}
+
+
+/**
+ *
+ *
+ */
+void generate_header::gen_enumerated( std::ostream &os
+                                    , asn1::node *type 
+                                    , const std::string &name)
+{
+  std::string indent("");
+  asn1::enumerated *e = dynamic_cast<asn1::enumerated *>(type); 
+  assert( (type->type_id()() == asn1::type::ASN1_ENUMERATED) && (e != NULL));
+  
+  cghpph_enumerated egen(*this,os,*e);
+  egen.generate();
+}
+
+//
+// gen_typeref
+//
+void generate_header::gen_typeref(std::ostream &os,asn1::typeref *type)
+{
+  std::string    type_name;
+  bool           resolved  = false;
+  asn1::node    *real_type = NULL;
+  asn1::typeref *ref       = dynamic_cast<asn1::typeref *>(type); 
+  // Pre requisit 
+  assert( (type != NULL) && (type->type_id()() == asn1::type::ASN1_REFERENCE));
+  assert( type->get_reference() != NULL);
+  assert( ref != NULL);  
+
+  if (with_source_comment()) 
+  {
+    GEN_LOG_DEBUG( "type identifier=%s type_id=%d\n"
+                 , type->identifier_name().c_str()
+                 , type->type_id()());
+    os<<"//generate_header::"<<__FUNCTION__;
+    os<<" "<<type->identifier_name()<<" id="<<type->type_id()()<<" ";
+    
+    if (type->has_constraints())
+    {
+      asn1::constraint *c = *(type->constraint_begin());
+      if (c)
+          os<<c->name();
+    }
+    
+    GEN_LOG_DEBUG("type is %s \n",type->name().c_str());
+    
+    if (type->parameters() != NULL)
+    {
+      GEN_LOG_DEBUG("type %s has parameters \n",type->name().c_str());
+      os<<" parameterized ";
+    }
+    os<<"\n";
+  }
+
+  type_name = type->cpp_name();
+  asn1::resolver resolver(*m_module,m_modules);
+
+  if ( (real_type = ref->get_real_type()) == NULL)
+    real_type = resolver.resolve(*ref);
+
+  if (real_type != NULL && real_type->type_node())
+  {
+    GEN_LOG_DEBUG("gen_typeref found Reference %s  of type : %s color : %d\n"
+                 , real_type->name().c_str()
+                 , real_type->type_node()->name().c_str()
+                 , real_type->get_color()
+                 );
+  } 
+  // TODO Don't understand
+  //  PkIx does not compile. Because the referenced type is not yet declared.
+  //  As I play with typedefs and classes I'm no easely able to figure out what to
+  //  do. An Idea is to generated the referenced type first if it's not generated
+  //    Where is the Color ?
+  gen_missing(os,type);
+  asn1::node *ns = NULL;
+  os<<"//\n//"<<type->identifier_name()<<"\n//\n"; 
+  
+  cghpph_typeref gen_ref(*this,os,*ref);
+  gen_ref.generate();
+}
+
+/**
+ *
+ */ 
+void generate_header::gen_typedef_integer( std::ostream &os
+                                         , asn1::node *type)
+{
+  asn1::integer *i = dynamic_cast<asn1::integer *>(type);
+
+  assert( (type->type_id()() == asn1::type::ASN1_INTEGER) && (i != NULL));
+
+  cghpph_integer igen(*this,os,*i);
+  igen.generate();
+}
+
+//
+//
+void 
+generate_header::gen_sequence_of( std::ostream &os
+                                , asn1::sequence_of  &_seqof)
+{
+  asn1::node     *ns = NULL;
+  asn1::typenode *seqof_type = _seqof.get_eltype();
+  if (seqof_type->get_parent() == NULL)
+  {
+    GEN_LOG_ERROR("gen_sequence_of type->get_parent() is NULL\n");
+  }
+  assert(seqof_type->get_parent() != NULL);
+
+  gen_missing(os,seqof_type);
+  
+  if (type_in_imports(seqof_type,&ns) ) 
+  {
+      cghpph_sequenceof genso(*this,os,_seqof);
+      genso.generate();
+  } else 
+  {
+    switch (seqof_type->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE:
+      {
+        assert(0 && "gen_seq_of type should be reference not sequence");
+      }
+      break;
+      case asn1::type::ASN1_CHOICE:
+      {
+        assert(0 && "gen_seq_of type should be reference not choice");
+      }
+      break;
+      case asn1::type::ASN1_ENUMERATED:
+      {
+        assert(0 && "gen_seq_of type should be reference not enumr");
+      }
+      break;
+      default:
+      cghpph_sequenceof genso(*this,os,_seqof);
+      genso.generate();
+    }
+  }
+}
+
+//
+//
+void 
+generate_header::gen_set_of(std::ostream &os,asn1::set_of  &_seqof) 
+{
+  asn1::node     *ns = NULL;
+  asn1::typenode *seqof_type = _seqof.get_eltype();
+  
+  gen_missing(os,seqof_type);
+  std::cout<<"gen_set_of "<<_seqof.identifier_cpp_name()<<" "<<seqof_type->cpp_name()<<std::endl;
+  if (type_in_imports(seqof_type,&ns) ) 
+  {
+      cghpph_setof gensetof(*this,os,_seqof);
+      gensetof.generate();
+  } else 
+  {
+    switch (seqof_type->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE:
+      {
+        assert(0 && "gen_set_of type should be reference not sequence");
+      }
+      break;
+      case asn1::type::ASN1_CHOICE:
+      {
+        assert(0 && "gen_set_of type should be reference not choice");
+      }
+      break;
+      case asn1::type::ASN1_ENUMERATED:
+      {
+        assert(0 && "gen_set_of type should be reference not enum");
+      }
+      break;
+      default:
+        cghpph_setof gensetof(*this,os,_seqof);
+        gensetof.generate();
+    }
+  }
+}
+
+
+//
+//
+//
+void generate_header::gen_typedef( std::ostream &os
+                                 , asn1::typenode *type)
+{
+  assert(type != NULL);
+  // Text cosmetic
+  GEN_LOG_DEBUG( "type %s ident=%s\n"
+               , type->name().c_str()
+               , type->identifier_name().c_str());
+  if (with_source_comment() ) 
+  {
+    os<<"// gen_typedef : "<<type->identifier_name();
+    os<<" id="<<type->type_id()()<<" color="<<type->get_color();
+    if (type->has_constraints())
+    {
+      asn1::constraint *c = *(type->constraint_begin());
+      if (c)
+        os <<c->name();
+
+    }
+    if ( type->identifier() && type->identifier()->parameters())
+    {
+      os<<" parameterized "; 
+    }
+    os<<"\n";
+  }
+  // start the real work 
+  if (type != NULL)
+    switch (type->type_id()())
+    {
+      case asn1::type::ASN1_REFERENCE:
+      {
+        GEN_LOG_ERROR("type %s is reference\n",type->name().c_str());
+        assert(0);
+      }
+      break;
+      case asn1::type::ASN1_INTEGER:
+        {
+          gen_typedef_integer(os,type);
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          asn1::sequence *seq = dynamic_cast<asn1::sequence *>(type);
+          if (with_source_comment())
+          {
+            os<<"// start SEQUENCE GENERATION ";
+            os<<type->identifier()->name()<<"\n";
+          }
+          std::string scope("");
+          // Genenerate missing before generating structure
+          asn1::node::iterator lit = seq->begin();
+          for (; lit != seq->end() ; ++lit)
+          {
+            asn1::field    *f = dynamic_cast<asn1::field *>(*lit);
+            asn1::typenode *attr_type = f->get_type() ;
+            if ( attr_type != NULL)
+            {
+              gen_missing(os,attr_type);
+            } else if (asn1::extension_field *ef = dynamic_cast<asn1::extension_field *>(f) )
+            {
+                os<<"// SEQUENCE GENERATION has extension field"<<std::endl;
+            } else
+            {
+              if (with_source_comment())
+              {
+                os<<"// SEQUENCE GENERATION ERROR on attribute ";
+                os<<(*lit)->name()<<" Does not have type node cannot call gen_missing"<<std::endl;
+            
+              }
+            }
+          }
+          gen_seq(os,scope,seq);
+          os<<";\n";
+          if (with_source_comment())
+            os<<"// end SEQUENCE GENERATION "<<type->identifier()->name()<<"\n";
+          os<<"\n"<<std::endl;
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE_OF:
+        gen_sequence_of(os,dynamic_cast<asn1::sequence_of &>(*type));
+        return ;
+        break;
+      case asn1::type::ASN1_SET:
+        {
+          asn1::set *col = dynamic_cast<asn1::set *>(type);
+          asn1::node::iterator lit = col->begin();
+          for (; lit != col->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( asn1::typenode *tn = f->get_type() ) {
+                  gen_missing(os,tn);
+            }
+          }
+          gen_set(os,type);
+          os<<";\n";
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SET_OF:
+        {
+          gen_set_of(os,dynamic_cast<asn1::set_of &>(*type));
+          return;
+        }
+        break;
+      case asn1::type::ASN1_CHOICE:
+        {
+          asn1::choice *choix = dynamic_cast<asn1::choice *>(type);
+          asn1::node::iterator lit = choix->begin();
+          for (; lit != choix->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( asn1::typenode *tn = f->get_type() ) {
+              gen_missing(os,tn);
+            }
+          }
+          gen_choice(os,choix);
+          os<<";\n";
+          return;
+        }
+        break;
+      case asn1::type::ASN1_ENUMERATED:
+        {
+          gen_enumerated(os,(type),type->identifier_cpp_name());
+          os<<";\n";
+          return;
+        }
+        break;
+      ;
+      case asn1::type::ASN1_BIT_STRING:
+      {
+             asn1::bit_string *bs = dynamic_cast<asn1::bit_string *>(type);
+        assert(bs != NULL);
+             gen_bitstring(os,*bs);    
+        return ;
+      }
+      break;
+      case asn1::type::ASN1_OCTET_STRING:
+      {
+        asn1::octet_string *o = dynamic_cast<asn1::octet_string *>(type);
+
+        assert( (type->type_id()() == asn1::type::ASN1_OCTET_STRING)
+                && (o != NULL));
+
+        cghpph_octet_string ogen(*this,os,*o);
+        ogen.generate();
+        return ;
+      }
+      case asn1::type::ASN1_BOOLEAN:
+      {
+        asn1::boolean *o = dynamic_cast<asn1::boolean *>(type);
+
+        assert( (type->type_id()() == asn1::type::ASN1_BOOLEAN)
+                && (o != NULL));
+
+        cghpph_boolean ogen(*this,os,*o);
+        ogen.generate();
+        return ;
+      }
+      
+      case asn1::type::ASN1_NULL:
+      {
+        asn1::primitive *o = dynamic_cast<asn1::primitive *>(type);
+        GEN_LOG_ERROR("type %s NULL is reference\n",type->name().c_str());
+
+        assert( (o != NULL)); 
+        std::cerr<<__FUNCTION__<<" GENERATE "<<o->identifier()->cpp_name();
+        std::cerr<<" type::ASN1_NULL"<<std::endl;
+        cghpph_primitive pgen(*this,os,*o);
+        pgen.generate();
+        GEN_LOG_ERROR("type %s end  is reference\n",type->name().c_str());
+        return ;
+      }
+
+
+      case asn1::type::ASN1_STRING_BMPString:
+      case asn1::type::ASN1_STRING_IA5String:
+      case asn1::type::ASN1_STRING_VisibleString:
+      case asn1::type::ASN1_STRING_GraphicString:
+      case asn1::type::ASN1_STRING_ISO646String:    /* aka VisibleString */
+      case asn1::type::ASN1_STRING_PrintableString:
+      case asn1::type::ASN1_STRING_NumericString:
+      case asn1::type::ASN1_STRING_TeletexString:
+      {
+        asn1::primitive *o = dynamic_cast<asn1::primitive *>(type);
+
+        assert( (o != NULL)); 
+
+        cghpph_string ogen(*this,os,*o);
+        ogen.generate();
+        return ;
+      }
+
+      break;
+      case asn1::type::ASN1_OBJECT_IDENTIFIER:
+      {
+        asn1::object_identifier *o = 
+            dynamic_cast<asn1::object_identifier *>(type);
+
+        assert( (o != NULL)); 
+
+        cghpph_oid ogen(*this,os,*o);
+        ogen.generate();
+        return ;
+      }
+
+      break;
+      case asn1::type::ASN1_STRING:
+      case asn1::type::ASN1_STRING_UniversalString:
+      case asn1::type::ASN1_STRING_UTF8String  :
+      case asn1::type::ASN1_STRING_GeneralString:
+      case asn1::type::ASN1_STRING_T61String:
+      case asn1::type::ASN1_STRING_VideotexString:
+      case asn1::type::ASN1_STRING_ObjectDescriptor:
+      //case asn1::type::ASN1_UNIVERSAL:
+      default:
+        {
+          std::string cppType;
+          if  ( ! type2cppstring(type,cppType))
+          {     
+            std::cerr<<"Failed get cpp type for "<<type->name()<<std::endl;
+            assert(0);
+          }
+           gen_missing(os,type);
+           asn1::node *ns = NULL;
+           os<<"//\n// gen_typdef default case "<<type->identifier_name()<<"\n//\n";
+           os<<"typedef ";
+           if (type_in_imports(type,&ns) ) {
+              os<<"\t"<<ns->cpp_name()<<"::";
+             os<<type->cpp_name()<<" ";
+            } else {
+             if (type->tagged())
+              {
+                os<<"asn1::types::";
+                if (type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+                {
+                  os<<"IMPLICIT<";
+                } else
+                  os<<"EXPLICIT<";
+                os<<type->tag().m_class<<","<<type->tag().m_value<<",";
+               if (type_in_imports(type,&ns) ) {
+                os<<"\t"<<ns->cpp_name()<<"::";
+                os<<type->cpp_name()<<"> ";
+               } else
+                 os<<" /**/ "<<type->cpp_name()<<"> ";
+             } else
+             {
+               if (with_source_comment())
+                 os<<" /*gtdef*/ ";
+               os<<cppType<<" ";
+             }
+           }
+        }
+    }
+  os<<"\t\t"<<type->identifier_cpp_name()<<";\n\n";
+  
+}
+
+/**
+ *
+ */
+void generate_header::gen_seq( std::ostream &os
+                             , std::string &scope
+                             , asn1::sequence *type)
+{
+  asn1::node * ident = type->identifier();
+  
+  assert(type->type_id()() == asn1::type::ASN1_SEQUENCE);
+  
+  // New way to handle and isolate sequence code generation 
+  asn1::sequence *seq = dynamic_cast<asn1::sequence *>(type);
+  assert(seq != NULL);
+  
+  cghpph_sequence seq_gen(*this,os,*seq);
+  seq_gen.generate();    
+}
+
+
+//
+//
+//
+void generate_header::gen_template_params(std::ostream &os,asn1::node *_params)
+{
+  asn1::constructed *params = dynamic_cast<asn1::constructed *>(_params);
+    asn1::node::node_list nl;
+
+    os<<"<";
+    for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+    {
+      if (nl.size()>0)
+      {
+        asn1::node::iterator it = std::find_if(nl.begin()
+                                   , nl.end()
+                                   , asn1::find_node((*p)->name()));
+        if (it != nl.end() )
+        {
+          //
+        } else {
+         if (p != params->begin()) os<<",";
+         os<<" "<<(*p)->cpp_name();
+         nl.push_back(*p);       
+        }
+      } else {
+        if (p != params->begin()) os<<",";
+        os<<" "<<(*p)->cpp_name();
+        nl.push_back(*p);
+      }
+    }
+   os<<"> ";
+}    
+//
+//
+//
+void generate_header::gen_template_signature( std::ostream &os
+                                            , asn1::node *_params)
+{
+  asn1::constructed *params = dynamic_cast<asn1::constructed *>(_params);
+  asn1::node::node_list nl;
+
+  assert(params != NULL);
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin()
+                                   ,nl.end()
+                                   ,asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" typename "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" typename "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+ os<<"> ";
+}    
+
+/**
+ *
+ *
+ */ 
+void generate_header::struct_name(asn1::node *type,std::string &structName)
+{
+  if (type->identifier() == NULL)  
+  {
+    structName = type->cpp_name();
+  } else
+  {
+    if (type->is_private())
+    {
+      std::cerr<<"struct_name : "<<type->identifier()->cpp_name()<<std::endl;
+      GEN_LOG_ERROR("struct_name %s \n",type->identifier()->cpp_name().c_str());
+      assert(type->identifier()->get_parent() != NULL);
+      private_attribute_type(type->identifier(),structName);
+    } else
+      structName = type->identifier()->cpp_name();
+  }
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_choice( std::ostream &os
+                                , asn1::choice *type
+                                , asn1::node *pparams)
+{
+  std::string scope("");
+  std::string structName;
+  asn1::node::iterator it;
+  
+  assert(type != NULL);
+  assert(type->get_parent() != NULL);  
+  struct_name(type,structName);
+  
+  m_Stack.push_back(structName);
+  
+  cghpph_choice choice_gen(*this,os,*type);
+  choice_gen.generate();
+  m_Stack.pop_back();
+}
+
+/**
+ * TODO: Remove
+ */ 
+void 
+generate_header::gen_composite_attribute_ref(std::ostream &os
+                            , std::string &scope
+                            , asn1::field *attribute
+                            , asn1::node  *params)
+{
+  generate_cpp::gen_composite_attribute_ref(os,scope,attribute,params);    
+}
+
+/**
+ *
+ * What means attributes ?
+ * TODO 2017/05/17 review this function it's too complicated.
+ *
+ */ 
+void 
+generate_header::gen_composite_attribute(std::ostream &os
+                            , std::string &scope
+                        , asn1::field &attribute
+                        , asn1::node *params
+                        , bool attributes)
+{
+    asn1::typenode *attr_type = attribute.get_type();
+    if (attr_type != NULL)
+    {
+      std::string structName = attribute.cpp_name() +"_t";
+      private_attribute_type(&attribute,structName);
+      switch (attr_type->type_id()())
+      {
+        case asn1::type::ASN1_ENUMERATED:
+          {
+            if (attributes) 
+            {
+              if (attribute.flags().is_optional() )
+              {
+                os<<"\n\tASN1_ATTRIBUTE_OPTIONAL( struct ";
+                os<<structName<<" )\t";
+                os<<"\t\t"<<attribute.cpp_name()<<";\n";
+              }else 
+              {
+                os<<"\t"<<structName<<"\t";
+                os <<attribute.cpp_name()<<";"<<std::endl;
+              }
+            } else {
+              os<<""<<std::endl;
+            }
+          } 
+          break;
+        case asn1::type::ASN1_SET:
+          {
+              attr_type->name(structName);
+              gen_set(os,attr_type);
+              if (attributes)
+              {
+                os<<"\t\t"<<attribute.cpp_name()<<";\n";
+              } else {
+                os<<"\t;\n";
+              }
+          }
+          break;
+        case asn1::type::ASN1_CHOICE:
+          {
+              attr_type->name(structName);
+              if (attributes) 
+              {
+                if (attribute.flags().is_optional() )
+                {
+                  os<<"\n\tASN1_ATTRIBUTE_OPTIONAL( struct ";
+                  os<<attr_type->cpp_name()<<" )\t";
+                  os<<"\t\t"<<attribute.cpp_name()<<";\n";
+                }else 
+                {
+                  os<<"\t"<<structName;
+                  os<<"\t\t"<<attribute.cpp_name()<<";\n";
+                }
+              } else
+              {
+              }
+          }
+          break;
+        case asn1::type::ASN1_SEQUENCE:
+          {
+              std::string scope("\t");
+              attr_type->name(structName);
+              if ( ! attributes) 
+              {
+                return;
+              }
+              if (attribute.flags().is_optional() )
+              {
+                os<<";\n\tASN1_ATTRIBUTE_OPTIONAL( struct ";
+                os<<attr_type->cpp_name()<<" )\t";
+                os<<"\t\t"<<attribute.cpp_name()<<";\n";
+              }else
+              {
+                os<<"\t"<<structName;
+                os<<"\t\t"<<attribute.cpp_name()<<";\n";
+              }
+          }
+          break;
+        case asn1::type::ASN1_SELECTION:
+          {
+            assert(0 && " Selection should have been solved in optimizer");
+            if ( ! attributes) 
+              return;
+              os<<"\t\tINTEGER "<<attribute.cpp_name()<<"; //SEL ?\n";
+          }
+          break;
+        case asn1::type::ASN1_SET_OF:
+        case asn1::type::ASN1_SEQUENCE_OF:
+          {
+            asn1::typenode *type    = attribute.get_type();
+            asn1::node *subtype     = type->get_eltype();
+            if (type->has_constraints())
+            {
+              os<<"//"<<__FUNCTION__;
+              os<<" I have constraints type SET_OF or SEQUENCE_OF\n";
+            }
+            switch (subtype->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+                subtype->name(attribute.cpp_name()+std::string("_type"));
+                if ( ! attributes) 
+                {
+                  return;
+                }
+                if (attribute.flags().is_optional() ) {
+                      os<<"\tASN1_ATTRIBUTE_OPTIONAL(";
+                }
+                os<<type->name()<<"<"<<std::string( attribute.cpp_name()+"_type")<<">";
+                if (attribute.flags().is_optional() ) {
+                      os<<") ";
+                }
+                break;
+                // Missing SET
+              case asn1::type::ASN1_CHOICE:
+                subtype->name(structName);
+                if ( ! attributes) 
+                {
+                  return;
+                }
+                if (attribute.flags().is_optional() )
+                {
+                      os<<"\tASN1_ATTRIBUTE_OPTIONAL(";
+                }
+                // TOBE CONSISTENT, this should be _type
+                os<<type->name()<<"<";
+                os<<std::string( attribute.cpp_name()+"_t")<<">";
+                if (attribute.flags().is_optional() )
+                {
+                      os<<") ";
+                }
+                break;
+              default:
+                asn1::node *ns;
+                if ( ! attributes) 
+                {
+                  return;
+                }
+                if (attribute.flags().is_optional() )
+                {
+                      os<<"\tASN1_ATTRIBUTE_OPTIONAL(";
+                }
+                if (type_in_imports(subtype,&ns) )
+                {
+                  os<<"\t"<<type->name()<<"<";
+                  os<<ns->cpp_name()<<"::"<<subtype->cpp_name()<<">";
+                } else
+                {
+                  if (asn1::typeref *stref = subtype->as_typeref()) 
+                  {
+                    os<<"\t"<<type->name()<<"</*r*/"<<stref->get_reference()->cpp_name()<<">";
+                  } else {
+                    os<<"\t"<<type->name()<<"</*nr*/"<<subtype->cpp_name()<<">";
+                  }
+                }
+                if (attribute.flags().is_optional() ) {
+                      os<<") ";
+                }
+            } // end switch
+            // common to all switch
+            os<<"\t"<<attribute.cpp_name()<<";\n";
+          }
+          break;
+        case asn1::type::ASN1_REFERENCE:
+          {
+            asn1::typeref *tref = attr_type->as_typeref();
+            if ( ! attributes) 
+              return;
+            os<<"\t";
+            if (tref->get_reference())
+            {
+              // New way to handle reference
+              gen_composite_attribute_ref(os,scope,&attribute,params);
+            } else 
+            {
+              assert(0);
+            }
+            os<<"\t"<<attribute.cpp_name()<<";";
+            os<<std::endl;
+          }
+          break;
+        default:
+          {
+            asn1::node *ns = NULL;
+            if ( ! attributes) 
+              return;
+            // Imported attribute
+            if (type_in_imports(attr_type,&ns) )
+            {
+              if ( attribute.flags().is_default() )
+              {
+                os<<scope<<"\t"<<ns->cpp_name()<<"::";
+                os<<attr_type->cpp_name()<<" ";
+              } else if ( attribute.flags().is_optional() ) {
+                os<<scope<<"\tASN1_ATTRIBUTE_OPTIONAL("<<ns->cpp_name()<<"::";
+                os<<attr_type->cpp_name()<<") ";
+              } else 
+              {
+                os<<scope<<"\t"<<ns->cpp_name()<<"::";
+                os<<attr_type->cpp_name()<<" ";
+              }
+            } else 
+            {
+              // Local attribute
+              //std::cout<<"HERE ?"<<std::endl;
+              std::string cppType;
+              if (! type2cppstring(attr_type,cppType))
+              {
+                std::cerr<<"Failed convert type ("<<attr_type->name();
+                os<<") 2cpp string "<<std::endl;
+                assert(0);
+              }
+              if ( attribute.flags().is_default() )
+              {
+                os<<scope<<"\t"<<cppType<<" ";
+              } else if ( attribute.flags().is_optional() )
+              {
+                os<<scope<<"\tASN1_ATTRIBUTE_OPTIONAL("<<cppType<<") ";
+              }
+              else {
+                os<<scope<<"\t"<<cppType<<" ";
+              }
+            }
+            os<<"\t"<<attribute.cpp_name()<<";";
+            if (with_source_comment())
+            {
+              if (attribute.get_type()->has_constraints())
+              {
+                os<<"\t//"<<__FUNCTION__<<" default case I have constraints";
+              } else
+              {
+                os<<" //"<<__FUNCTION__<<" ";
+                os<<attr_type->type_id()()<<" default without constraints";
+              }
+            }
+            os<<"\n";
+          }
+      }
+    }
+}
+
+
+/**
+ *
+ */
+void generate_header::gen_set(std::ostream &os,asn1::node *type)
+{
+  std::string scope("");
+  std::string structName;
+  asn1::node *n = type->identifier();
+
+  // New way to handle and isolate sequence code generation 
+  asn1::set *set = dynamic_cast<asn1::set *>(type);
+  assert(set != NULL);
+  
+  cghpph_set set_gen(*this,os,*set);
+  set_gen.generate();
+}
+
+/**
+ *
+ */ 
+class genh_oc_tplt : public node_visitor<genh_oc_tplt>
+{
+  protected:
+    asn1::classdef  &m_classdef;
+    generate_header &m_gen;
+    bool             m_param;
+    std::ostringstream m_result;
+    long             m_count;
+  public:
+    genh_oc_tplt( generate_header &_gen
+                , asn1::classdef &_cdef
+                , bool is_param=false)
+     : m_classdef(_cdef),m_gen(_gen) , m_count(0), m_param(is_param)
+    { m_result.str(""); };
+
+   inline std::string result() { return m_result.str(); } ;
+
+#define ASN1_CLASSFIELD_TYPE(cf,code) \
+   void visit_##cf(asn1::cf *field) code
+
+ASN1_CLASSFIELD_TYPE(classfield_tf,{
+    if (m_count++)
+      m_result<<",";
+    if (! m_param)
+      m_result<<"typename ";
+    std::string fieldname = field->cpp_name();
+    fieldname[0] = '_';
+    m_result<<fieldname;
+    })
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,{
+    })
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,{})
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,{})
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,{})
+ASN1_CLASSFIELD_TYPE(classfield_of,{})
+ASN1_CLASSFIELD_TYPE(classfield_osf,{})
+#undef ASN1_CLASSFIELD_TYPE
+};
+
+/**
+ *
+ */
+void 
+generate_header::gen_object_class_tplt(std::ostream &os,asn1::classdef *type)
+{
+  std::list<std::string> l;
+  genh_oc_tplt gt(*this,*type);
+  os<<"template<";
+  for ( asn1::node::iterator it = type->begin()
+      ; it != type->end(); ++it)
+  {
+    gt.visit(*it);
+  }
+  os<<gt.result();
+  os<<", int _uuid = 0 /*uuid */";
+  os<<">\n";
+}
+
+void 
+generate_header::gen_object_class_tplt_params(std::ostream &os,asn1::classdef *type)
+{
+  assert(type != NULL);
+  asn1::node::iterator it = type->begin();
+  std::list<std::string> l;
+  
+  for ( ; it != type->end(); ++it)
+  {
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    /* Type  Field */
+    if (  (*it)->type_id()() == asn1::type::ASN1_CLASSFIELD_TF)
+    {
+      l.push_back(fieldname);
+    }
+  }
+
+  if (l.size()>0)
+  {
+    os<<"<";
+    for ( std::list<std::string>::const_iterator it = l.begin()
+        ; it != l.end()
+        ; ++it)
+    {
+      if (it != l.begin()) {
+        os<<",";
+      }
+      os<<" "<<(*it)<<"";
+    }
+    os<<",  _uuid  /*uuid */";
+    os<<">";
+  }
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_object_class_missing(std::ostream &os,asn1::classdef *type)
+{
+  asn1::node::iterator it = type->begin();
+  // cosntructors
+
+  // public methods 
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::classfield *ltype = dynamic_cast<asn1::classfield *>(*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    os<<"//"<<(*it)->cpp_name()<<" type_id="<<(*it)->type_id()();
+    //<<std::endl;
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_FTVF:  /* Fixed Type Value Field       */
+        os<<std::endl;
+        // call missing here
+        gen_missing(os,ltype->get_type());
+        break;
+      case asn1::type::ASN1_CLASSFIELD_TF:    /* Type Field                   */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVF:  /* Variable Type Value Field    */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_FTVSF: /* Fixed Type Value Set Field   */
+        os<<std::endl;
+        gen_missing(os,ltype->get_type());
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVSF: /* Variable Type Value Set Field*/
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OF:    /* Object Field                 */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OSF:   /* Object Set Field             */
+        os<<std::endl;
+        break;
+      break;
+      default:
+        os<<std::endl;
+    };
+  }
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_object_class(std::ostream &os,asn1::assignment *n)
+{
+  asn1::classdef *type = dynamic_cast<asn1::classdef *>(n->get_type());
+  assert(type != NULL);
+  cghpph_classdef cdef(*this,os,*type);
+  cdef.generate();
+}
+
+/**
+ *
+ *
+ */
+void generate_header::gen_object(std::ostream &os,asn1::assignment *n)
+{
+  asn1::typenode *type = n->get_type();
+  
+  os<<"// generate_header::"<<__FUNCTION__<<" "<<n->name()<<"\n";
+  os.flush();
+  
+  assert(type->type_id()() == asn1::type::ASN1_REFERENCE);
+  asn1::node *real_type = 
+    m_resolver.resolve(dynamic_cast<asn1::typeref &>(*type));
+  if (real_type != NULL)
+  {
+    asn1::object   *obj  = dynamic_cast<asn1::object *>(type->get_eltype()); 
+    asn1::classdef *cdef = dynamic_cast<asn1::classdef *>(real_type);
+    assert( obj  != NULL);
+    assert( cdef != NULL);
+    // Check Done at optimization level
+    cghpph_object obj_gen(*this,os,*obj,*cdef);
+    obj_gen.generate();     
+  } else
+  {
+    std::cerr<<"OBJECT CLASS not found "<<type->name()<<std::endl;
+    os<<"// object class not found  "<<n->name()<<"\n";
+  }
+}
+
+
+
+
+
+void 
+generate_header::gen_include(std::string fname,asn1::assignment *type)
+{
+    struct stat st;
+    char *cd = getcwd(NULL,0);
+    std::string cdir( cd);
+
+
+    std::fstream inc;
+    std::string module_path = cdir+"/include/"+m_module->cpp_name();
+    std::string f;
+    if (type->meta_id()() == asn1::meta::OBJECTCLASS ) {
+      f = "./include/"+m_module->cpp_name()+"/I"+fname;
+    } else {
+      f = "./include/"+m_module->cpp_name()+"/"+fname;
+    }
+    
+    if (stat("./include",&st) == -1) {
+#ifdef WIN32
+      mkdir("include");
+#else
+      mkdir("include",0777);
+#endif
+    }
+    
+    if (stat(module_path.c_str(),&st) == -1) {
+#ifdef WIN32
+      mkdir(module_path.c_str());
+#else
+      mkdir(module_path.c_str(),0777);
+#endif
+    }
+    
+    inc.open(f.c_str(),std::fstream::out);
+    inc<<"#ifndef __"<<m_module->cpp_name()<<"_H__"<<std::endl;
+    inc<<"#define __"<<m_module->cpp_name()<<"_H__"<<std::endl;
+    inc<<"#include \""<<m_module->cpp_name()<<".h\""<<std::endl;
+    inc<<"#endif"<<std::endl;
+    inc.close();
+    delete cd;
+}
+
+class do_genh_assignment : public assignment_visitor<do_genh_assignment>
+{
+  protected:
+    generate_header &m_gen;
+    std::ostream    &m_os;
+    std::fstream    &m_log;
+    std::vector<asn1::node *> &m_objects;
+    std::string path ;
+  public:
+    do_genh_assignment( generate_header &_h
+                      , std::ostream &os
+                      , std::vector<asn1::node *> &_objects
+     ) 
+      : m_os(os),m_gen(_h),m_log(_h.logger()) ,m_objects(_objects) {};
+    // Main processing function per assignment
+    void operator ()(asn1::node *n)
+    {
+      asn1::typenode *type = n->as_assignment()->get_type();
+      path = n->cpp_name()+".h";
+      GEN_LOG_DEBUG( "Process  item=%s meta=%d\n"
+                 , n->name().c_str()
+                 , n->meta_id()());
+      if ( ! type)
+        return;
+      if ( n->is_generated())
+      {
+        GEN_LOG_DEBUG("%s already generated\n",n->name().c_str());
+        return;
+      }
+      visit(n->as_assignment());
+      n->set_color(asn1::node::CL_RED);
+    }
+#define ASSIGNMENT(Ty,Code) \
+    void visit_##Ty(asn1::Ty##_assignment *a) Code
+
+    ASSIGNMENT(typeref,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is TYPEREF parameterized: %d\n"
+                  , a->name().c_str(),params);
+      m_gen.gen_include(path,a);
+      m_gen.gen_typeref(m_os,a->get_type()->as_typeref());
+    })
+    ASSIGNMENT(type,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is TYPE parameterized: %d\n"
+                  , a->name().c_str(),params);
+      m_gen.gen_include(path,a);
+      m_gen.gen_typedef(m_os,a->get_type());
+    })
+    ASSIGNMENT(value,{
+      GEN_LOG_DEBUG("meta of %s is VALUE\n",a->name().c_str());
+      m_gen.gen_const(m_os,a);
+    })
+    ASSIGNMENT(valueset,{
+      GEN_LOG_DEBUG( "meta of %s is VALUESET do nothing ?\n"
+                , a->name().c_str());
+    })
+    ASSIGNMENT(object,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "meta of %s is OBJECT parameterized: %d\n"
+                  , a->name().c_str(),params);
+      m_gen.gen_object(m_os,a);
+      m_objects.push_back(a);
+    })
+    ASSIGNMENT(objectclass,{
+      int params = (a->parameters() != NULL)?1:0;
+      GEN_LOG_DEBUG( "meta of %s is OBJECT CLASS parameterized: %d\n"
+                , a->name().c_str(),params);
+      m_gen.gen_object_class(m_os,a);
+    })
+    ASSIGNMENT(objectset,{})
+    ASSIGNMENT(objectfield,{})
+
+};
+/**
+ *
+ */
+void generate_header::gen_module(std::ostream &os,asn1::module *n)
+{
+  asn1::import_list *imports = n->imports();
+  os<<"#ifndef "<<n->cpp_name()<<"_H__"<<std::endl;
+  os<<"#define "<<n->cpp_name()<<"_H__"<<std::endl;
+  os<<"#include \"rtasn1/asn1.h\"\n"<<std::endl;
+  // Add include for external dependencies
+  if (imports != NULL)
+  {
+    for (asn1::node::iterator it = imports->begin(); it!= imports->end(); it++)
+    {
+      asn1::import *import = dynamic_cast<asn1::import *>( *it);   
+      if (import)
+      {
+        cghpph_import imp_gen(*this,os,*import);
+        imp_gen.generate();
+      }
+    }
+  }
+
+  os<<"using namespace asn1;\n"<<std::endl;
+  os<<"namespace "<<n->cpp_name()<<" {\n"<<std::endl;
+  
+  n->sort_childs();
+  
+  do_genh_assignment dogen(*this,os,m_objects);
+  std::for_each( n->begin()
+             , n->end()
+             , dogen
+            );
+
+  os<<"}\n\n"<<std::endl;
+  os<<"#endif "<<std::endl;
+  os<<"/** "<<std::endl;
+  os<<" * vim: sw=2 ts=2:"<<std::endl;
+  os<<" */"<<std::endl;
+
+  m_template_codec.erase(m_template_codec.begin(),m_template_codec.end());
+  /**
+   * Alright gen template code for 
+   * objects in a separated file
+   */ 
+  if (m_module->has_objects())
+  { 
+    std::string fname = m_module->cpp_name() + ".hpp";
+    std::fstream ost;
+    ost.open(fname.c_str(),std::fstream::out);
+    if (!m_module->name().compare("Remote-Operations-Useful-Definitions"))
+    {
+      ost<<"// Dont generate anything\n";
+    } else
+    {
+      std::for_each( m_objects.begin()
+                 , m_objects.end()
+                 , gen_tplt(ost,*this)
+                );
+    }
+    ost.close();
+  }
+}
+
+
+/**
+* vim:et:sw=2:ts=2
+*/
diff --git a/libgen/asn1_gen_hpp.h b/libgen/asn1_gen_hpp.h
new file mode 100644 (file)
index 0000000..2755032
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef GEN_HEADER_H__
+#define GEN_HEADER_H__
+#include <iostream>
+#include <algorithm>
+
+
+/**
+ *
+ */
+class generate_header : public generate_cpp
+{
+  public:
+    
+    typedef std::vector<asn1::node *> template_list_type;
+
+    generate_header(asn1::module *n); 
+    
+    generate_header(asn1::module *n,asn1::module::modules_type &m); 
+   
+    /**
+     * This is a recursive function
+     *   In no nested context, it generates all private classes  
+     *
+     */ 
+    void gen_missing(std::ostream &os,asn1::node *n) ;
+
+    void encode_integer(long value,std::vector<unsigned char> &v);
+
+    void gen_oid_value(std::ostream &os,asn1::object_identifier *n);
+    /**
+     *
+     *
+     */
+    void gen_const(std::ostream &os,asn1::node *n);
+    /**
+     *
+     * 
+     */ 
+    void gen_enumerated(std::ostream &os,asn1::node *n ,const std::string &name);
+    /**
+     * 
+     */ 
+    void gen_bitstring(std::ostream &os,asn1::bit_string &type );
+    //
+    // called for ntype ::= SEQUENCE OF 
+    virtual void gen_sequence_of(std::ostream &os,asn1::sequence_of  &) ;
+    // called for ntype ::= SEQUENCE OF 
+    virtual void gen_set_of(std::ostream &os,asn1::set_of  &) ;
+    //
+    void gen_typedef(std::ostream &os,asn1::typenode *n);
+    
+    void gen_typedef_integer(std::ostream &os,asn1::node *n);
+    
+    void gen_typeref(std::ostream &os,asn1::typeref *n);
+    
+    /**
+     *
+     */
+    void gen_seq(std::ostream &os,std::string &scope,asn1::sequence *n);
+    
+    void gen_choice(std::ostream &os,asn1::choice *n,asn1::node *params = NULL);
+    /**
+     *
+     * attributes flags is for choice case. We only generate internal structures in that case.
+     */
+    void gen_composite_attribute( std::ostream &os
+                                , std::string &scope
+                                , asn1::field &attribute
+                                , asn1::node *params = NULL,bool attributes = true);
+    void gen_composite_attribute_ref(std::ostream &os
+                                , std::string &scope
+                                , asn1::field *attribute
+                                , asn1::node *params = NULL);
+    void gen_template_params(std::ostream &os,asn1::node *params);
+    void gen_template_signature(std::ostream &os,asn1::node *params);
+    /**
+     *
+     */
+    void gen_set(std::ostream &os,asn1::node *n);
+  
+    /*
+     * Ros generation Code
+     */
+    void gen_object_class(std::ostream &os,asn1::assignment *n); 
+    void gen_object_class_missing(std::ostream &os,asn1::classdef *n);
+    void gen_object_class_tplt(std::ostream &os,asn1::classdef *n); 
+    void gen_object_class_tplt_params(std::ostream &os,asn1::classdef *n); 
+  
+    void gen_object(std::ostream &os,asn1::assignment *n); 
+    /**
+     *
+     */
+    void gen_module(std::ostream &os,asn1::module *n);
+    void gen_include(std::string fname,asn1::assignment *type);
+    /**
+     * Helper method to compute structName
+     */
+    void struct_name(asn1::node *type,std::string &sn);
+
+    /**
+     * TODO Must be removed after migration with EXPLICT /IMPLICIT
+     *
+     */
+    template_list_type &get_template_list() 
+    {
+      return m_template_codec;
+    }
+  protected:
+    std::fstream              m_tplt_os;
+    std::vector<std::string>  m_Stack;
+    std::vector<asn1::node *> m_template_codec;
+    std::vector<asn1::node *> m_objects;
+};
+/**
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libgen/asn1_gen_optimizer.cpp b/libgen/asn1_gen_optimizer.cpp
new file mode 100644 (file)
index 0000000..94d3af3
--- /dev/null
@@ -0,0 +1,918 @@
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <map>
+#include <iterator>
+#include <list>
+#include <assert.h>
+#include "asn1_generator.h"
+#include "asn1_gen_optimizer.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#if defined(__APPLE__) || (GCC_VERSION > 40800)
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+#if defined(_WIN32)
+#include <stdlib.h>
+#endif
+#include "asn1_resolver.h"
+#include "asn1_generator_helper.h"
+
+#include "asn1_recursive_visitor.h"
+
+/**
+ *
+ */ 
+struct find_type
+{
+  find_type(asn1::type::id t)
+    : m_type(t)
+  { }
+  bool operator ()(asn1::node *t)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(t);
+    if (f->get_type() &&
+      t->type_id()() == m_type)
+    {
+      return true;
+    }
+    return false;  
+  }
+  asn1::type::id  m_type;
+};
+
+/**
+ * Works for :
+ *   components of  are integrated in new class
+ *   selection type is replaced with real type
+ *   object defined syntax is checked
+ *
+ */ 
+class optimize_phase1 : public asn1::recursive_visitor<optimize_phase1>
+{
+  public:
+  optimize_phase1(asn1::resolver &r,std::fstream &l)
+    : resolver(r) , m_log(l)
+  {
+  }
+
+  bool traverse_module(asn1::module *m)
+  {
+    m_module = m ;
+    asn1::recursive_visitor<optimize_phase1>::traverse_module(m);
+    return true;
+  }
+
+  bool visit_typeref(asn1::node *tref)
+  {
+    tref->as_typeref()->resolve(resolver);
+    return true;
+  }
+  bool visit_sequence(asn1::sequence *n)
+  {
+    asn1::node::iterator it = std::find_if( n->begin()
+                                          , n->end()
+                                          , find_type(asn1::type::ASN1_COMPONENTS_OF));
+
+    if ( it != n->end())
+    {
+      asn1::field *f = dynamic_cast<asn1::field *>(*it);
+      asn1::typeref *type  = dynamic_cast<asn1::typeref *>(f->get_type());    
+      asn1::constructed *rtype = resolver.resolve(*type)->as_constructed();
+      if (rtype)
+      {
+        GEN_LOG_INFO("%s COMPONENTS OF  %s transformed \n"
+                    ,n->identifier()->name().c_str()
+                    ,type->name().c_str()
+                    );
+        std::insert_iterator<asn1::node::node_list> iit(n->nodes(),it);
+        std::copy(rtype->begin(),rtype->end(),iit);
+        n->nodes().erase(it);
+      }
+    }
+    return true;
+  }
+  bool visit_selection(asn1::selection *n)
+  {
+    GEN_LOG_ERROR("SELECTION TO BE HANDLED %s\n",n->type_node()->name().c_str());
+    return true; 
+  }
+
+  /**
+   * @brief handle selection type
+   *
+   */ 
+  bool visit_component_type(asn1::field *n)
+  {
+    GEN_LOG_INFO("phase1 Visite %s\n"
+                ,n->name().c_str());
+    process_selection(n);
+    return true; 
+  }
+  //
+  bool visit_alternative_choice(asn1::field *n)
+  {
+    GEN_LOG_INFO("phase1 Visite %s\n"
+                ,n->name().c_str());
+#if 0
+    if (asn1::typeref *_rf = n->get_type()->as_typeref())
+    {
+      std::cerr<<"visit_alternative_choice "<<n->name()<<std::endl;
+      GEN_LOG_INFO("phase1 Visite alternative %s resolve type %s\n"
+                ,n->name().c_str()
+                ,n->get_type()->name().c_str()
+      );
+      _rf->resolve(resolver);
+      // Trying to understand what's going on
+      if (! n->get_type()->name().compare("DistinguishedName"))
+      {
+        std::cerr<<"visit_alternative_choice real type "<<_rf->get_real_type()->from_module()->name();
+        std::cerr<<"::"<<_rf->get_real_type()->name()<<std::endl;
+        assert( 0);
+      }
+    }
+#endif
+    process_selection(n);
+    return true; 
+  }
+  //
+  bool process_selection(asn1::field *n)
+  {
+    asn1::typenode *stype    = n->get_type();
+    if (stype && stype->type_id()() == asn1::type::ASN1_SELECTION)
+    {
+      asn1::typeref *ref   = dynamic_cast<asn1::typeref *>(stype->get_eltype());
+      asn1::constructed    *rtype = resolver.resolve(*ref)->as_constructed();
+
+      GEN_LOG_INFO("SELECTION HANDLED %s < %s\n"
+                   ,stype->name().c_str()
+                   ,ref->name().c_str()
+                   );
+      // Check if rtype is CHOICE and lookup for n->name type.
+      // Replace n->type with new type and delete selection
+      // Keep tag and other stuff from selection before delete
+      asn1::node::iterator it = std::find_if(rtype->begin()
+                                         ,rtype->end()
+                                         ,asn1::find_node(stype->name()));
+      if (it != rtype->end())
+      {
+        asn1::field *a = dynamic_cast<asn1::field *>(*it);
+        asn1::typenode *ntype = a->get_type();
+        asn1::typenode *t = ntype->clone();
+        t->set_parent(n->get_parent());
+        if (stype->tagged())
+        {
+          t->tag(stype->tag());
+        }
+        if (t->identifier())
+        {
+          t->identifier(n);
+        }
+        n->set_type(t);
+        delete (stype);
+        GEN_LOG_INFO("TYPE IS : %s\n"
+                    , a->get_type()->name().c_str()); 
+      } else 
+      {
+        GEN_LOG_INFO("ERROR Type not found : %s\n"
+                    , n->name().c_str()); 
+      }
+    }
+    return true;
+  }
+  /**
+   * Parse defined syntax and check object 
+   */ 
+  bool visit_assign_object(asn1::object_assignment *n)
+  {
+    asn1::typenode *type = n->get_type();
+  
+    assert(type->type_id()() == asn1::type::ASN1_REFERENCE);
+    asn1::node *real_type = 
+      resolver.resolve(dynamic_cast<asn1::typeref &>(*type));
+    if (real_type != NULL)
+    {
+      asn1::object   *obj  = dynamic_cast<asn1::object *>(type->type_node()); 
+      asn1::classdef *cdef = dynamic_cast<asn1::classdef *>(real_type);
+      assert( obj  != NULL);
+      assert( cdef != NULL);
+      if ( cdef->check_object_syntax(obj) )
+      {
+        GEN_LOG_INFO("OBJECT syntax OK %s\n",n->name().c_str());
+        obj->set_classdef(cdef);
+      } else
+      {
+        GEN_LOG_ERROR("OBJECT syntax error %s\n",n->name().c_str());
+        std::cerr<<"Syntax ERROR for object "<<n->name()<<std::endl;    
+      }
+    } else
+    {
+      GEN_LOG_ERROR("OBJECT CLASS not found %s\n",type->name().c_str());
+      std::cerr<<"OBJECT CLASS not found "<<type->name()<<std::endl;
+    }
+    return true;
+  }
+
+  bool visit_object_classfield_tf(asn1::classfield_tf *S,asn1::node  *f)
+  {
+    if (f->is_constructed())
+    {
+      asn1::object  *obj = dynamic_cast<asn1::object *>(f->get_parent());
+      std::string type_name = S->name().substr(1) + "_"+ obj->identifier()->cpp_name();         
+      asn1::assignment *nt  = new asn1::type_assignment(type_name);
+      asn1::typeref    *tr  = new asn1::typeref(
+                                  new asn1::simple_reference(type_name));
+      tr->set_parent(f->get_parent());
+      //
+      nt->set_type(f);
+      nt->set_parent(m_module);
+      //nt->parameters(pi->parameters());
+      f->set_parent(m_module);
+      f->identifier(nt);
+      m_module->append(nt);
+      obj->update_field(S->name(),tr);
+      GEN_LOG_INFO( "VISIT OBJECT FIELD %s NOT REF FIXED TO  %s\n"
+         , S->name().c_str()
+         , type_name.c_str()
+         );
+    }
+    return true;
+  }
+  /*
+   *
+   */
+  bool visit_object_classfield_osf(asn1::classfield_osf *S,asn1::node  *f)
+  {
+    asn1::object  *obj = dynamic_cast<asn1::object *>(f->get_parent());
+    std::string tname = S->name().substr(1) + "_"+ obj->identifier()->cpp_name(); 
+    GEN_LOG_INFO( "VISIT OBJECT FIELD %s TO BE FIXED %s\n"
+           , S->name().c_str()
+           , tname.c_str()
+    );
+    return true;
+  } 
+  /**
+   *
+   */
+  bool visit_object_classfield_ftvf(asn1::classfield_ftvf *ftvf,asn1::node *f)
+  {
+    asn1::valuetype *vt  = dynamic_cast<asn1::valuetype *>(f);
+    asn1::typenode  *type= ftvf->get_type();
+    asn1::object   *obj  = dynamic_cast<asn1::object *>(f->get_parent());
+    asn1::classdef *cdef = obj->get_classdef();
+    std::string tname  = ftvf->name().substr(1) + "_"+ obj->identifier()->cpp_name(); 
+    GEN_LOG_INFO( "VISIT OBJECT FIELD ftvf %s TO BE FIXED %s %s\n"
+           , ftvf->name().c_str()
+           , tname.c_str()
+           , f->cpp_name().c_str()
+    );
+    assert((cdef != NULL) && "cdef should be set");
+    //assert( (vt != NULL) && "fixed type value field should be value type node");
+    if (! vt )
+    {
+      return true;
+    }
+    asn1::value *v = vt->value();
+    GEN_LOG_INFO( "ftvf %s value is   %s\n"
+           , ftvf->name().c_str()
+           , v->cpp_name().c_str()
+    );
+    // Get real type instead of typeref
+    if (type->as_typeref())
+    {
+      asn1::node *real_type = 
+        resolver.resolve(dynamic_cast<asn1::typeref &>(*type));
+      type = real_type->as_typenode();
+    }
+    // Check value node !!!
+    if (asn1::choice *c = type->as_choice())
+    {
+      asn1::field *field = c->get_field(f->name());
+      if (! field )
+      {
+        GEN_LOG_ERROR("ftvf: field %s 0x0x",f->name().c_str()
+            , c->get_field(f->name()));
+        std::cerr<<"ftvf: "<<c->cpp_name()<<" "<<c<<" field "<<f->name()<<" 0x"<<c->get_field(f->name())<<std::endl;
+        return true;
+      }
+      asn1::typenode *ct = c->get_field(f->name())->get_type();
+      GEN_LOG_INFO( "ftvf %s type is %s id=%d\n"
+           , ftvf->name().c_str()
+           , ct->cpp_name().c_str()
+           , ct->type_id()()
+      );
+      if (v && v->m_node->type_id()() == 0)
+      {
+        asn1::constructed *vn = v->m_node->value()->m_node->as_constructed();
+        std::cerr<<__FUNCTION__<<" Proccess ftvf because of wrong id ";
+        std::cerr<<"<"<<v->m_node->cpp_name()<<"> "<<typeid(*(v->m_node)).name()<<std::endl;
+        assert((vn != NULL) && " VN should be constructed ");
+        switch (ct->type_id()())
+        {
+          case asn1::type::ASN1_INTEGER:
+          break;
+          case asn1::type::ASN1_OBJECT_IDENTIFIER:
+          {
+            #if 1
+            asn1::object_identifier *oid = new asn1::object_identifier();
+            std::copy (vn->begin(),vn->end(),
+                       std::back_inserter(oid->nodes()));
+            delete vn;
+            oid->set_parent(cdef->from_module());
+            //v->m_node->value()->m_node = oid;
+            v->m_node= oid;
+            #endif
+          }
+          break;
+          default:
+           std::cerr<<__FUNCTION__<<" Proccess ftvf AIIIIIII"<<std::endl;
+           ;
+        }
+      } 
+    }
+    return true;
+  }
+  protected:
+    asn1::module   *m_module;
+    asn1::resolver &resolver;
+    std::fstream   &m_log;
+};
+
+/**
+ *    OPTIMIZE NESTED
+ */
+
+
+/**
+ *
+ *
+ */ 
+class optimize_nested : public asn1::recursive_visitor<optimize_nested>
+{
+  public:
+  optimize_nested(asn1::resolver &r,std::fstream &l)
+    : resolver(r) , m_log(l)
+  {
+  }
+
+  bool traverse_module(asn1::module *m)
+  {
+    m_module = m ;
+    asn1::recursive_visitor<optimize_nested>::traverse_module(m);
+    return true;
+  }
+
+
+  bool visit_sequence(asn1::sequence *n)
+  {
+    GEN_LOG_INFO("optimize_nested %s set of  %s transformed \n"
+                ,n->identifier()->name().c_str()
+                ,n->name().c_str()
+                );
+    asn1::node::iterator it = std::find_if( n->begin()
+                                          , n->end()
+                                          , find_type(asn1::type::ASN1_COMPONENTS_OF));
+
+    if ( it != n->end())
+    {
+      asn1::field *f = dynamic_cast<asn1::field *>(*it);
+      asn1::typeref *type  = dynamic_cast<asn1::typeref *>(f->get_type());    
+      asn1::constructed    *rtype = resolver.resolve(*type)->as_constructed();
+      if (rtype)
+      {
+        GEN_LOG_INFO("optimize_nested ident: %s COMPONENTS OF %s transformed\n"
+                    ,n->identifier()->name().c_str()
+                    ,type->name().c_str()
+                    );
+        std::insert_iterator<asn1::node::node_list> iit(n->nodes(),it);
+        std::copy(rtype->begin(),rtype->end(),iit);
+        n->nodes().erase(it);
+      }
+    }
+    return true;
+  }
+
+  /**
+   * @brief handle selection type
+   *
+   */ 
+  bool visit_alternative_choice(asn1::field *ident)
+  {
+    GEN_LOG_INFO("optimize_nested field: %s type: %s process\n"
+                ,ident->name().c_str()
+                ,(ident->get_type())?ident->get_type()->name().c_str():"..."
+                );
+    process(ident);
+    process_reference(ident);
+    return true;
+  }
+  /**
+   * @brief handle selection type
+   *
+   */ 
+  bool visit_component_type(asn1::field *ident)
+  {
+    GEN_LOG_INFO("optimize_nested field: %s type: %s process\n"
+                ,ident->name().c_str()
+                ,(ident->get_type())?ident->get_type()->name().c_str():"..."
+                );
+    process(ident);
+    process_reference(ident);
+    return true;
+  }
+  //
+  bool visit_set_of(asn1::set_of *so)
+  {
+    asn1::typenode *stype = so->get_eltype();
+    GEN_LOG_INFO("optimize_nested TODO %s set of  %s transformed \n"
+                ,so->identifier()->name().c_str()
+                ,stype->name().c_str()
+                );
+    switch (stype->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE:
+      case asn1::type::ASN1_SET:
+      case asn1::type::ASN1_CHOICE:
+        process(so);
+        break;
+      default:
+       ;
+    }
+    return true;
+  }
+  //
+  bool visit_sequence_of(asn1::sequence_of *so)
+  {
+    asn1::typenode *stype = so->get_eltype();
+    GEN_LOG_INFO("TODO %s sequence of  %s transformed \n"
+                ,so->identifier()->name().c_str()
+                ,stype->name().c_str()
+                );
+    switch (stype->type_id()())
+    {
+      case asn1::type::ASN1_SEQUENCE:
+      case asn1::type::ASN1_SET:
+      case asn1::type::ASN1_CHOICE:
+        process(so);
+        break;
+      default:
+       ;
+    }
+    return true;
+  }
+  /**
+   * Parse defined syntax and check object 
+   */ 
+  bool visit_assign_object(asn1::object_assignment *n)
+  {
+    return true;
+  }
+
+  void process_reference(asn1::field *n)
+  {
+    asn1::typenode *stype    = n->get_type();
+    if (! stype)
+      return;
+
+    GEN_LOG_INFO( "optimize_nested start field: %s type: %s \n"
+                , n->name().c_str()
+                , stype->name().c_str()
+                );
+    if (asn1::typeref *_ref = stype->as_typeref())
+    {
+      _ref->resolve(resolver);
+    } else {
+      GEN_LOG_INFO("optimize_nested FAILED type: %s not typeref !!!\n"
+                   ,stype->name().c_str()
+                   );
+    }
+  }
+
+  bool visit_assign_typeref(asn1::typeref_assignment *n)
+  {
+    asn1::typenode *stype    = n->get_type();
+    if (! stype)
+      return true;
+    GEN_LOG_INFO(" %s \n"
+                   ,stype->name().c_str()
+                   );
+    if (asn1::typeref *_ref = stype->as_typeref())
+    {
+      _ref->resolve(resolver);
+    }
+    return true;
+  }
+  /**
+   * Needs to be split into two prototypes.
+   *   one for asn1::field    types
+   *   one for asn1::typenode types eg elements in set_of / seq_of
+   */
+  void process(asn1::node *ident)
+  {
+    asn1::node::node_list pm; 
+    asn1::node *type = ident->type_node();
+    GEN_LOG_DEBUG(" %s %s\n"
+                   , __FUNCTION__
+                   ,ident->name().c_str()
+                   );
+    if (type && type->is_constructed())
+    {
+      asn1::node * pi = ident->get_parent()->identifier();
+      std::string type_name;
+      if (pi)
+      {
+        type_name = pi->cpp_name() +"_" + ident->name();
+      } else
+      { // It seams that parent for set_of subtypes are NULL !!!:
+        type_name = ident->identifier()->cpp_name() +"_type" ;
+      }
+      GEN_LOG_INFO("PROCESS %s -> %s\n",ident->name().c_str(),type_name.c_str());
+      asn1::assignment *nt  = new asn1::type_assignment(type_name);
+      asn1::typeref     *tr = new asn1::typeref(
+                                  new asn1::simple_reference(type_name));
+      nt->set_type(type);
+      nt->set_parent(m_module);
+      if (pi)
+        nt->parameters(pi->parameters());
+      type->set_parent(m_module);
+      type->identifier(nt);
+      m_module->append(nt);
+      //
+      asn1::node *subtype = type->type_node();
+      if ( subtype 
+           && subtype->identifier() 
+           && subtype->identifier()->get_parent() == NULL)
+      {
+        GEN_LOG_INFO( "PROCESS ERROR %s -> %s type-type->get_parent is NULL\n"
+                    , ident->name().c_str()
+                    , type_name.c_str());
+      } else if (subtype)
+      {
+        GEN_LOG_INFO("PROCESS WARN %s -> %s Maybe change parent of subtype \n",ident->name().c_str(),type_name.c_str());
+      }
+      //
+      if (ident->get_parent() == NULL)
+      {
+        GEN_LOG_INFO("PROCESS ERROR %s -> %s ident->get_parent is NULL\n",ident->name().c_str(),type_name.c_str());
+      }
+      tr->set_parent(ident->get_parent());
+      tr->identifier(ident);
+      ident->type_node(tr);
+    } else {
+        GEN_LOG_INFO( " Nothing field: %s -> type:%s DONE\n"
+                    , ident->name().c_str()
+                    , (type)?type->name().c_str():"NULL");
+    }
+  }
+  protected:
+    asn1::module   *m_module;
+    asn1::resolver &resolver;
+    std::fstream   &m_log;
+};
+
+
+/**
+ *    OPTIMIZE params
+ */
+class replace_params : public asn1::recursive_visitor<replace_params>
+{
+  public:
+  replace_params(asn1::resolver &r,std::fstream &l,asn1::module *m,asn1::parameters &p,asn1::act_parameters &ap)
+    : resolver(r) , m_log(l), m_actual_params(ap),m_parameters(p),m_module(m)
+  {
+  }
+  /**
+   * @brief handle replacements in alternative_choice 
+   *
+   */ 
+  bool visit_alternative_choice(asn1::field *ident)
+  {
+    asn1::typenode         *type      = ident->get_type(); 
+    asn1::module           *m         = ident->from_module();
+    std::string            type_name  = type->name(); 
+    
+    if ( (type->type_id()() == asn1::type::ASN1_REFERENCE)
+          && m_module != m    )
+    {
+      asn1::typeref *typeref = dynamic_cast<asn1::typeref *>(type);
+      if (typeref->is_simple())
+      {      
+        process_reference(ident);
+      } else
+      {
+        GEN_LOG_INFO("no process reference %s -> %s wp\n",ident->name().c_str(),type_name.c_str());
+      }
+    }
+    if  ( type->parameters()) 
+    {
+      asn1::act_parameters &act_params  = dynamic_cast<asn1::act_parameters &>(*type->parameters()); 
+
+      GEN_LOG_INFO("check %s -> %s wp\n",ident->name().c_str(),type_name.c_str());
+    }
+    return true;
+  }
+
+  /**
+   *
+   */ 
+  void process_reference(asn1::field *ident)
+  {
+    asn1::typenode         *type      = ident->get_type();
+    asn1::module           *m         = ident->from_module();
+    asn1::node::iterator   it; 
+    asn1::external_type_reference *etr = 
+           new asn1::external_type_reference(m->name(),type->name());      
+    asn1::typeref *nref = new asn1::typeref(type->name(),etr);
+    GEN_LOG_INFO("check process_reference  %s -> %s with %s\n"
+              ,ident->name().c_str()
+              ,type->name().c_str()
+              ,etr->name().c_str());
+
+    nref->set_parent(type->get_parent());
+    nref->identifier(ident);
+
+    if (type->parameters())
+        nref->parameters(type->parameters()->clone());
+
+    ident->set_type(nref);
+  }
+  /**
+   * @brief handle remplacement in component_type
+   *
+   */ 
+  bool visit_component_type(asn1::field *ident)
+  {
+    std::string            type_name  = ident->get_type()->name();
+    asn1::typenode         *type      = ident->get_type();
+    asn1::module           *m         = ident->from_module();
+    asn1::node::iterator   it; 
+    GEN_LOG_INFO("check ct %s:%s -> %s:%s\n"
+            , m_module->name().c_str()
+            ,ident->name().c_str()
+            , m->name().c_str()
+            ,type_name.c_str());
+    
+    if ( (type->type_id()() == asn1::type::ASN1_REFERENCE)
+         && m_module != m    )
+    {
+      asn1::typeref *typeref = dynamic_cast<asn1::typeref *>(type);
+      if (typeref->is_simple())
+      {      
+        process_reference(ident);
+      } else
+      {
+        GEN_LOG_INFO("no process reference %s -> %s wp\n",ident->name().c_str(),type_name.c_str());
+      }
+    }
+    
+    if (m_parameters.have_reference(type->name(),it))
+    {
+        size_t l = std::distance(m_parameters.begin(),it);
+        asn1::typenode *rtype = m_actual_params[l]->clone()->as_typenode();
+        GEN_LOG_INFO("check ct HOHO %s -> %s %s %ld\n"
+          , ident->name().c_str()
+          , type_name.c_str()
+          , rtype->name().c_str()
+          , l
+          );
+        ident->set_type(rtype);
+        rtype->identifier(ident);
+        rtype->set_parent(ident->get_parent());
+    }
+    return true;
+  }
+
+  protected:
+    asn1::module         *m_module;
+    asn1::resolver       &resolver;
+    std::fstream         &m_log;
+    asn1::act_parameters &m_actual_params;
+    asn1::parameters     &m_parameters;
+};
+
+/**
+ *
+ *
+ */ 
+class optimize_params : public asn1::recursive_visitor<optimize_params>
+{
+  public:
+  optimize_params(asn1::resolver &r,std::fstream &l)
+    : resolver(r) , m_log(l)
+  {
+  }
+
+  bool traverse_module(asn1::module *m)
+  {
+    m_module = m ;
+    asn1::recursive_visitor<optimize_params>::traverse_module(m);
+    return true;
+  }
+
+  /**
+   * @brief handle selection type
+   *
+   */ 
+  bool visit_alternative_choice(asn1::field *ident)
+  {
+    asn1::node *parent = ident->get_parent();
+    if (parent->identifier()->parameters())
+    {
+      GEN_LOG_ERROR( "PROCESS ALTERNATIVE TYPE WP %s -> forget\n"
+                    ,ident->name().c_str());
+      return true;
+    }     
+    if (ident->get_type() && ident->get_type()->parameters())
+    {
+      asn1::typeref        *type        = dynamic_cast<asn1::typeref *>(ident->get_type());    
+      asn1::act_parameters &act_params  = dynamic_cast<asn1::act_parameters &>(*type->parameters()); 
+      asn1::node    *rtype = resolver.resolve(*type);
+      std::string type_name  = ident->get_type()->name(); 
+      if (rtype == NULL)
+      {
+        std::cerr<<"rtpye NULL === "<<type->name()<<std::endl;      
+        GEN_LOG_ERROR("PROCESS ALTERNATIVE TYPE WP %s -> %s\n"
+                     ,ident->name().c_str()
+                     ,type_name.c_str());
+      } else 
+      {
+        asn1::parameters &p  = dynamic_cast<asn1::parameters &>
+                                (*rtype->identifier()->parameters());
+        std::cerr<<"visit_alternative_choice before clone "<<ident->name()<<"rtype="<<rtype->name()<<std::endl;
+        asn1::node    *ctype = rtype->clone();
+        std::cerr<<"visit_alternative_choice after clone :"<<ident->name()<<std::endl;
+        GEN_LOG_INFO("PROCESS ALTERNATIVE TYPE WP %s -> %s\n"
+                    ,ident->name().c_str(),type_name.c_str());
+        // Process replacing parameters ....
+        replace_params replace(resolver,m_log,m_module,p,act_params);
+        replace.traverse_type(ctype);
+        process_component(ident,ctype->as_typenode());
+      }
+    } else if (ident->get_type())
+    {
+      std::string type_name  = ident->get_type()->name(); 
+        GEN_LOG_INFO("PROCESS ALTERNATIVE TYPE NP %s -> %s\n"
+                    ,ident->name().c_str(),type_name.c_str());
+    }
+    return true;
+  }
+  /**
+   * @brief handle selection type
+   *
+   */ 
+  bool visit_component_type(asn1::field *ident)
+  {
+    if (ident->get_type() && ident->get_type()->parameters())
+    {
+      asn1::typeref *type  = dynamic_cast<asn1::typeref *>(ident->get_type());    
+      std::string type_name  = type->name(); 
+      GEN_LOG_INFO("PROCESS COMPONENT TYPE WP %s -> %s\n"
+                  ,ident->name().c_str(),type_name.c_str());
+    } else
+    {
+    }
+    return true;
+  }
+  /**
+   * Parse defined syntax and check object 
+   */ 
+  bool visit_assign_type(asn1::type_assignment *n)
+  {
+    if (! n->parameters( ) && n->get_type()->parameters())
+    {
+      std::string type_name  = n->get_type()->name(); 
+      GEN_LOG_INFO("visit_assign_type %s -> %s\n"
+                  ,n->name().c_str()
+                  ,type_name.c_str());
+    }
+    return true;
+  }
+  /**
+   * Parse typerefs and see if there are parameter instantiated classes
+   * If so process with the instantiation
+   *   -> Replace typeref with the real type This can be bad for generator if
+   *      the global type is not changed !!!! 
+   *   -> We should also replace all parameters with the actual parameters
+   */ 
+  bool visit_assign_typeref(asn1::typeref_assignment *n)
+  {
+    asn1::typeref *type  = dynamic_cast<asn1::typeref *>(n->get_type());    
+    if (! n->parameters( ) && type->parameters())
+    {
+      asn1::act_parameters &act_params  = dynamic_cast<asn1::act_parameters &>(*type->parameters()); 
+      asn1::node    *rtype = resolver.resolve(*type);
+      asn1::parameters &p  = dynamic_cast<asn1::parameters &>
+                                (*rtype->identifier()->parameters());
+      std::string type_name  = type->name(); 
+      GEN_LOG_INFO("visit_assign_typeref TYPEREF %s -> %s\n"
+                  ,n->name().c_str(),type_name.c_str());
+      std::cerr<<"visit_assign_typeref "<<n->name()<<std::endl;
+      asn1::node *ctype = rtype->clone();
+      // temp
+      //ctype->identifier(type->identifier());
+      //ctype->set_parent(m_module);
+         
+      // Process replacing parameters ....
+      std::cerr<<"visit_assign_typeref before replace "<<n->name()<<std::endl;
+    }
+    return true;
+  }
+
+
+  void process(asn1::assignment *ident,asn1::node *ntype)
+  {
+    asn1::node::node_list pm; 
+    asn1::node *type = ident->get_type();
+
+    GEN_LOG_INFO("PROCESS %s -> type\n",ident->name().c_str());
+    asn1::assignment *nt  = new asn1::type_assignment(ident->name());
+    nt->set_type(ntype);
+    nt->set_parent(m_module);
+    //nt->parameters(pi->parameters());
+    ntype->set_parent(m_module);
+    ntype->identifier(nt);
+    m_module->append(nt);
+    //
+  }
+  /**
+   *
+   */ 
+  void process_component(asn1::field *ident,asn1::typenode *ntype)
+  {
+    asn1::node::node_list pm; 
+    asn1::node *type = ident->get_type();
+    GEN_LOG_INFO("PROCESS COMPONENT %s -> type %s\n"
+                , ident->name().c_str()
+                , ntype->name().c_str());
+    assert( (ntype != NULL) && "ntype must not be NULL");
+    //nt->parameters(pi->parameters());
+    ntype->set_parent(ident->get_parent());
+    ntype->identifier(ident);
+    //
+    ident->set_type(ntype);
+    // If properly cloned, I should delete type from ident before replacing it
+  }
+  protected:
+    asn1::module   *m_module;
+    asn1::resolver &resolver;
+    std::fstream   &m_log;
+};
+
+
+
+namespace asn1
+{
+
+/**
+ *
+ */ 
+gen_optimizer::gen_optimizer(asn1::module *n,asn1::module::modules_type &m) 
+  : generator(n,m)
+{
+}
+
+
+/**
+ *
+ */ 
+void 
+gen_optimizer::gen_module(std::ostream &os,module  *m)
+{
+  optimize_phase1 opt1(m_resolver,m_log);
+  
+  os<<"*"<<std::endl;
+  os<<"* OPTIMIZE MODULE "<<m->name()<<std::endl;
+  os<<"*"<<std::endl;
+  os<<"-- Phase 1 --"<<std::endl;
+  os<<"\t-> Parse Object Defined Syntax"<<std::endl;
+  os<<"\t-> Replace components of"<<std::endl;
+  os<<"\t-> Replace selection with real type"<<std::endl;
+  os<<"Processing ....";
+  opt1.traverse_module(m);
+  os<<" done."<<std::endl;
+  m_log.flush();
+
+  optimize_nested opt2(m_resolver,m_log);
+  os<<"-- Phase 2 --"<<std::endl;
+  os<<"\t-> nested types made global "<<std::endl;
+  os<<"\t-> typeref resolution. Set real_type adjust reference "<<std::endl;
+  os<<"Processing ....";
+  opt2.traverse_module(m);
+  os<<" done."<<std::endl;
+
+  optimize_params params(m_resolver,m_log);
+  os<<"-- Phase 3 --"<<std::endl;
+  os<<"\t-> Process parameterized types ..."<<std::endl;
+  os<<"\t-> Check/Correct values eg v1 Toto ::= { mib 2 }"<<std::endl;
+  os<<"Processing ....";
+  params.traverse_module(m);
+  os<<" done."<<std::endl;
+}
+
+}
+/**
+ * vim:et sw=2 ts=2 list:
+ */
diff --git a/libgen/asn1_gen_optimizer.h b/libgen/asn1_gen_optimizer.h
new file mode 100644 (file)
index 0000000..7b5584f
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef ASN1_GEN_OPTIMIZER_H
+#define ASN1_GEN_OPTIMIZER_H
+
+#include <iostream>
+#include "asn1_generator.h"
+
+namespace  asn1
+{
+
+/**
+ * @brief this generator does not produce any output. 
+ * It processes the module and performs AST transformation
+ * in order to facilitate the generators work.
+ *   -> COMPONENTS OF and SELECTION replacement
+ *   -> Object with defined syntax parsing
+ *   -> Inner private types are set global with typeref
+ *      example : G ::= SEQUENCE { a SEQUENCE { b INTEGER } }
+ *      while be transormed G_a ::= SEQUENCE { b INTEGER }
+ *           G ::= SEQUENCE { a G_a }
+ *
+ */ 
+class gen_optimizer : public asn1::generator
+{
+  public:
+    gen_optimizer(asn1::module *n,asn1::module::modules_type &m); 
+    
+    virtual void gen_module(std::ostream &os,module  *) ;
+    
+    void gen_const(std::ostream &os,asn1::node *n) {};
+    //
+    void gen_typedef(std::ostream &os,asn1::typenode *n) {};
+  private:  
+};
+
+
+}
+/**
+ * vim:et:sw=2:ts=2
+ */
+#endif /*ASN1_GEN_OPTIMIZER_H*/
diff --git a/libgen/asn1_generator.cpp b/libgen/asn1_generator.cpp
new file mode 100644 (file)
index 0000000..9c74cad
--- /dev/null
@@ -0,0 +1,472 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <assert.h>
+
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_generator.h"
+#include "adt/asn1_recursive_visitor.h"
+
+namespace  asn1
+{
+    
+generator::generator(module *root_m)
+  :   m_module(root_m) 
+    , m_config()
+    , m_resolver(*root_m,asn1::module::modules_type())  
+{
+}
+
+generator::generator(module *root_m,asn1::module::modules_type &m_) 
+  :   m_module(root_m) 
+    , m_config()
+    , m_resolver(*root_m,m_)  
+{
+  asn1::module::modules_type::iterator it;
+  GEN_LOG_DEBUG("generator::generator m_.size=%lu ",m_.size());
+  m_modules.resize(m_.size());
+  m_modules = m_;
+  // Debuging code
+#if 0  
+  for (  it  = m_.begin()
+       ; it != m_.end()
+       ; ++it) 
+  {
+    std::cerr<<"generator::generator "<<(*it)->name()<<" "<<(*it)->size()<<std::endl;
+    GEN_LOG_DEBUG("generator::generator m_ *it.name=%s size=%lu "
+        ,(*it)->name().c_str()
+        ,(*it)->size());
+  }
+  for (  it  = m_modules.begin()
+       ; it != m_modules.end()
+       ; ++it) 
+  {
+    std::cerr<<"generator::generator "<<(*it)->name()<<" "<<(*it)->size()<<std::endl;
+    GEN_LOG_DEBUG("generator::generator m_ *it.name=%s size=%lu "
+        ,(*it)->name().c_str()
+        ,(*it)->size());
+  }
+#endif  
+}
+
+// If a parameter is of type without value, it's template
+// otherwise it's normal structure
+//
+bool
+generator::is_template(asn1::node *_params)
+{
+  bool ret = false;
+  asn1::parameters *params = dynamic_cast<asn1::parameters *>(_params);
+  if (_params)
+    assert(params != NULL);
+  if (params) 
+  {
+    asn1::node::iterator it = params->begin();
+    if (params->name().compare("SIGNED") == 0)
+    {
+      std::cerr<<"generator::is_template "<<params->name()<<" Should be yes "<<(it== params->end())<<std::endl;
+      assert(0);
+    }
+    for (; it != params->end(); ++it)
+    {
+      asn1::parameter &param = dynamic_cast<asn1::parameter &>(*(*it));    
+      if (params->name().compare("SIGNED") == 0)
+      {
+        std::cerr<<"generator::is_template "<<params->name()<<" "<<param.get_governor()<<std::endl;
+        assert(0);
+      }
+      if ( param.get_governor() == NULL)
+      {
+        // Presence if identifier means typed value or ValueSet
+        ret = true;
+        break;
+      }
+    }
+    if (params->name().compare("SIGNED") == 0)
+    {
+      std::cerr<<"generator::is_template "<<params->name()<<" but is false"<<std::endl;
+      assert(0);
+    }
+    return ret;
+  } else
+    return false;
+}
+
+/**
+ * This is only valid for OID where we use 7 bits for each octet.
+ */
+void generator::encode_integer(long value,std::vector<unsigned char> &v)
+{
+  long integer = value;
+  long intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer %ld %lx",value,value);
+  // std::cout<<"encode_integer: "<<value<<" 0x"<<std::hex<<value<<std::dec<<"\n";
+#endif
+  while ( (((integer & mask) == 0) || ((integer & mask) == mask)) 
+          && (intsize > 1)) {
+      intsize--;
+      integer <<=8;
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer step 1  %lx",integer);
+  //    std::cout<<"is: "<<std::hex<<integer<<std::dec<<" ";
+#endif
+  }
+  mask = (0x7f << ((intsize-1)*7));
+  long decal = (intsize -1)*7;
+#ifdef DEBUG
+  GEN_LOG_DEBUG("generator::encode_integer step 1  intsize=%ld mask=0x%lx decal=%ld",intsize,mask,decal);
+  //std::cout<<" intsize="<<intsize<<" mask="<<std::hex<<mask<<std::dec<<" decal="<<decal<<std::endl;
+#endif
+  while ((value & mask  ) != 0) 
+  {
+      long treat = ((value & mask)>>decal);
+      v.push_back (( treat   & 0x7F) |0x80 );
+#ifdef DEBUG
+      std::cout<<"\tpushed :";
+      std::cout<<std::hex<<(int)v.back()<<" integer was:"<<value;
+      std::cout<<" Mask=0x"<<mask<<" treat="<<treat;
+      std::cout<<std::dec<<std::endl;
+#endif
+      value<<=7;
+  }
+  v.back() = v.back() & 0x7F;
+}
+
+    
+void 
+generator::oid_value(asn1::node *type,int *pos,std::vector<unsigned char> *v)
+{
+  asn1::object_identifier *oid = type->as_object_identifier();
+  assert(oid != NULL);
+  oid->arcs(reinterpret_cast<asn1::object_identifier::arcsType &>(*v));
+  *pos = v->size();
+}
+
+
+/**
+ *
+ *
+ */
+void generator::gen(std::ostream &os,const std::string &suf) 
+{
+    if (m_module)
+    {
+        std::string fn("./log/");
+        fn.append(m_module->name());
+        fn.append(suf);
+        fn.append(".gen.log");
+        m_log.open(fn.c_str(),std::fstream::out);
+        gen_module(os,m_module);
+        m_log.close();
+    }
+}
+    
+int generator::tag_mode(asn1::node *node) const
+{
+  assert((m_module != NULL) && "generator::tag_mode m_module should not be NULL");
+  asn1::node::tag_type t = node->tag();
+  if (node->tagged())
+  {
+    if (t.m_mode == asn1::node::tag_type::TM_DEFAULT)
+    {
+      asn1::node::tag_type mt = m_module->tag();
+      if (mt.m_mode == asn1::node::tag_type::TM_DEFAULT)
+      {
+        return asn1::node::tag_type::TM_EXPLICIT;
+      } else {
+        return mt.m_mode;
+      }
+    } else {
+      return t.m_mode;
+    }
+  } else {
+    return asn1::node::tag_type::TM_DEFAULT;
+  }
+}
+
+
+bool 
+generator::is_tag_explicit(asn1::typenode &_type) const
+{
+  return tag_mode(&_type) == asn1::node::tag_type::TM_EXPLICIT;
+}
+/**
+* For the generator classes We provide a methode to convert types::ASN1_<type> to ASN1 tags ids
+*/
+int generator::type2tagid(int v) const
+{
+  switch (v) {
+    case asn1::type::ASN1_BOOLEAN:
+      return 1;
+    break;
+    case asn1::type::ASN1_INTEGER:
+      return 2;
+    break;
+    case asn1::type::ASN1_BIT_STRING:
+      return 3;
+    break;
+    case asn1::type::ASN1_OCTET_STRING:
+      return 4;
+    break;
+    case asn1::type::ASN1_NULL:
+      return 5;
+    break;
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+      return 6;
+    break;
+    case asn1::type::ASN1_OBJECT_DESCRIPTOR:
+      return 7;
+    break;
+    case asn1::type::ASN1_EXTERNAL:
+      return 8;
+    break;
+    case asn1::type::ASN1_REAL:
+      return 9;
+    break;
+    case asn1::type::ASN1_ENUMERATED:
+      return 10;
+    break;
+    case asn1::type::ASN1_EMBEDDED_PDV:
+      return 11;
+    break;
+    case asn1::type::ASN1_UTCTime:
+      return 23;
+    break;
+    case asn1::type::ASN1_GeneralizedTime:
+      return 24;
+    break;
+    case asn1::type::ASN1_STRING_IA5String:
+      return 22;
+    break;
+    case asn1::type::ASN1_STRING_PrintableString:
+      return 19;
+    break;
+    case asn1::type::ASN1_STRING_VisibleString:
+      return 26;
+    break;
+    case asn1::type::ASN1_STRING_ISO646String:
+      return 29;
+    break;    /* aka VisibleString */
+    case asn1::type::ASN1_STRING_NumericString:
+      return 18;
+    break;
+    case asn1::type::ASN1_STRING_UniversalString:
+      return 28;
+    break;
+    case asn1::type::ASN1_STRING_BMPString:
+      return 30;
+    break;
+    case asn1::type::ASN1_STRING_UTF8String:
+      return 12;
+    break;  
+    case asn1::type::ASN1_STRING_GeneralString:
+      return 27;
+    break;
+    case asn1::type::ASN1_STRING_GraphicString:
+      return 25;
+    break;
+    case asn1::type::ASN1_STRING_TeletexString:
+      return 22;
+    break;
+    case asn1::type::ASN1_STRING_T61String:
+      return 20;
+    break;
+    case asn1::type::ASN1_STRING_VideotexString:
+      return 21;
+    break;
+    case asn1::type::ASN1_STRING_ObjectDescriptor:
+      return 7;
+    break;
+    default: return 0;
+  }
+}
+/**
+ *
+ */ 
+bool generator::type_in_imports(asn1::node *type,asn1::node **ns) 
+{
+  return type_in_imports(type->name(),ns);
+}
+
+bool generator::type_in_imports(const std::string &type,asn1::node **ns)
+{
+  bool ret = false;
+  asn1::import_list *imports = m_module->imports();
+  if (imports == NULL)
+  {
+    GEN_LOG_ERROR("type %s not in imports no imports\n",type.c_str());
+    return ret;
+  }
+  asn1::import  *import;
+  asn1::typeref *ref;
+  if (ret = imports->get_item(type,import,ref))
+  {
+    GEN_LOG_DEBUG("found %s in %s\n",type.c_str(),import->identifier()->name().c_str());
+    *ns = import->identifier();
+  }
+  return ret;
+}
+
+bool 
+generator::get_type_in_module(const std::string &mod_name,const std::string &typ_name,asn1::node **n)
+{
+  GEN_LOG_INFO("generator::get_type_in_module mod=%s cur_module=%s name=%s modules=%lu\n"
+                 ,mod_name.c_str()
+                 ,m_module->name().c_str()
+                 ,typ_name.c_str()
+                 ,m_modules.size());
+  asn1::module::modules_type::iterator mit = std::find_if(m_modules.begin(),m_modules.end(),
+                                                asn1::find_module(mod_name));
+  if (mit != m_modules.end()) 
+  {
+    asn1::node::iterator nit =
+        std::find_if((*mit)->begin(),(*mit)->end(),asn1::find_node(typ_name));
+    if (nit != (*mit)->end())
+    {
+      *n = (*nit);
+      return true;
+    } else 
+    {
+      GEN_LOG_ERROR("get_type_in_module type %s not in module %s\n"
+                     ,typ_name.c_str()
+                     ,mod_name.c_str());
+      return false;
+    }
+  } else {
+      GEN_LOG_ERROR("get_type_in_module did not find module %s\n",mod_name.c_str());
+    return false;
+  }
+}
+
+/**
+ *
+ */ 
+void generator::path2modulestring(asn1::node *type,std::string &ss)
+{
+  asn1::node::node_list lst;
+  
+  type->path2module(lst);
+  for (asn1::node::const_iterator nit = lst.begin()
+     ; nit != lst.end()
+     ; ++nit )
+  {
+    if ( (*nit)->is_private() )
+    {
+      ss += (*nit)->cpp_name() + "::";
+    } else
+      ss += (*nit)->identifier()->cpp_name() + "::";
+  }
+}
+
+/**
+ * Find a referenced value 
+ */
+bool
+generator::loockup_value(const std::string &_v,asn1::node **ov) 
+{
+  bool ret = false;
+  asn1::node *ns = NULL;
+  if (type_in_imports(_v,&ns)) {
+    GEN_LOG_ERROR("Value %s in import %s not yet handled\n",_v.c_str(),ns->name().c_str());
+  } else {
+    asn1::node::iterator it = std::find_if( m_module->begin()
+                                          , m_module->end()
+                                          ,asn1::find_value(_v));
+    if ( it != m_module->end()) 
+    {
+      // Ok, found the value, return it
+      *ov = (*it);
+      ret = true;
+    }
+  }
+  return ret;
+}
+
+/**
+ * Find the appropriate class node
+ */
+bool
+generator::loockup_class(const std::string &_v,asn1::node **ov)
+{
+  bool ret = false;
+    GEN_LOG_ERROR("To be coded %s\n",_v.c_str());
+  return ret;
+}
+
+/**
+ * Find the primary type for a typeref type
+ */
+bool
+generator::loockup_prim_type(const std::string &_v,asn1::node **ov)
+{
+  bool ret = false;
+    GEN_LOG_ERROR("To be coded %s \n",_v.c_str());
+  return ret;
+}
+
+
+
+
+bool 
+generator::have_attributes_to_init(const asn1::constructed *type) const 
+{
+  bool result = false;
+  asn1::node::const_iterator attr_it = type->begin();
+
+  for (; attr_it != type->end() ; ++attr_it)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*attr_it);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL  && attr_type->type_id()() != asn1::type::ASN1_EXTENSIBLE ) {
+      result = true; 
+      break;
+    }
+  }
+  return result;
+}
+
+void 
+generator::reference_chaine(asn1::typeref *type, std::list<asn1::node *> &lst)
+{
+  //asn1::node *t = type;
+  asn1::node *ns = NULL;
+  // add the first reference in case it's tagged Explicitly
+  //lst.push_back(type);
+  if ( type == NULL)
+    return;
+  //
+   asn1::node *t = type->get_real_type();
+  while  (t && t->as_typeref() )
+  {
+    lst.push_back(t);
+    t = t->as_typeref()->get_real_type();
+  }
+  if (t)
+    lst.push_back(t);
+}
+
+
+bool 
+generator::add_symbol(std::string &name,asn1::node *type)
+{
+  SymbolMap_iterator it = m_symbols.find(name);
+
+  if (it == m_symbols.end())
+  {
+    m_symbols[name] = type;
+    return true; 
+  } else
+  {
+    GEN_LOG_WARN("generator::add_symbol %s are equal %d\n",name.c_str(),((*((it)->second)) == *type));
+    return false;
+  }
+}
+
+}
+/*
+ *  vim: et sw=2 ts=2 list:
+ */
diff --git a/libgen/asn1_generator.h b/libgen/asn1_generator.h
new file mode 100644 (file)
index 0000000..7711321
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef ASN1_GENERATOR_H__
+#define ASN1_GENERATOR_H__
+#include <iostream>
+#include <fstream>
+#include <map>
+#include <string.h>
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_resolver.h"
+
+#if defined(_WIN32)
+#define GEN_LOG_DEBUG(fmt,...) do {\
+  } while (0)
+#define GEN_LOG_INFO(fmt,...) do {\
+  } while (0)
+#define GEN_LOG_WARN(fmt,...) do {\
+  } while (0)
+#define GEN_LOG_ERROR(fmt,...) do {\
+  } while (0)
+#else
+#define GEN_LOG_DEBUG(fmt,args...) do {\
+  char _lbuf[1024]; \
+  const char  *fn = strrchr(const_cast<char *>(__FILENAME__),'/');  \
+  fn = (fn == NULL)?__FILENAME__:fn+1;    \
+  if (m_log.is_open()) { \
+    m_log<<"DEBUG "<<__FUNCTION__<<" "; \
+    sprintf(_lbuf," (%s : %d) ",fn,__LINE__); m_log<<_lbuf; \
+    sprintf(_lbuf,fmt,##args); m_log<<_lbuf; \
+  }  \
+  } while (0)
+
+#define GEN_LOG_INFO(fmt,args...) do {\
+  char _lbuf[1024];      \
+  const char  *fn = strrchr(const_cast<char *>(__FILENAME__),'/');  \
+  fn = (fn == NULL)?__FILENAME__:fn+1;    \
+  if (m_log.is_open()) { \
+    m_log<<"INFO  "<<__FUNCTION__<<" "; \
+    sprintf(_lbuf," (%s : %d) ",fn,__LINE__); m_log<<_lbuf; \
+    sprintf(_lbuf,fmt,##args); m_log<<_lbuf; \
+  }  \
+  } while (0)
+
+#define GEN_LOG_WARN(fmt,args...) do {\
+  char _lbuf[1024]; \
+  if (m_log.is_open()) { \
+    m_log<<"WARN  "<<__FUNCTION__<<" "; \
+    sprintf(_lbuf," (%s : %d) ",__FILENAME__,__LINE__); m_log<<_lbuf; \
+    sprintf(_lbuf,fmt,##args); m_log<<_lbuf; \
+  }  \
+  } while (0)
+
+#define GEN_LOG_ERROR(fmt,args...) do {\
+  char _lbuf[1024]; \
+  if (m_log.is_open()) { \
+    m_log<<"ERROR "<<__FUNCTION__<<" "; \
+    sprintf(_lbuf," (%s : %d) ",__FILENAME__,__LINE__); m_log<<_lbuf; \
+    sprintf(_lbuf,fmt,##args); m_log<<_lbuf; \
+  }  \
+  } while (0)
+#endif
+namespace  asn1
+{
+
+
+struct generator_config
+{
+  generator_config()
+   : m_printf(true) 
+           , m_ber(true)
+           , m_per(false)
+           , m_xer(false)
+           , m_jer(false)
+           , m_ots(false)
+           , m_oer(false)
+           , m_template(false)
+           , m_debug(true)
+           , m_source_comment(true) 
+           , m_source_debug(false) 
+           , m_codec(false) 
+           , m_split_cpp(false) 
+  {}; 
+#define WITH_CODEC(nm) \
+  bool with_##nm() { return m_##nm; } ; \
+  void with_##nm(bool b) { m_##nm = b ; } ;
+  WITH_CODEC(ber)
+  WITH_CODEC(per)
+  WITH_CODEC(xer)
+  WITH_CODEC(jer)
+  WITH_CODEC(printf)
+  WITH_CODEC(oer)
+  WITH_CODEC(template)
+  WITH_CODEC(debug)
+  WITH_CODEC(source_comment)
+  WITH_CODEC(source_debug)
+  WITH_CODEC(nested)
+  WITH_CODEC(codec)
+  WITH_CODEC(split_cpp)
+#undef WITH_CODEC  
+  // generator configuration flags
+  bool    m_printf;
+  bool    m_ber;
+  bool    m_per;
+  bool    m_xer;
+  bool    m_ots;
+  bool    m_jer;
+  bool    m_oer;
+  bool    m_template; // tells if we generate template file or cpp file
+  bool    m_debug;
+  bool    m_source_comment;
+  bool    m_source_debug;
+  bool    m_nested;
+  bool    m_codec;   //  Remove codec function code 
+  bool    m_split_cpp;   //  Implementation in separated cpp files 
+
+};
+
+/**
+ *
+ */ 
+class generator
+{
+  protected:
+    generator(const generator &g) : m_resolver(g.m_resolver) {};
+  public:
+    typedef std::map<std::string,asn1::node * > SymbolMap;
+    typedef SymbolMap::iterator                 SymbolMap_iterator;
+    typedef SymbolMap::const_iterator           SymbolMap_const_iterator;
+
+    generator(module *n = NULL);
+    
+    generator(module *root_m,asn1::module::modules_type &m_)  ;
+
+    virtual ~generator() {};
+
+    void set_config(const generator_config &c) { m_config = c; } 
+    generator_config &get_config() { return m_config; }
+    
+    // Set and getters
+    //
+    module *get_module() const { return m_module ; };
+    
+    asn1::module::modules_type  &get_module_list() { return m_modules;};
+    
+    //
+    void oid_value(asn1::node *n,int *pos,std::vector<unsigned char> *v);
+
+    void encode_integer(long value,std::vector<unsigned char> &v);
+
+    // Tells if a the structure should be in the form of templale
+#define WITH_CODEC(nm) \
+    bool with_##nm() { return m_config.m_##nm; } ;   
+    WITH_CODEC(ber)
+    WITH_CODEC(per)
+    WITH_CODEC(xer)
+    WITH_CODEC(jer)
+    WITH_CODEC(printf)
+    WITH_CODEC(oer)
+    WITH_CODEC(template)
+    WITH_CODEC(debug)
+    WITH_CODEC(source_comment)
+    WITH_CODEC(source_debug)
+    WITH_CODEC(codec)
+    WITH_CODEC(split_cpp)
+#undef WITH_CODEC  
+  // generator configuration flags
+    // or not
+    bool is_template(asn1::node *params);
+
+    virtual void gen_const(std::ostream &os,node  *) = 0;
+    
+    virtual void gen_typedef(std::ostream &os,typenode  *) = 0;
+    
+    virtual void gen_set_of(std::ostream &os,set_of  &) {};
+    
+    virtual void gen_sequence_of(std::ostream &os,sequence_of  &) {};
+    
+    virtual void gen_seq(std::ostream &os,sequence  &) {};
+    
+    virtual void gen_choice(std::ostream &os,choice  &) {};
+    
+    virtual void gen_object(std::ostream &os,node  *) {};
+    
+    virtual void gen_module(std::ostream &os,module  *) = 0;
+    
+    virtual  void gen(std::ostream &os,const std::string &s = "gen"); 
+    // return the choosen tagging mode
+    int tag_mode(asn1::node *node) const;
+    /**
+     *
+     */
+    bool is_tag_explicit(asn1::typenode &_type) const ;
+    /**
+     * This function loops over alll childs in module and 
+     * depending on the meta type call gen_typedef,gen_const,
+     */
+    int type2tagid(int v) const;
+
+    //bool size_range(asn1::node * type,long &start ,long &end);
+    /**
+     * Generic function that is going to check if 
+     * a type is imported.
+     * DEPRECATED. Use resolver  
+     */
+    bool type_in_imports(asn1::node *type,asn1::node **ns) ;
+    bool type_in_imports(const std::string &type,asn1::node **ns) ;
+    /**
+     * Find a referenced value 
+     */
+    bool loockup_value(const std::string &_v,asn1::node **ov) ;
+    /**
+     * Find the appropriate class node
+     */
+    bool loockup_class(const std::string &_v,asn1::node **ov) ;
+    /**
+     * Find the primary type for a typeref type
+     */
+    bool loockup_prim_type(const std::string &_v,asn1::node **ov) ;
+    
+    /**
+     * DEPRECATED, use resolver
+     */ 
+    bool get_type_in_module(const std::string &mod_name,const std::string &typ_name,asn1::node **n) ;
+    
+    /** 
+     * Usefull object functions
+     */
+    inline void set_gen_printf(bool _b) { m_config.m_printf = _b;};
+    inline bool do_gen_printf() {return m_config.m_printf;};
+
+    bool have_attributes_to_init(const asn1::constructed *type) const ;
+    // for optimization purpose
+    void reference_chaine(asn1::typeref *type, std::list<asn1::node *> &lst);
+  
+    void path2modulestring(asn1::node *type,std::string &s);
+    /**
+     *
+     */ 
+    std::fstream &logger() { return m_log; };
+    /**
+     * Give access to the resolver for helper classes
+     */ 
+    asn1::resolver &resolver() { return m_resolver; };
+    /**
+     * if the symbol does not exists, add it and return true.
+     * if the symbol exists in the map, return false;
+     */ 
+    bool add_symbol(std::string &name,asn1::node *);
+  protected:
+    std::fstream m_log;
+    module       *m_module;
+    SymbolMap    m_symbols;
+    asn1::module::modules_type  m_modules;
+    generator_config            m_config;
+    asn1::resolver              m_resolver;
+};
+
+}
+
+/*
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libgen/asn1_generator_helper.h b/libgen/asn1_generator_helper.h
new file mode 100644 (file)
index 0000000..275e8ba
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef ASN1_GENERATOR_HELPER_H
+#define ASN1_GENERATOR_HELPER_H
+
+/**
+ * This class defines the interface that each 
+ *    asn1 type generation should implement ....
+ *    -- typedef sequence generator
+ *    -- typedef choice   generator
+ *    -- typedef set      generator
+ *    -- typedef set  of  generator
+ *    -- typedef sequ of  generator
+ *
+ *    This allows us to split and isolate the generation
+ *    code .... and simplifity the readability
+ */ 
+class generator_helper
+{
+  public:
+    generator_helper(std::ostream &os) : m_os(os) { } ;
+  
+    // generate entry point
+    virtual void generate()  {};
+    // generate codec part
+    virtual void generate_per() = 0;
+    //
+    virtual void generate_ber() = 0;
+    //
+    virtual void generate_oer() = 0;
+    //
+    virtual void generate_jer() = 0;
+    //
+    virtual void generate_xer() = 0;
+
+    // generate encoder
+    // generate decoder
+    // generate constructor
+    // generate 
+  protected:
+    std::ostream &m_os;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpp_helper.cpp b/libgen/cpp/cgcpp_helper.cpp
new file mode 100644 (file)
index 0000000..c9194f1
--- /dev/null
@@ -0,0 +1,64 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+
+
+/**
+ * constructor
+ */
+cgcpp_helper::cgcpp_helper( generate_codec_cpp &g
+                          , std::ostream       &os
+                         )
+  : m_gencpp(g), generator_helper(os),m_log(g.logger())
+{
+}
+
+/**
+ *
+ * @brief common way to generate the required code depending
+ * on the global settings given to the asn1 parser.
+ */
+void
+cgcpp_helper::generate()
+{
+  generate_descriptor();
+
+  generate_members();
+
+  generate_ctors();
+
+  generate_operators();
+
+  generate_printf();
+  /* codec function generators */
+  if (m_gencpp.with_ber())
+  {
+    generate_ber();
+  }
+  if (m_gencpp.with_oer())
+  {
+    generate_oer();
+  }
+  if (m_gencpp.with_jer())
+  {
+    generate_jer();
+  }
+  if (m_gencpp.with_per())
+  {
+    generate_per();
+  }
+}
+
+void 
+cgcpp_helper::generate_descriptor()
+{
+}
+
+
diff --git a/libgen/cpp/cgcpp_helper.h b/libgen/cpp/cgcpp_helper.h
new file mode 100644 (file)
index 0000000..71d6545
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef CODE_GEN_CPP_HELPER_H
+#define CODE_GEN_CPP_HELPER_H
+
+/**
+ * This class defines the interface that each 
+ *    asn1 type generation should implement ....
+ * Unlike generator_helper, this class provides a first
+ * level of functions dedicated to c++ code generation. The goal is
+ * to move the generation from one unique file to one file per type.
+ *   -> provide streams for cpp,h and hpp.
+ *   -> provide generic preamble et epilog
+ *   -> open /close stream 
+ */ 
+class cgcpp_helper : public generator_helper
+{
+  public:
+    cgcpp_helper( generate_codec_cpp &g
+                , std::ostream       &os
+                );
+  
+    // generate entry point
+    virtual void generate()  ;
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() {};
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {};
+
+    // Type of code generated in CPP files
+    virtual void generate_ctors() {};
+
+    virtual void generate_printf() {};
+
+    virtual void generate_descriptor() ;
+
+    virtual void generate_members() {};
+
+    virtual void generate_operators() {};
+    // generate encoder
+    // generate decoder
+    // generate constructor
+    // generate 
+  protected:
+    std::fstream          &m_log;
+    generate_codec_cpp    &m_gencpp;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_bitstring.cpp b/libgen/cpp/cgcpph_bitstring.cpp
new file mode 100644 (file)
index 0000000..9c7eed2
--- /dev/null
@@ -0,0 +1,239 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_construct.h"
+#include "cgcpph_bitstring.h"
+
+
+/**
+ *
+ *
+ */ 
+cgcpph_bit_string::cgcpph_bit_string(generate_codec_cpp &g,std::ostream &os,asn1::bit_string &s)
+  : cgh_construct(g,os,s) , m_bit_string(s) 
+{
+}
+
+/**
+ *
+ *
+ */ 
+cgcpph_bit_string::~cgcpph_bit_string()
+{
+}
+
+
+/** Helper functions
+ *
+ */ 
+void cgcpph_bit_string::generate(const std::string &scope)
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_bit_string helper launched "<<std::endl;
+  cgcpp_helper::generate();
+}
+
+//
+void cgcpph_bit_string::generate_ctors( )
+{
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_structName<<" &c) : BIT_STRING()\n{\n}\n";
+  // With tag
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const asn1::tag &t) : BIT_STRING(t)\n{\n}\n";
+}
+
+
+//
+void cgcpph_bit_string::generate_printf( )
+{
+ // std::string structName = type->identifier()->cpp_name();
+  
+  m_os<<"std::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<(BIT_STRING)s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_bit_string::generate_per()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_bit_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    /* template specialisation hpp */
+    // m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecPER::encode(streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecPER::decode(streams::per &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// bit_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_bitstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_bitstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_bit_string::generate_ber()
+{
+  std::string scope;
+  std::string structName = m_bit_string.identifier_cpp_name();
+
+
+
+  //
+  if (m_bit_string.tagged())
+  {
+    if ( m_gencpp.tag_mode(&m_bit_string) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<scope<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_bit_string.tag().m_class<<","<<m_bit_string.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,3));\n";
+      m_os<<"\tctx.encode_bitstring(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<scope<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_bit_string.tag().m_class<<","<<m_bit_string.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\tBIT_STRING tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp.get_value();\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_bit_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    /* template specialisation hpp */
+    // m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// bit_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if ( m_bit_string.tagged()
+         && ( m_gencpp.is_tag_explicit(m_bit_string)))
+    {
+      //cpp<<"\tint len;\n";
+      cpp<<"\tasn1::tag t("<<m_bit_string.tag().m_class<<","<<m_bit_string.tag().m_value<<",true);\n";
+      //cpp<<"\tstd::cout<<\"codecBER::encode "<<structName<<" TODO\"<<std::endl;\n"<<std::endl;
+      cpp<<"\tencode_tag(c,t,_t.get_length());\n";
+    }
+    cpp<<"\tc.encode_bitstring(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    if ( m_bit_string.tagged()
+         && ( m_gencpp.is_tag_explicit(m_bit_string) ))
+    {
+      cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" TODO\"<<std::endl;\n"<<std::endl;
+    }
+    cpp<<"\treturn c.decode_bitstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_bit_string::generate_oer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_bit_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    /* template specialisation hpp */
+    // m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// bit_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_integer(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_bit_string::generate_jer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_bit_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    /* template specialisation hpp */
+    // m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// bit_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_bitstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_bitstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_bit_string::generate_xer()
+{
+}
+/* vi: set ts=2 sw=2 sts=2 et: */
diff --git a/libgen/cpp/cgcpph_bitstring.h b/libgen/cpp/cgcpph_bitstring.h
new file mode 100644 (file)
index 0000000..9f92a4f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef CGCPPH_BITSTRING_H
+#define CGCPPH_BITSTRING_H
+
+
+/**
+ *
+ */
+class cgcpph_bit_string : public cgh_construct
+{
+  protected:
+    cgcpph_bit_string(const  cgcpph_bit_string &s) :  cgh_construct(s)
+                                     , m_bit_string(s.m_bit_string) {}  
+  public:
+    cgcpph_bit_string(generate_codec_cpp &g,std::ostream &os,asn1::bit_string &s) ;
+    ~cgcpph_bit_string();
+    
+    // Helper functions
+    virtual void generate(const std::string &scope) ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_ctors();
+    
+    virtual void generate_printf( );
+  protected:  
+    asn1::bit_string      &m_bit_string;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_boolean.cpp b/libgen/cpp/cgcpph_boolean.cpp
new file mode 100644 (file)
index 0000000..1827237
--- /dev/null
@@ -0,0 +1,242 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_primitive.h"
+#include "cgcpph_boolean.h"
+
+
+cgcpph_boolean::cgcpph_boolean(generate_codec_cpp &g,std::ostream &os,asn1::boolean &s)
+  : cgcpph_primitive(g,os,s)
+  , m_boolean(s)
+{
+}
+
+cgcpph_boolean::~cgcpph_boolean()
+{
+}
+
+/** Helper functions
+ *
+ *  
+ */ 
+void cgcpph_boolean::generate_ctors()
+{
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"// cgcpph_boolean helper launched ";
+    m_os<<m_structName<<"\n";
+  }
+  GEN_LOG_DEBUG("cgcpph_boolean::generate node=%s\n",m_boolean.identifier_cpp_name().c_str());
+  // May be just include each module ...
+  m_os<<"\n"<<m_structName;
+  m_os<<"::"<<m_structName<<"(const asn1::tag &t) : BOOLEAN(t)\n{\n}\n";
+  m_os<<"\n// Copy Constructor "<<m_structName<<"\n//\n";
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_structName<<" &c) : BOOLEAN()\n{\n}\n";
+}
+
+/**
+ *
+ */
+void cgcpph_boolean::generate_operators()
+{
+  gen_equal();
+}
+
+/**
+ *
+ */
+void cgcpph_boolean::gen_equal()
+{
+  m_os<<"\n// comparaison "<<m_structName<<"\n//\n";
+  m_os<<"bool\n"<<m_structName;
+  m_os<<"::operator =="<<"( "<<m_structName<<" &t)\n{\n";
+  m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+ /**
+  *
+  */
+void cgcpph_boolean::generate_printf()
+{
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<(BOOLEAN)s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_boolean::generate_per()
+{
+  //
+  std::string  ns        = m_gencpp.get_module()->cpp_name();
+       std::string structName(ns + "::" + m_boolean.identifier_cpp_name());
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecPER::encode(streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecPER::decode(streams::per &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// boolean generator"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_boolean(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_boolean(_t);\n";
+    cpp<<"}\n";
+
+  }
+}
+
+//
+void cgcpph_boolean::generate_ber()
+{
+  //
+  if (m_boolean.tagged())
+  {
+    std::string structName = m_boolean.identifier_cpp_name();
+    if ( m_gencpp.tag_mode(&m_boolean) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_boolean.tag().m_class<<","<<m_boolean.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,1));\n";
+      m_os<<"\tctx.encode_boolean(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_boolean.tag().m_class<<","<<m_boolean.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\tBOOLEAN tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp.get_value();\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+  /**
+   * New way with codec ....
+        */ 
+  if (m_gencpp.with_codec())
+  {
+    std::string structName;
+    std::string  ns        = m_gencpp.get_module()->cpp_name();
+    structName  = ns + "::" + m_boolean.identifier_cpp_name();
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    /* header template specialisation */
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+    /* Implementation part */
+    cpp<<"// boolean generator"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if (m_boolean.tagged()
+      && (m_gencpp.tag_mode(&m_boolean) == asn1::node::tag_type::TM_EXPLICIT))
+    {
+      // I should encode explicit tag here
+      cpp<<"\tasn1::tag t("<<m_boolean.tag().m_class<<","<<m_boolean.tag().m_value<<",true);\n";
+      cpp<<"\tstd::cerr<<\"encode explicit tagging for BER TODO\"<<std::endl;\n";
+      cpp<<"\tc.encode_boolean(_t);";
+    } else
+      cpp<<"\tc.encode_boolean(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_boolean(_t);\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_boolean::generate_oer()
+{
+  //
+  std::string  ns        = m_gencpp.get_module()->cpp_name();
+       std::string structName(ns + "::" + m_boolean.identifier_cpp_name());
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// boolean generator"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_boolean(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_boolean(_t);\n";
+    cpp<<"}\n";
+
+  }
+}
+
+//
+void cgcpph_boolean::generate_jer()
+{
+  std::string structName = m_gencpp.get_module()->cpp_name();
+  std::string  ns        = m_gencpp.get_module()->cpp_name();
+  structName  = ns + "::" + m_boolean.identifier_cpp_name();
+  std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+  std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+
+  if (m_gencpp.with_codec())
+  {
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"// boolean generator"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_boolean(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_boolean(_t);\n";
+    cpp<<"}\n";
+
+  }
+}
+
+//
+void cgcpph_boolean::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_boolean.h b/libgen/cpp/cgcpph_boolean.h
new file mode 100644 (file)
index 0000000..7aa4e96
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CGCPPH_BOOLEAN_H
+#define CGCPPH_BOOLEAN_H
+
+
+/**
+ *
+ */
+class cgcpph_boolean : public cgcpph_primitive
+{
+  protected:
+    cgcpph_boolean(const  cgcpph_boolean &s) : cgcpph_primitive(s)
+                                      , m_boolean(s.m_boolean)
+    {}  
+  public:
+    cgcpph_boolean(generate_codec_cpp &g,std::ostream &os,asn1::boolean &s) ;
+   
+    ~cgcpph_boolean();
+    
+    // Helper functions
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_ctors();
+    virtual void generate_operators();
+
+    void gen_equal();
+    
+    virtual void generate_printf();
+  protected:
+    asn1::boolean         &m_boolean;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_choice.cpp b/libgen/cpp/cgcpph_choice.cpp
new file mode 100644 (file)
index 0000000..9cee759
--- /dev/null
@@ -0,0 +1,1159 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "asn1_visitor.h"
+#include "cgh_construct.h"
+#include "cgcpph_choice.h"
+
+
+cgcpph_choice::cgcpph_choice(generate_codec_cpp &g,std::ostream &os,asn1::choice &s)
+  : cgh_construct(g,os,s)
+  , m_choice(s) 
+{
+}
+
+cgcpph_choice::~cgcpph_choice()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgcpph_choice::generate()
+{
+  
+  GEN_LOG_DEBUG("cgcpph_choice::generate node=%s\n",m_choice.identifier_cpp_name().c_str());
+  
+  // End generate private ...
+
+  cgcpp_helper::generate();
+  
+  if (m_gencpp.with_codec())
+    gen_codec();
+  // Generate encoders and decoders
+}
+
+/**
+ *
+ */
+void cgcpph_choice::generate_descriptor()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_choice helper launched "<<m_structName<<std::endl; 
+
+  gen_member_table();
+  gen_tag2el_table();
+
+  m_os<<"static asn1::types::descriptor CHOICE_"<<m_structName<<" = {\n";
+  m_os<<"  NULL,0,";
+  m_os<<"  MEMBER_"<<m_structName<<",\n";
+  m_os<<"  "<<m_elcount<<",\n";
+  m_os<<"  MAP_"<<m_structName<<"_tag2el,\n";
+  m_os<<"  "<<m_t2elcount<<",\n";
+  m_os<<"};\n";
+  m_os<<std::endl;
+}
+/**
+ *
+ */
+void cgcpph_choice::generate_ctors()
+{
+  // Generate functions constructors and  so on
+  gen_ctor( );
+  
+  m_os<<std::endl;
+  gen_create_object( );
+  
+  m_os<<std::endl;
+  gen_clone( );
+}
+/**
+ *
+ */
+void cgcpph_choice::generate_members()
+{
+  // Generate setters and getters, private and missing
+  // Loop over all attributes
+    for (asn1::node::iterator lit = m_choice.begin()
+         ; lit != m_choice.end() 
+         ; ++lit)
+    {
+      asn1::field    *f  = dynamic_cast<asn1::field *>(*lit);
+      asn1::typenode *ft = f->get_type();
+
+      if (m_gencpp.with_source_comment())
+      {
+        m_os<<"//gen_choice preproc="<<f->cpp_name();
+        m_os<<" private="<<m_choice.is_private()<<std::endl;
+      }
+      if ( ft != NULL)
+      {
+        GEN_LOG_DEBUG("call gen_private_attribute for %s type=%s\n",
+                                                 f->cpp_name().c_str()
+                                               , ft->name().c_str());
+        if (m_gencpp.with_source_comment())
+          m_os<<"// gen_choice call gen_private_attribute: "<<f->cpp_name()<<std::endl;
+        
+        m_gencpp.gen_private_attribute( m_os
+                                   , std::string("")
+                                   , ft);
+        
+      } else
+      {
+          m_os<<"// priv? extension "<<f->cpp_name()<<std::endl;
+      }
+      // May here 
+      asn1::node *params = m_choice.act_parameters();
+   
+      gen_attribute_setter( m_structName+"::"
+                          , m_structName
+                          , f
+                          , params
+                          , m_choice.is_private());
+  }
+}
+
+/**
+ *
+ */
+void cgcpph_choice::generate_operators()
+{
+  gen_equal(m_structName);
+}
+
+
+// Old codec function. Will probably be removed
+void cgcpph_choice::gen_codec( )
+{
+  std::string ns = m_gencpp.get_module()->cpp_name();
+  std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+  //m_gencpp.gen_template_signature(m_os,type);
+  hpp<<"\n// choice type "<<"::"<<m_structName<<"\n";
+  if (m_gencpp.with_jer())
+  {
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<ns<<"::"<<m_structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<ns<<"::"<<m_structName<<" &_t);\n";
+  }
+
+
+}
+/**
+ * 
+ * Choice code and decode
+ *
+ */
+void cgcpph_choice::gen_codec_decode(const std::string &scope)
+{
+  asn1::node *type = &m_choice;
+  
+  asn1::node *n = type->identifier();
+  
+  m_os<<"\t\tunsigned long pos = ctx.bytes();"<<std::endl;
+  m_os<<"\t\tunsigned char *b = ctx.buffer();"<<std::endl;
+  
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\"DECODE CHOICE start ";
+    m_os<<n->cpp_name()<<" tag = %02x \",(unsigned short)b[pos]);"<<std::endl;
+  }
+  m_os<<"\t\treturn decode(ctx);"<<std::endl;
+  
+  // Now add an enum to identifie type
+  // m_os<<"\t\tASN1_BER_LOG_DEBUG(\"DECODE CHOICE END "<<n->cpp_name()<<" none selected tag = %02x WRONG\",(unsigned short)b[pos]);"<<std::endl;
+  m_os<<"\t\treturn asn1::wrong_tag;\n";
+}
+
+/**
+ *
+ */
+void cgcpph_choice::gen_codec_encode(const std::string &scope)
+{
+  asn1::node *type = &m_choice;
+  
+  asn1::node *n = type->identifier();
+
+  if (n == NULL )
+  {
+    std::cerr<<"gen_choice_encode n == NULL"; return;
+  }
+
+  m_os<<"\t\tint _ret = asn1::ok;\n";
+  m_os<<"\t\tif (m_choice)\n";
+  m_os<<"\t\t{\n";
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\t\t\tASN1_BER_LOG_DEBUG(\""<<type->cpp_name();
+    m_os<<"::codec ENCODE tag=%d \",m_choice->tag().byte());\n";
+  }
+  m_os<<"\t\t\tencode(ctx);"<<std::endl;
+  m_os<<"\t\t}\n";
+  m_os<<"\t\treturn _ret;\n";
+
+}
+    
+//
+void 
+cgcpph_choice::gen_setter_ref( const std::string &scope
+                         , const std::string &structName
+                         , asn1::field       *attribute
+                         , asn1::typeref     &tref
+                         , asn1::node        *params
+                         , bool              priv)
+{
+  asn1::node *rt = m_gencpp.resolver().resolve(tref);
+
+  if (tref.is_simple()
+      || (rt && rt->type_node())
+      )
+  {
+    m_os<<"// Reference"<<std::endl;
+    m_os<<"void "<<scope<<"set_"<<attribute->cpp_name()<<"(const ";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" &s)\n{\n";
+    m_os<<"\tif (m_kind != typeof_"<<attribute->cpp_name()<<" )\n";
+    m_os<<"\t{\n";
+#if 1
+    asn1::node::tag_type  o_tag = tref.otag(m_gencpp.resolver());
+    m_os<<"\t\tchoice_type::set_tag(asn1::tag(";
+    m_os<<o_tag.m_class<<","<<o_tag.m_value<<"));\n";
+#else
+    m_os<<"\t\t"<<"if (m_choice)\n\t\t\tdelete m_choice;\n";
+    m_os<<"\t\tm_kind = typeof_"<<attribute->cpp_name()<<";\n";
+    m_os<<"\t\tcreate_object();\n";
+#endif
+    m_os<<"\t}\n";
+
+    m_os<<"\tget_"<<attribute->cpp_name()<<"() = s;\n";
+    m_os<<"};\n"<<std::endl;
+  } else
+  {
+    m_os<<"// setter to DO set_"<<attribute->cpp_name()<<std::endl;
+    m_os<<"void "<<scope<<"set_"<<attribute->cpp_name()<<"(const ";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" *s)\n{\n";
+    m_os<<"\tassert(0);\n";
+    m_os<<"};\n"<<std::endl;
+  }
+}
+
+//
+void
+cgcpph_choice::gen_getter_ref( const std::string &scope
+                         , const std::string &structName
+                         , asn1::field       *attribute
+                         , asn1::typeref     &tref
+                         , asn1::node        *params
+                         , bool              priv)
+{
+  asn1::node *rt = m_gencpp.resolver().resolve(tref);
+  if (tref.is_simple()
+      || (rt && rt->type_node())
+      )
+  {
+    // getter
+    m_gencpp.gen_composite_attribute_ref( m_os
+                                      ,scope
+                                      ,attribute
+                                      ,params);
+    m_os<<" &"<<scope<<"get_"<<attribute->cpp_name()<<"()\n{\n";
+    // Debug Version
+    m_os<<"#ifdef DEBUG"<<std::endl; 
+    if (m_gencpp.with_source_debug())
+    {
+      m_os<<"\tASN1_BER_LOG_DEBUG(\"get_"<<attribute->cpp_name();
+      m_os<<"(%p) "<<attribute->cpp_name()<<" k=%d tag=%ld\",this,m_kind,m_tag.get_tag());\n";
+    }
+    /**/
+    asn1::node::tag_type  o_tag = tref.otag(m_gencpp.resolver());
+    m_os<<"\t"<<"if ( m_kind != typeof_"<<attribute->cpp_name()<<")\n\t{\n";
+    m_os<<"\t\t"<<"set_tag( asn1::tag(";
+    m_os<<o_tag.m_class<<","<<o_tag.m_value<<"));\n";
+    m_os<<"\t}\n";
+    /**/
+    m_os<<"\tassert(check_create());"<<std::endl;
+    m_os<<"\tassert(dynamic_cast<";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" *>(m_choice) != NULL);"<<std::endl;
+    //os<<"\tif (m_kind == typeof_"<<attribute->cpp_name()<<") {\n";
+    m_os<<"\treturn dynamic_cast<";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" &>(*m_choice);\n";
+    // Release Version
+    m_os<<"#else"<<std::endl; 
+    m_os<<"\t"<<"if ( m_kind != typeof_"<<attribute->cpp_name()<<")\n";
+    m_os<<"\t\t"<<"set_tag( asn1::tag(";
+    m_os<<o_tag.m_class<<","<<o_tag.m_value<<"));\n";
+    m_os<<"\treturn dynamic_cast<";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" &>(*m_choice);\n";
+    m_os<<"#endif"<<std::endl; 
+    // m_os<<"/* TODO unfinished*/ 
+    m_os<<"}\n";
+    /* const getter */
+    m_os<<"const ";
+    m_gencpp.gen_composite_attribute_ref( m_os
+                                      ,scope
+                                      ,attribute
+                                      ,params);
+    m_os<<" &"<<scope<<"get_"<<attribute->cpp_name()<<"() const\n{\n";
+    m_os<<"\treturn dynamic_cast<const ";
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" &>(*m_choice);\n";
+    m_os<<"}\n";
+  } else
+  {
+    m_os<<"// getter to DO get_"<<attribute->cpp_name()<<std::endl;
+    m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    m_os<<" *"<<scope<<"get_"<<attribute->cpp_name()<<"()\n{\n";
+    m_os<<"assert(0);\n";
+    //m_os<<"\t\treturn dynamic_cast<";
+    //m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+    //m_os<<" &>(*m_choice);\n";
+    m_os<<"}\n";
+  }
+}
+
+
+
+//
+void
+cgcpph_choice::gen_attribute_setter( const std::string &scope
+                                   , const std::string &structName
+                                   , asn1::field       *attribute
+                                   , asn1::node        *params
+                                   , bool              priv) 
+{
+  asn1::typenode *attr_type = attribute->get_type();
+  
+  if (attr_type != NULL)
+  {
+    switch (attr_type->type_id()())
+    {
+      case asn1::type::ASN1_ENUMERATED:
+      case asn1::type::ASN1_CHOICE:
+      case asn1::type::ASN1_SET:
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          m_os<<"//\nvoid "<<scope<<"set_"<<attribute->cpp_name();
+          m_os<<"(const "<<attribute->cpp_name()<<"_t";
+          m_os<<" &s)\n{\n\tm_kind = typeof_"<<attribute->cpp_name();
+          m_os<<";\n";
+          m_os<<"\tget_"<<attribute->cpp_name()<<"()=s;\n}\n\n"<<std::endl;
+          std::string strtype;
+          
+          if (m_gencpp.type2cppstring(attr_type,strtype) )
+          {
+            m_os<<scope<<strtype<<" &"<<scope<<"get_"<<attribute->cpp_name()<<" ()\n{\n";
+            m_os<<"\tassert(check_create());\n";
+            m_os<<"\tif (m_kind == typeof_"<<attribute->cpp_name()<<")\n\t{\n";
+            m_os<<"\t\treturn static_cast<"<<strtype<<" &>(*m_choice);\n";
+            m_os<<"\t} else {\n";
+            m_os<<"\t\tif (m_choice)\n\t\t{\n";
+            m_os<<"\t\t\tdelete m_choice;\n\t\t\t m_choice = NULL;\n";
+            m_os<<"\t\t\tm_kind = typeof_"<<attribute->cpp_name()<<";\n";
+            m_os<<"\t\t\tcreate_object();\n";
+            m_os<<"\t\t\tassert( m_choice != NULL);\n";
+            m_os<<"\t\t}\n";
+            m_os<<"\t\treturn static_cast<"<<strtype<<" &>(*m_choice);\n";
+            m_os<<"\t}\n";
+            m_os<<"}\n";
+          }
+        } 
+        break;
+      case asn1::type::ASN1_REFERENCE:
+        {
+          asn1::typeref *tref  = dynamic_cast<asn1::typeref *>(attr_type);
+          gen_setter_ref(scope,structName,attribute,*tref,params,priv);
+          gen_getter_ref(scope,structName,attribute,*tref,params,priv);
+        }
+        break;
+      default:
+        {
+          std::string strtype;
+          if (m_gencpp.type2cppstring(attr_type,strtype,scope) )
+          {
+            m_os<<"//cgcpph_choice::"<<__FUNCTION__<<" default: "<<attribute->cpp_name()<<std::endl;
+            m_os<<"void "<<scope<<"set_"<<attribute->cpp_name()<<"(const ";
+            m_os<<strtype;
+            m_os<<" &s)\n {\n";
+            m_os<<"\tif (m_kind != typeof_"<<attribute->cpp_name()<<" )\n";
+            m_os<<"\t{";
+            if (attr_type->tagged())
+            { // Tagged value
+               asn1::node::tag_type tg = attr_type->tag();
+               m_os<<"\t\tset_tag(asn1::tag("<<tg.m_class<<","<<tg.m_value<<"));\n";
+            }
+            else
+            {
+              //assert(0 && "Attribute in choice should have a tag");
+              asn1::node::tag_type tg = attr_type->tag();
+              //std::cerr<<"attribute "<<attribute->cpp_name()<<" not tagged(0,"<<tg.m_value<<") !!!"<<std::endl;
+              m_os<<"\t\tset_tag(asn1::tag("<<tg.m_class<<","<<tg.m_value<<"));\n";
+            }
+            m_os<<"\t\t"<<"if (m_choice) {\n\t\t\tdelete m_choice;\n";
+            m_os<<"\t\t\tm_choice = NULL;\n\t\t}"<<std::endl;
+            m_os<<"\t\tm_kind = typeof_"<<attribute->cpp_name()<<";\n";
+            m_os<<"\t\tcreate_object();\n";
+            m_os<<"\t}\n";
+            //os<<"\t"<<attribute->cpp_name()<<"\t=\ts;\n";
+            m_os<<"\tget_"<<attribute->cpp_name()<<"() = s;\n";
+            m_os<<"}\n"<<std::endl;
+            // get function
+            m_os<<strtype<<" &"<<scope<<"get_"<<attribute->cpp_name()<<" ()\n{\n";
+            m_os<<"\tif (m_kind != typeof_"<<attribute->cpp_name()<<" )\n";
+            m_os<<"\t{";
+            if (attr_type->tagged())
+            { // Tagged value
+               asn1::node::tag_type tg = attr_type->tag();
+               m_os<<"\t\tset_tag(asn1::tag("<<tg.m_class<<","<<tg.m_value<<"));\n";
+            }
+            else
+            {
+              //assert(0 && "Attribute in choice should have a tag");
+              asn1::node::tag_type tg = attr_type->tag();
+              std::cerr<<"attribute "<<attribute->cpp_name()<<" not tagged(0,"<<tg.m_value<<") !!!"<<std::endl;
+              m_os<<"\t\tset_tag(asn1::tag("<<tg.m_class<<","<<tg.m_value<<"));\n";
+            }
+            m_os<<"\t}\n";
+            m_os<<"\tassert(check_create());"<<std::endl;
+            m_os<<"\tif (m_kind == typeof_"<<attribute->cpp_name()<<")\n\t{\n";
+            m_os<<"\t\treturn static_cast<"<<strtype<<" &>(*m_choice);\n";
+            m_os<<"\t} else\n\t{\n";
+            m_os<<"\t\tif (m_choice)\n";
+            m_os<<"\t\t{\n";
+            m_os<<"\t\t\tdelete m_choice;\n";
+            m_os<<"\t\t\tm_choice = NULL;\n";
+            m_os<<"\t\t\tm_kind = typeof_";
+            m_os<<attribute->cpp_name()<<"; create_object() ;\n";
+            m_os<<"\t\t}\n";
+            m_os<<"\t\treturn static_cast<"<<strtype<<" &>(*m_choice);\n";
+            m_os<<"\t}\n";
+            m_os<<"}\n";
+            /* const*/
+            m_os<<"const "<<strtype<<" &"<<scope<<"get_"<<attribute->cpp_name()<<" () const\n{\n";
+            m_os<<"\treturn dynamic_cast<const "<<strtype<<" &>(*m_choice);\n";
+            m_os<<"}\n";
+          }
+        }
+        break;
+    }
+  } else 
+  {
+    GEN_LOG_ERROR("attr_type is NULL\n");
+  }
+
+}
+
+// Helper function to replace :: with _ in scope
+static 
+char  lop_substitute(char c)
+{
+    return (c == ':')?'_':c;
+}
+
+//
+void cgcpph_choice::generate_printf()
+{
+  asn1::node::iterator lit;
+  asn1::node *ident  = m_choice.identifier();
+
+  
+  // FIND ANOTHER NAME FOR THAT DEFINE ASN1_WITH_PRINTF
+  m_os<<"#if 1\n";
+  // ostream function
+  m_os<<"std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+
+  if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s)\n";
+
+  m_os<<"{\n";
+  // Ok, Now, deal with the attributes and so on 
+  //
+  //os<<"\tif (s.m_choice != NULL)"<<std::endl;
+  m_os<<"\ts.printf(os);"<<std::endl;
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+  m_os<<"#endif\n";
+}
+
+// generate codec part
+void cgcpph_choice::generate_per()
+{
+}
+
+//
+void cgcpph_choice::generate_ber()
+{
+  std::string ns = m_gencpp.get_module()->cpp_name();
+  std::string structName( ns + "::" + m_choice.identifier_cpp_name() );
+  std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+  std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+  bool priv = m_choice.is_private();
+  
+  // Generator for encode en decode wrong place
+  gen_ber_encode("",m_choice.identifier_cpp_name(),priv);
+  gen_ber_decode("",m_choice.identifier_cpp_name(),priv)
+    ;
+  if (m_gencpp.with_codec())
+  {
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// choice type "<<structName<<"\n";
+    hpp<<"template<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    /**
+     *  Implementation part codec encode
+     */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if (m_gencpp.with_source_debug())
+    {
+    }
+    cpp<<"}\n";
+    /**
+     *  Implementation part codec decode
+     */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tasn1::tag t(0,0);\n";
+    cpp<<"\tunsigned long    m_pos = c.bytes();\n";
+    cpp<<"\tint              len   = 0;\n";
+    cpp<<"\tif (c.decode_tag(t,len) )\n";
+    cpp<<"\t{\n";
+    cpp<<"\t\t_t.set_tag(t);\n";
+    cpp<<"\t\tif (_t.check_create())\n";
+    cpp<<"\t\t{\n";
+    // What do I do here
+    cpp<<"\t\t\tswitch (_t.m_kind)\n\t\t\t{\n";
+    for (asn1::node::iterator it = m_choice.begin(); it != m_choice.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            cpp<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            cpp<<"\t\t\tcase "<<structName<<"::typeof_"<<f->cpp_name()<<": ";
+            cpp<<"return decode(c,_t.get_"<<f->cpp_name()<<"());\n";
+         }
+      }
+    }
+    cpp<<"\t\t\t}\n";
+    cpp<<"\t\t}\n";
+    cpp<<"\t}\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+//
+  if (m_choice.tagged())
+  {
+      if ( m_gencpp.is_tag_explicit(m_choice) )
+      {
+      }
+  }
+}
+
+/**
+ *
+ *
+ */ 
+void cgcpph_choice::gen_ctor( )
+{
+  asn1::node  *type = &m_choice;
+  // Constructor
+  //
+  m_os<<""<<m_structName<<"::"<<m_structName;
+  m_os<<"(unsigned int k,const asn1::tag t)\n\t\t: asn1::types::";
+  m_os<<"choice_type(k,t,&CHOICE_"<<m_structName<<")\n{\n";
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name();
+    m_os<<"(%p) choice:: 1 "<<type->identifier_name()<<" k=%d tag=%ld\",this,k,t.get_tag());\n";
+  }
+  m_os<<"\tset_tag(t);\n";
+  m_os<<"}\n";
+
+  // New constructor without k
+  m_os<<""<<m_structName<<"::"<<m_structName;
+  m_os<<"(const asn1::tag &t)\n\t\t: asn1::types::choice_type(t.get_tag(),t";
+  m_os<<",&CHOICE_"<<m_structName<<")\n{\n";
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name();
+    m_os<<"(%p) choice:: 2 "<<type->identifier_name()<<" m_choice=%p tag=%ld\",this,m_choice,t.get_tag());\n";
+  }
+  m_os<<"\tset_tag(t);\n";
+  m_os<<"}\n";
+
+  // Needed for clone
+  m_os<<""<<m_structName<<"::"<<m_structName<<"(const "<<m_structName;
+  m_os<<" &s)\n\t\t: asn1::types::choice_type(s) \n{\n";
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name();
+    m_os<<"(%p) copy ctor "<<type->identifier_name()<<" s.m_kind=%d s.tag=%ld\",this,s.m_kind,s.m_tag.get_tag());\n";
+  }
+  m_os<<"}\n";
+  // destructor
+}
+//
+void 
+cgcpph_choice::gen_clone( )
+{
+  asn1::node  *ident        = m_choice.identifier();
+  asn1::constructed *params = NULL;
+
+  if (ident != NULL) 
+  {
+    params = ident->parameters();
+  }
+
+  m_os<<m_structName;;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<"* "<<m_structName;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\""<<m_choice.identifier_name();
+    m_os<<"::clone "<<m_choice.identifier_name()<<" \");\n";
+  }
+  m_os<<"\treturn new "<<m_structName;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<"(*this);\n}\n"<<std::endl; 
+}
+
+//
+void
+cgcpph_choice::gen_equal( const std::string  &structName)
+{
+  std::string          lscope;
+  asn1::choice        *type = &m_choice;
+  asn1::node::iterator lit  = m_choice.begin();
+  //
+  
+  lscope = structName;
+  m_os<<"bool "<<structName<<"::"<<"operator ==";
+  m_os<<"("<<structName<<" &o) \n{\n";
+  m_os<<"\tif (m_kind == o.m_kind)\n"; 
+  m_os<<"\t{\n";
+  //m_os<<"\t\treturn m_choice->equal(*(o.m_choice));\n";
+  /**
+   * Handle choices for down casting ...
+   */ 
+  m_os<<"\t\tswitch (m_kind)\n";
+  m_os<<"\t\t{\n";
+  for (; lit != (type)->end() ; lit++)
+  {
+      std::string strtype;
+      asn1::field    *field          = dynamic_cast<asn1::field *>(*lit);
+      asn1::typenode *attribute_type = field->get_type();
+      if (attribute_type == NULL)
+          continue;
+      asn1::type type_id            = attribute_type->type_id();
+      
+      if (type_id() == asn1::type::ASN1_EXTENSIBLE)
+      {
+       m_os<<"\t\t// Extensible marker"<<std::endl;
+      } else
+      {
+         m_os<<"\t\tcase typeof_"<<field->cpp_name()<<":\n";
+         m_os<<"\t\t\treturn get_"<<field->cpp_name()<<"() ==";
+         m_os<<" o.get_"<<field->cpp_name()<<"();\n";
+      }
+  }
+  m_os<<"\t\tdefault: return false;\n;"; 
+  m_os<<"\t\t}\n"; /* End switch */
+  
+  m_os<<"\t}\n";
+  m_os<<"\treturn false;\n";
+  m_os<<"}\n\n";
+}
+//
+
+//
+void cgcpph_choice::gen_ber_encode(  const std::string &scope
+                                   , const std::string &structName
+                                   , bool              priv)
+{
+  std::string lscope;
+  asn1::node *type = &m_choice; 
+  if ( m_gencpp.with_ber() 
+       && type->tagged()  
+       && m_gencpp.is_tag_explicit(m_choice) )
+  {
+    lscope = scope  + structName;
+
+    m_os<<"void "<<scope<<""<<structName<<"::";
+    m_os<<"encode_ber(asn1::streams::ber &ctx)\n{"<<std::endl;
+    m_os<<"\tunsigned long    m_pos     = ctx.bytes();"<<std::endl;
+    m_os<<"\tunsigned char   *m_buffer  = ctx.buffer();"<<std::endl;
+    // This is not good at all
+    m_os<<"\tm_buffer[m_pos++] = MAKE_TAG(";
+    m_os<<type->tag().m_class<<",1,"<<type->tag().m_value<<");"<<std::endl;
+    m_os<<"\tctx.nb_bits(16);"<<std::endl;
+    m_os<<"\tif (m_choice)"<<std::endl;
+    m_os<<"\t\tm_choice->encode(ctx);"<<std::endl;
+    m_os<<"\tif (ctx.bytes() - m_pos > 127)"<<std::endl;
+    m_os<<"\t\tASN1_BER_LOG_ERROR(\""<<lscope<<"::encode_ber too long\");"<<std::endl;
+    m_os<<"\tm_buffer[m_pos] = ctx.bytes() - m_pos-1;"<<std::endl;
+    m_os<<"\n}\n"<<std::endl;
+  }
+}
+
+//
+void 
+cgcpph_choice::gen_ber_decode( const std::string &scope
+                             , const std::string &structName
+                             , bool              priv)
+{
+  std::string lscope;
+  asn1::node *type = &m_choice; 
+  
+  if ( m_gencpp.with_ber() 
+       && type->tagged()  
+       && m_gencpp.is_tag_explicit(m_choice) )
+  {
+    lscope = scope  + structName;
+    // decode
+    m_os<<"int "<<scope<<""<<structName<<"::";
+    m_os<<"decode_ber(asn1::streams::ber &ctx)\n{\n"<<std::endl;
+    m_os<<"\tunsigned char   *m_buffer  = ctx.buffer();"<<std::endl;
+    m_os<<"\tint              len       = 0;"<<std::endl;
+    if (m_gencpp.with_source_debug())
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<lscope<<"::decode_ber \");\n";
+    //m_os<<"\tassert(0);\n";
+    m_os<<"\tif (ctx.decode_header( asn1::tag("<<type->tag().m_class<<",";
+    m_os<<type->tag().m_value<<",true),len) ) {"<<std::endl;
+    m_os<<"\t\tasn1::tag t(0,0);"<<std::endl;
+    m_os<<"\tunsigned long    m_pos     = ctx.bytes();"<<std::endl;
+    // Decode Header, 
+    m_os<<"\t\tif (ctx.decode_tag(t,len) ) {"<<std::endl;
+    m_os<<"\t\t\tctx.bytes(m_pos);"<<std::endl;
+    m_os<<"\t\t\tset_tag(t);"<<std::endl;
+    m_os<<"\t\t\tif (check_create()) "<<std::endl;
+    m_os<<"\t\t\t\treturn m_choice->decode(ctx);"<<std::endl;
+    m_os<<"\t\t}"<<std::endl;
+    // Check and create
+    // if ok, call decode
+    m_os<<"\t}\n"<<std::endl;
+    m_os<<"\treturn asn1::unknown;"<<std::endl;
+    m_os<<"\n}\n"<<std::endl;
+  
+  }
+}
+
+/**
+ *
+ */
+void cgcpph_choice::generate_oer()
+{
+  std::string MName = m_gencpp.get_module()->cpp_name();
+  std::string structName  = MName + "::" + m_choice.identifier()->cpp_name();
+  std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+  // TODO
+  if (m_gencpp.with_codec())
+  {
+    std::string ns = m_gencpp.get_module()->cpp_name();
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// choice type "<<structName<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+  }
+}
+
+/**
+ *
+ */
+void cgcpph_choice::generate_jer()
+{
+  std::string MName = m_gencpp.get_module()->cpp_name();
+  std::string structName  = MName + "::" + m_choice.identifier()->cpp_name();
+  std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+  if (m_gencpp.with_codec())
+  {
+    std::string ns = m_gencpp.get_module()->cpp_name();
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// choice type "<<structName<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+    /** Implementation for encoder */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void asn1::codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.put_char(\"{\",1);\n";
+    /* get should have the const version ! */
+    cpp<<"\tswitch (_t.get_kind())\n\t{\n";
+    for (asn1::node::iterator it = m_choice.begin(); it != m_choice.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            cpp<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            cpp<<"\t\tcase "<<structName<<"::typeof_"<<f->cpp_name()<<":\n";
+            cpp<<"\t\t{\n";
+            cpp<<"\t\t\tc.put_char(\"\\\"\",1);\n";
+            cpp<<"\t\t\tc.put_char(_t.get_member()->m_name,"<<f->cpp_name().size()<<");\n";
+            cpp<<"\t\t\tc.put_char(\"\\\": \",3);\n";
+            cpp<<"\t\t\tencode(c,_t.get_"<<f->cpp_name()<<"());\n";
+            cpp<<"\t\t\tbreak;\n";
+            cpp<<"\t\t}\n";
+         }
+      }
+    }
+    cpp<<"\t\tdefault: ;\n";
+    cpp<<"\t}\n";
+    cpp<<"\tc.put_char(\"}\",1);\n";
+    cpp<<"}\n";
+
+    /** Implementation for decoder */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int asn1::codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"std::string field;\n";
+    cpp<<"\tif (!c.get_token(asn1::streams::jer::jer_tok_left_bracket))\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\tif ( c.get_token(field))\n\t{\n";
+    cpp<<"\t\tif (!c.get_token(asn1::streams::jer::jer_tok_colon))\n\t\treturn asn1::wrong_type;\n";
+    for (asn1::node::iterator it = m_choice.begin(); it != m_choice.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            cpp<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            cpp<<"\t\tif (! field.compare(\""<<f->cpp_name()<<"\"))\n";
+            cpp<<"\t\t{\n";
+            cpp<<"\t\t\tdecode(c,_t.get_"<<f->cpp_name()<<"());\n";
+            cpp<<"\t\t\tgoto choice_end;\n";
+            cpp<<"\t\t}\n";
+         }
+      }
+    }
+    cpp<<"\t}\n";
+    cpp<<"choice_end:\n";
+    cpp<<"\tif (!c.get_token(asn1::streams::jer::jer_tok_right_bracket))\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_choice::generate_xer()
+{
+}
+
+/**
+ * Helper class to generate parameter 
+ * initialization per attribute.
+ */
+class gco_actp : public node_visitor<gco_actp>
+{
+  public:
+    gco_actp(std::ostream &_os,generate_codec_cpp &_g,asn1::choice &_c)
+      : m_os(_os) , m_log(_g.logger()), m_gencpp(_g), m_choice(_c)
+    {
+      m_assign = m_choice.identifier()->as_assignment();
+      assert( (m_assign != NULL ) && " m_assign should not be NULL for choice type");
+    }
+
+    
+    void visit_valueset(asn1::valueset *v)
+    {
+      long pos;
+      asn1::typeref *g = NULL; // governor 
+      m_os<<"\t\t// Ok "<<__FUNCTION__<<" todo ";
+      if (asn1::typeref *tref = v->get_typeref())
+      {
+        m_os<<tref->name()<<" ";
+        if (asn1::parameter *p = m_assign->have_parameter(tref,pos) ) 
+        {
+          if (asn1::node *gov = p->get_governor())
+            g = dynamic_cast<asn1::typeref *>(gov);
+          m_os<<" yes have parameter "<<pos<<" ... "<<p->name()<<"\n";
+          // If gorvernor is not simple, 
+          if ( g && (! g->is_simple()))
+          {
+            asn1::parameters &cparams = *m_rt->identifier()->parameters()->as_parameters();
+            m_os<<"\t\tinstance."<<cparams[pos]->name()<<" = "<<p->name()<<";\n";
+          }
+        }
+      }
+      m_os<<std::endl;
+    }
+    void visit_objectset(asn1::objectset *v)
+    {
+      m_os<<"\t// Ok "<<__FUNCTION__<<" todo"<<std::endl;
+    }
+    void visit_reference(asn1::reference *v)
+    {
+      m_os<<"\t// Ok "<<__FUNCTION__<<" todo"<<std::endl;
+    }
+    void do_act_parameters(asn1::node *_type,asn1::node *rt)
+    {
+      m_rt = rt;
+      if ( ! _type)
+        return;
+      asn1::constructed *aplist = _type->act_parameters();
+      if ( ! aplist)
+        return;
+      for ( asn1::node::iterator it = aplist->begin() ;
+            it != aplist->end(); ++it)
+      {
+        /* either value_set, object_set value, typeref */
+        if ((*it))
+          visit((*it));
+      }
+    }
+  protected:
+    asn1::node            *m_rt;
+    asn1::assignment       *m_assign;
+    std::fstream          &m_log;
+    std::ostream          &m_os;
+    generate_codec_cpp    &m_gencpp;
+    asn1::choice          &m_choice;
+};
+
+void cgcpph_choice::gen_create_object( )
+{
+  std::string scope(""); // Needs to be removed in the futur 
+    // There is a possibility to optimize here. count the types ....
+  asn1::choice *type  = &m_choice;
+  asn1::node *ident = m_choice.identifier();
+  asn1::node::iterator lit;
+  std::list<asn1::node *> choice_nodes;
+  
+  asn1::node *params = ident->parameters();
+  
+  m_os<<"bool "<<m_structName<<"::create_object()\n{\n";
+  // Ok, Now, deal with the attributes and so on 
+  //
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_structName;
+    m_os<<"::create_object m_kind=%d tag=%ld\",m_kind,tag().get_tag());"<<std::endl;
+  }
+  m_os<<"\tswitch (m_kind )\n\t{\n";
+  lit = type->begin();
+  for (; lit != type->end() ; lit++)
+  {
+      std::string strtype;
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*lit);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type == NULL)
+          continue;
+      asn1::type              type_id = attr_type->type_id();
+      std::list<asn1::node *> refs;
+
+      m_gencpp.reference_chaine(attr_type->as_typeref(),refs);
+      
+      if (type_id() == asn1::type::ASN1_EXTENSIBLE)
+      {
+       m_os<<"\t\t// Extensible marker"<<std::endl;
+      } else if (type_id() == asn1::type::ASN1_CHOICE )
+      { 
+          // In case of Choice
+          choice_nodes.push_back(f);
+      } else if ( (refs.size() > 0)
+              &&  ! (refs.back()->tagged() )
+              &&  attr_type 
+              && (!attr_type->tagged() )
+              &&  (refs.back()->tag().m_value < 0) 
+              && (type_id() == asn1::type::ASN1_REFERENCE) )
+      {
+          choice_nodes.push_back(f);
+      } else 
+      {
+        asn1::node::tag_type tg ;
+        m_os<<"\tcase "<<m_structName<<"::typeof_"<<f->cpp_name()<<":\n";
+        
+        // In ber mode, also check tag (for CSTA ...) 
+        if (m_gencpp.with_ber() && attr_type->tagged() )
+        {
+          tg = attr_type->tag();
+          m_os<<"\tif ( tag() == MAKE_LONG_TAG(";
+          m_os<<tg.m_class<<",0,"<<tg.m_value<<"))"<<std::endl;
+          m_os<<"\t{"<<std::endl;
+        } else 
+        {
+          m_os<<"\t// with_ber()="<<m_gencpp.with_ber();
+          m_os<<" tagged ="<<attr_type->tagged()<<std::endl;
+          if ((refs.size() > 0) && refs.back() != NULL)
+          {
+            if (refs.back()->tag().m_value >= 0)
+            {
+               tg = refs.back()->tag();
+               m_os<<"\tif ( tag() == MAKE_LONG_TAG(";
+               m_os<<tg.m_class<<",0,"<<tg.m_value<<")) /*ref tag*/"<<std::endl;
+               m_os<<"\t{"<<std::endl;
+            }
+          }
+
+        }
+        // Handle tag stuff 
+        if (attr_type->tagged())
+        {
+          asn1::node::tag_type tg = attr_type->tag();
+          m_os<<"\t\t";
+          if (attr_type->type_id()() == asn1::type::ASN1_REFERENCE)
+          {
+            asn1::typeref *tref = dynamic_cast<asn1::typeref *>(attr_type);
+            asn1::node    *rt   = m_gencpp.resolver().resolve(*tref);
+            if (tref->is_simple()
+                || (rt && rt->type_node()))
+            {
+             m_gencpp.gen_composite_attribute_ref(m_os,scope,f,params);
+             m_os<<" instance( asn1::tag(";
+             m_os<<tg.m_class<<","<<tg.m_value<<")";
+             m_os<<") ;\n";
+             // Process actual parameters ....
+             gco_actp gen_actual_param_init(m_os,m_gencpp,m_choice);
+             gen_actual_param_init.do_act_parameters(attr_type,rt);
+             m_os<<"\t\tm_choice = instance.clone();\n";
+            } else 
+            {
+             m_os<<"\t\tm_choice = NULL;\n";
+            }
+          } 
+          else if (m_gencpp.type2cppstring(attr_type,strtype) )
+          {
+            if (m_gencpp.is_tag_explicit(*attr_type) )
+            {
+              m_os<<"\tm_choice = new "<<strtype<<"(); /* Explicit tagged*/\n";
+            } else
+            {
+              m_os<<strtype;
+              m_os<<" instance( asn1::tag(";
+              m_os<<tg.m_class<<","<<tg.m_value<<")";
+              m_os<<") ;\n";
+              m_os<<"\t\tm_choice = instance.clone();\n";
+            }
+
+          } else 
+          {
+             m_os<<attr_type->cpp_name();
+             m_os<<" instance( asn1::tag(";
+             m_os<<tg.m_class<<","<<tg.m_value<<")";
+             m_os<<") ;\n";
+             m_os<<"\t\tm_choice = instance.clone();\n";
+          }
+        } else
+        {
+           m_os<<"\t\tm_choice = new ";
+           if (m_gencpp.type2cppstring(attr_type,strtype) )
+           {
+             m_os<<strtype<<"(); /*untg 1*/\n";
+           } else 
+             m_os<<attr_type->cpp_name()<<"(); /*untg 2*/\n";
+        }
+        m_os<<"\t\treturn true; \n";
+        // In ber mode, also check tag (for CSTA ...) 
+        if (m_gencpp.with_ber() && attr_type->tagged() )
+        {
+          asn1::node::tag_type tg = attr_type->tag();
+          m_os<<"\t} else {"<<std::endl;
+           //os<<"\treturn false;"<<std::endl;
+          m_os<<"\t\tASN1_BER_LOG_ERROR(\"create_object ";
+          m_os<<type->identifier_name()<<" tag=%ld expected ";
+          m_os<<tg.m_value<<" FAILED \",tag().get_tag());\n";
+          m_os<<"\t}"<<std::endl;
+        } else 
+        {
+          std::list<asn1::node *>lst;
+          m_gencpp.reference_chaine(attr_type->as_typeref(),lst);
+          
+          if ((lst.size() > 0) && lst.back() != NULL)
+          {
+            if (lst.back()->tag().m_value >= 0)
+            {
+              asn1::node::tag_type tg = lst.back()->tag();
+              m_os<<"\t}"<<std::endl;
+            }
+          }
+        }
+        m_os<<"\t\tbreak;\n";
+      }
+      refs.erase(refs.begin(),refs.end());
+  } /* End for attributes */
+
+  m_os<<"\tdefault:\n\t;\n";
+  m_os<<"\t}\n";
+  // Alright handle inner choices
+  for (lit = choice_nodes.begin() ; lit != choice_nodes.end(); ++lit)
+  {
+    std::string strtype;
+    asn1::field    *f              = dynamic_cast<asn1::field *>(*lit);
+    asn1::typenode *attribute_type = f->get_type();
+    m_os<<"\tm_choice = new ";
+    if (m_gencpp.type2cppstring(attribute_type,strtype) )
+    {
+        m_os<<strtype<<"(m_tag.get_tag(),m_tag);\n";
+    } else 
+       m_os<<attribute_type->cpp_name()<<"(m_tag.get_tag(),m_tag);\n";
+    
+    m_os<<"\tif (static_cast<asn1::types::choice_type *>(m_choice)->create_object())\n";
+    m_os<<"\t{"<<std::endl;
+    m_os<<"\t\tm_kind = typeof_"<<f->cpp_name()<<";\n";
+    m_os<<"\t\treturn true;"<<std::endl;
+    m_os<<"\t}"<<std::endl;
+    m_os<<"\tdelete m_choice;\n\tm_choice = NULL;"<<std::endl;
+  } /* End second for */
+
+  m_os<<"\tASN1_BER_LOG_ERROR(\""<<m_structName;
+  m_os<<"::create_object failed m_kind=%d tag=%ld\",m_kind,tag().get_tag());"<<std::endl;
+  m_os<<"\treturn false;\n";
+  m_os<<"}\n";
+}
+
+/*
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/libgen/cpp/cgcpph_choice.h b/libgen/cpp/cgcpph_choice.h
new file mode 100644 (file)
index 0000000..fbd171b
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef CGCPPH_CHOICE_H
+#define CGCPPH_CHOICE_H
+
+
+/**
+ *
+ */
+class cgcpph_choice : public cgh_construct
+{
+  protected:
+    cgcpph_choice(const  cgcpph_choice &s) :
+                                       cgh_construct(s.m_gencpp,s.m_os,s.m_choice)
+                                      , m_choice(s.m_choice)
+    {}  
+  public:
+    cgcpph_choice(generate_codec_cpp &g,std::ostream &os,asn1::choice &s) ;
+   
+    ~cgcpph_choice();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    // Generate descriptor code
+    //
+    virtual void generate_descriptor();
+    // generator entry points
+    virtual void generate_ctors();
+
+    virtual void generate_members();
+
+
+    virtual void generate_operators();
+    //
+    virtual void generate_printf();
+  protected:
+    //
+    void gen_ctor( );
+    //
+    void gen_create_object( );
+    //
+    void 
+    gen_ber_encode( const std::string &scope
+                  , const std::string &structName
+                  , bool              priv);
+    void 
+    gen_ber_decode( const std::string &scope
+                  , const std::string &structName
+                  , bool              priv);
+    //
+    void gen_attribute_setter( const std::string &scope
+                             , const std::string &structName
+                             , asn1::field       *attribute
+                             , asn1::node        *params
+                             , bool              priv);
+    //
+    void gen_setter_ref( const std::string &scope
+                             , const std::string &structName
+                             , asn1::field       *attribute
+                             , asn1::typeref     &tref
+                             , asn1::node        *params
+                             , bool              priv);
+    //
+    void gen_getter_ref( const std::string &scope
+                             , const std::string &structName
+                             , asn1::field       *attribute
+                             , asn1::typeref     &tref
+                             , asn1::node        *params
+                             , bool              priv);
+
+
+    //
+    void gen_codec( );
+    //
+    void gen_clone( );
+    //
+    void gen_equal( const std::string  &structName );
+    //
+    //
+    //
+    void gen_codec_decode(const std::string &scope);
+    //
+    void gen_codec_encode(const std::string &scope);
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    asn1::choice          &m_choice;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_enumerated.cpp b/libgen/cpp/cgcpph_enumerated.cpp
new file mode 100644 (file)
index 0000000..482b7a5
--- /dev/null
@@ -0,0 +1,264 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_construct.h"
+#include "cgcpph_enumerated.h"
+
+static 
+char  lop_substitute(char c)
+{
+    return (c == ':')?'_':c;
+}
+
+
+cgcpph_enumerated::cgcpph_enumerated(generate_codec_cpp &g,std::ostream &os,asn1::enumerated &s)
+  : cgh_construct(g,os,s) , m_enumerated(s) 
+{
+}
+
+cgcpph_enumerated::~cgcpph_enumerated()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgcpph_enumerated::generate(const std::string &scope)
+{
+  asn1::node *ident  = m_enumerated.identifier();
+  
+  if (m_gencpp.with_source_comment())
+    m_os<<"//\n// cgcpph_enumerated helper launched\n//"<<std::endl;
+  
+  cgcpp_helper::generate();
+}
+//
+//
+void 
+cgcpph_enumerated::generate_ctors()
+{
+  asn1::node::iterator it = m_enumerated.begin();
+
+  m_os<<""<<m_structName<<"::"<<m_structName<<"(const asn1::tag &t)\n";
+  m_os<<"    : asn1::ENUMERATED(t)\n";
+  m_os<<"{\n\tm_Prim = "<<(*it)->cpp_name()<<";\n}\n"<<std::endl; 
+  // Copy ctor
+  m_os<<"\n"<<m_structName<<"::"<<m_structName;
+  m_os<<"(const "<<m_structName<<" &t) : asn1::ENUMERATED(t)\n{\n}\n";
+  // clone
+  m_os<<"\n"<<m_structName<<"* "<<m_structName;
+  m_os<<"::clone()\n{\n\treturn new "<<m_structName<<"(*this);\n}\n"<<std::endl;
+  
+  // operator =
+  m_os<<m_structName<<" & "<<m_structName<<"::operator = (unsigned int v)\n{\n";
+  m_os<<"\tm_Prim = v;"<<std::endl; 
+  m_os<<"\treturn *this;"<<std::endl; 
+  m_os<<"}"<<std::endl; 
+}
+//
+//
+void 
+cgcpph_enumerated::generate_operators( )
+{
+  //std::string structName;
+  //m_gencpp.type2cppstring(&m_enumerated,structName,scope);
+  m_os<<"bool "<<m_structName<<"::operator ==(const "<<m_structName<<" &v) const\n";
+  m_os<<"{\n\treturn  v.get_value() ==  get_value();\n}\n";
+  m_os<<"bool "<<m_structName<<"::operator ==(const e"<<m_structName<<" v) const\n";
+  m_os<<"{\n\treturn m_Prim == v ;\n}\n";
+  m_os<<"\nbool "<<m_structName<<"::operator !=(const e"<<m_structName<<" v) const\n";
+  m_os<<"{\n\treturn m_Prim != v ;\n}\n";
+}
+
+//
+//
+void cgcpph_enumerated::generate_printf( )
+{
+  std::string fname(m_structName);
+  asn1::enumerated *type   = &m_enumerated;
+  
+  assert(type->type_id()() == asn1::type::ASN1_ENUMERATED );
+  
+  m_os<<"#if 1 /* ASN1_PRINTF*/"<<std::endl;
+  
+  //m_gencpp.type2cppstring(&m_enumerated,structName,scope);
+#if 0
+  m_os<<"std::string Names_"<<lscope<<"[] = {"<<std::endl;
+  it = type->begin();
+  for (; it != type->end(); it++)
+  {
+    asn1::value *num = (*it)->value();
+    if (it != type->begin() )
+    {
+      m_os<<"\t,\""<<(*it)->cpp_name()<<"\"\n";
+    } else
+    {
+      m_os<<"\t \""<<(*it)->cpp_name()<<"\"\n";    
+    }
+  
+  }  
+  m_os<<"};\n"<<std::endl;
+#endif
+  // printf function
+  m_os<<"void "<<fname<<"::printf(std::ostream &os) const\n{\n\tos<<*this;\n}\n"<<std::endl; 
+
+  // stream operator function
+  m_os<<"std::ostream &operator <<(std::ostream &os,const ";
+  m_os<<" "<<fname;
+  m_os<<" &s)\n{\n";
+  
+  for ( asn1::node::iterator it = m_enumerated.begin()
+       ; it != m_enumerated.end(); ++it)
+  {
+    if (it != m_enumerated.begin() )
+    {
+      m_os<<"\telse if (s.m_Prim == "<<fname<<"::"<<(*it)->cpp_name()<<")\n";
+      m_os<<"\t\tos<<\""<<(*it)->cpp_name()<<"\";\n";
+    } else
+    {
+      m_os<<"\tif (s.m_Prim == "<<fname<<"::"<<(*it)->cpp_name()<<")\n";
+      m_os<<"\t\tos<<\""<<(*it)->cpp_name()<<"\";\n";    
+    }
+  
+  }  
+  m_os<<"\t\tos<<\" (\"<<s.m_Prim<<\")\";\n";
+  m_os<<"\t\treturn os;\n";
+
+  m_os<<"}\n"<<std::endl;
+  m_os<<"#endif"<<std::endl;
+}
+
+// generate codec part
+void cgcpph_enumerated::generate_per()
+{
+  //
+  m_os<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cgcpph_enumerated::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_enumerated;
+#if 0
+  //
+  m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  //
+  if (m_enumerated.tagged()) {
+        if ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+        {
+          m_os<<scope<<"\tvirtual void encode_preamble_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual void encode_epilogue_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual int decode_preamble_ber(asn1::streams::ber &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual int decode_epilogue_ber(asn1::streams::ber &ctx);"<<std::endl;
+        }
+  }
+#endif
+  //m_Gen.gen_template_signature(m_os,type);
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName( ns + "::" + m_enumerated.identifier_cpp_name() );
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"encode typeref "<<structName<<"\"<<std::endl;\n";
+    //cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"decode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_enumerated::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cgcpph_enumerated::generate_jer()
+{
+  std::string fname;
+  std::string ns( m_gencpp.get_module()->cpp_name() );
+  std::string structName ( ns + "::" + m_enumerated.identifier_cpp_name());
+  
+  //m_gencpp.type2cppstring(&m_enumerated,structName,scope);
+  fname = structName;
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+    /* */
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    /**/
+    cpp<<"\tswitch (_t.get_sys_value())\n\t{\n";
+    asn1::node::iterator it = m_enumerated.begin();
+    for (; it != m_enumerated.end(); it++)
+    {
+       if ( (*it)->is_extensible()) continue; 
+       cpp<<"\t\tcase "<<fname<<"::"<<(*it)->cpp_name()<<": ";
+       cpp<<"c.put_field(\""<<(*it)->cpp_name()<<"\","<<(*it)->cpp_name().size()<<"); break;\n";    
+    }  
+    cpp<<"\t};\n";
+    /**/
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_enumerated::generate_xer()
+{
+}
+
+/**
+ * private structures are generated before the current on.
+ *  outside the scope of the current type.
+ *  This code could be factorized and generator level 
+ */ 
+void cgcpph_enumerated::gen_private()
+{
+    asn1::node *type = &m_enumerated; 
+}
diff --git a/libgen/cpp/cgcpph_enumerated.h b/libgen/cpp/cgcpph_enumerated.h
new file mode 100644 (file)
index 0000000..af94c7e
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CGCPPH_ENUMERATED_H
+#define CGCPPH_ENUMERATED_H
+
+
+/**
+ *
+ */
+class cgcpph_enumerated : public cgh_construct
+{
+  protected:
+    cgcpph_enumerated(const  cgcpph_enumerated &s) :  cgh_construct(s)
+                                     , m_enumerated(s.m_enumerated) {}  
+  public:
+    cgcpph_enumerated(generate_codec_cpp &g,std::ostream &os,asn1::enumerated &s) ;
+    ~cgcpph_enumerated();
+    
+    // Helper functions
+    virtual void generate(const std::string &scope) ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_printf( );
+    virtual void generate_ctors( );
+    virtual void generate_operators( );
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+    void gen_private();
+  protected:  
+    asn1::enumerated     &m_enumerated;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_import.cpp b/libgen/cpp/cgcpph_import.cpp
new file mode 100644 (file)
index 0000000..e9143ad
--- /dev/null
@@ -0,0 +1,87 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_import.h"
+
+
+cgcpph_import::cgcpph_import(generate_codec_cpp &g,std::ostream &os,asn1::import &s)
+  : m_Gen(g), generator_helper(os) , m_import(s) , m_log(g.logger())
+{
+}
+
+cgcpph_import::~cgcpph_import()
+{
+}
+
+
+/** Helper functions
+ *
+ *  
+ */ 
+void cgcpph_import::generate()
+{
+  asn1::node::iterator items,end;
+  asn1::node::iterator it = m_import.begin();
+  
+  m_os<<"// cgcpph_import helper launched ";
+  
+  // GEN_LOG_DEBUG("cgcpph_import::generate node=%s\n",type->identifier_cpp_name().c_str());
+  m_os<<"\n#if 0\n";
+  // May be just include each module ...
+
+  items = m_import.begin();
+  end   = m_import.end();
+  // Loop over items and check if OPERATION is imported
+  for (  items  = m_import.begin()
+       ; items != end
+       ; ++items)
+  {
+    //os <<"//#include \""<<(*it)->identifier_cpp_name()<<"/"<<(*items)->cpp_name()<<".h\" /*item "<<(*items)->name()<<"*/\n";
+    if (std::string("OPERATION").compare((*items)->name()) == 0 )
+    {
+      m_os<<"#include \"rtasn1/asn1_rose.h\"\n";
+    }
+  }
+  m_os<<"#include \""<<m_import.identifier()->cpp_name()<<".h\"\n";
+  
+  m_os<<"#endif\n"; 
+}
+//
+void cgcpph_import::gen_printf(const std::string &scope)
+{
+}
+
+// generate codec part
+void cgcpph_import::generate_per()
+{
+}
+
+//
+void cgcpph_import::generate_ber()
+{
+}
+
+//
+void cgcpph_import::generate_oer()
+{
+  //
+}
+
+//
+void cgcpph_import::generate_jer()
+{
+}
+
+//
+void cgcpph_import::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_import.h b/libgen/cpp/cgcpph_import.h
new file mode 100644 (file)
index 0000000..9cf0f94
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef CGCPPH_IMPORT_H
+#define CGCPPH_IMPORT_H
+
+
+/**
+ *
+ */
+class cgcpph_import : public generator_helper
+{
+  protected:
+    cgcpph_import(const  cgcpph_import &s) : generator_helper(s.m_os)
+                                      , m_Gen(s.m_Gen)
+                                      , m_import(s.m_import)
+                                      , m_log(s.m_log)
+    {}  
+  public:
+    cgcpph_import(generate_codec_cpp &g,std::ostream &os,asn1::import &s) ;
+   
+    ~cgcpph_import();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    std::fstream          &m_log;
+    generate_codec_cpp    &m_Gen;
+    asn1::import          &m_import;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_integer.cpp b/libgen/cpp/cgcpph_integer.cpp
new file mode 100644 (file)
index 0000000..dc893a9
--- /dev/null
@@ -0,0 +1,264 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_construct.h"
+#include "cgcpph_integer.h"
+
+
+cgcpph_integer::cgcpph_integer(generate_codec_cpp &g,std::ostream &os,asn1::integer &s)
+  : cgh_construct(g,os,s)
+  , m_integer(s)
+{
+}
+
+cgcpph_integer::~cgcpph_integer()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgcpph_integer::generate()
+{
+  m_os<<"// cgcpph_integer helper launched "<<m_integer.identifier()->name()<<std::endl;
+  
+  cgcpp_helper::generate();
+}
+
+void cgcpph_integer::generate_ctors()
+{
+  m_os<<m_structName<<"::"<<m_structName<<"(const asn1::tag &t )\n";
+  if (m_integer.is_unsigned())
+  {
+    m_os<<"\t: UInt64(t)\n{\n}\n"<<std::endl;
+  } else
+    m_os<<"\t: INTEGER(t)\n{\n}\n"<<std::endl;
+}
+void cgcpph_integer::generate_operators()
+{
+  m_os<<"bool "<<m_structName<<"::operator ==(const "<<m_integer.identifier_cpp_name()<<" &v)";
+  m_os<<" const\n{\n\treturn v.get_value() == get_value();\n}\n";
+  if (m_integer.is_unsigned())
+  {
+    m_os<<"void "<<m_structName<<"::operator =(const unsigned long v)";
+    m_os<<"\n{\n\tm_Prim = v;\n}\n";
+    m_os<<"void "<<m_structName<<"::operator =(const asn1::prim::types::UInt64 &v)";
+    m_os<<"\n{\n\tm_Prim = v;\n}\n";
+  }else
+  {
+    m_os<<"void "<<m_structName<<"::operator =(const long v)";
+    m_os<<"\n{\n\tm_Prim = v;\n}\n";
+    m_os<<"void "<<m_structName<<"::operator =(const asn1::prim::types::Integer &v)";
+    m_os<<"\n{\n\tm_Prim = v;\n}\n";
+  }
+  m_os<<"\n";
+  if (m_integer.size() > 0)
+  {
+    m_os<<"bool "<<m_structName<<"::operator ==(const e"<<m_integer.identifier_cpp_name()<<" v)";
+    m_os<<" const\n{\n\treturn m_Prim == v;\n}\n";
+    m_os<<"void "<<m_structName<<"::operator =(const e"<<m_integer.identifier_cpp_name()<<" v)";
+    m_os<<"\n{\n\tm_Prim = v;\n}\n";
+  }
+
+
+}
+//
+void cgcpph_integer::generate_printf( )
+{
+}
+
+// generate codec part
+void cgcpph_integer::generate_per()
+{
+       if (m_gencpp.with_codec())
+  {
+    std::string  ns(m_gencpp.get_module()->cpp_name());
+    std::string  structName(ns + "::" +m_integer.identifier_cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_Gen.gen_template_signature(m_os,type);
+    hpp<<"\n// construct type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecPER::encode(streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecPER::decode(streams::per &c,"<<structName<<" &_t);\n";
+               /* Implementation part */
+    cpp<<"// integer generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_integer(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_integer(_t);\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_integer::generate_ber()
+{
+  asn1::node *type       = &m_integer;
+  std::string structName = m_integer.identifier_cpp_name();
+  //
+  //
+  if (m_integer.tagged())
+  {
+    if ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<"void "<<structName<<"::encode(asn1::context &ctx)"<<std::endl;
+      m_os<<"{\n";
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d BIG Issue \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_integer.tag().m_class<<","<<m_integer.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,2));\n";
+      m_os<<"\tctx.encode_integer(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      // Decode function
+      m_os<<"int  "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_integer.tag().m_class<<","<<m_integer.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      if (m_integer.is_unsigned())
+      { 
+             m_os<<"\t\tUInt64 tmp;\n";
+      } else
+      {
+             m_os<<"\t\tINTEGER tmp;\n";
+      }
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp.get_value();\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+     }
+  }
+  /* Handle codec aspect */
+       if (m_gencpp.with_codec())
+  {
+    std::string  ns(m_gencpp.get_module()->cpp_name());
+    std::string  structName(ns + "::" +m_c.identifier()->cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_Gen.gen_template_signature(m_os,type);
+    hpp<<"\n// construct type "<<structName<<""<<"\n";
+    hpp<<"template<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+   /* Handle implementation part */
+    cpp<<"// integer generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if ( m_integer.tagged()
+         && ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT))
+    {
+      cpp<<"\tasn1::tag t("<<m_integer.tag().m_class<<","<<m_integer.tag().m_value<<",true);\n";
+      //cpp<<"\tstd::cout<<\"encode "<<structName<<" explicit tag TODO\"<<std::endl;\n";
+      cpp<<"\tencode_tag(c,t,_t.get_length());\n";
+    }
+    cpp<<"\tc.encode_integer(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    if ( m_integer.tagged()
+         && ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT))
+    {
+      cpp<<"\tasn1::tag t("<<m_integer.tag().m_class<<","<<m_integer.tag().m_value<<",true);\n";
+      cpp<<"\tif (c.decode_tag(t))\n\t{\n";
+      cpp<<"\t\treturn c.decode_integer(_t);\n";
+      cpp<<"\t}\n";
+      cpp<<"\treturn asn1::wrong_tag;\n";
+    } else 
+      cpp<<"\treturn c.decode_integer(_t);\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_integer::generate_oer()
+{
+       if (m_gencpp.with_codec())
+  {
+    std::string  ns(m_gencpp.get_module()->cpp_name());
+    std::string  structName(ns + "::" +m_integer.identifier_cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_Gen.gen_template_signature(m_os,type);
+    hpp<<"\n// construct type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+    /* Implementation part */
+    cpp<<"// integer generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_integer(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_integer(_t);\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_integer::generate_jer()
+{
+       if (m_gencpp.with_codec())
+  {
+    std::string  ns(m_gencpp.get_module()->cpp_name());
+    std::string  structName(ns + "::" +m_integer.identifier_cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_Gen.gen_template_signature(m_os,type);
+    hpp<<"\n// construct type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+               /* Implementation part */
+    cpp<<"// integer generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_integer(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_integer(_t);\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_integer::generate_xer()
+{
+  std::string structName = m_integer.identifier_cpp_name();
+  m_os<<"void"<<structName<<"::encode_jer(asn1::context &ctx)\n{"<<std::endl;
+  m_os<<"\n}"<<std::endl;
+  m_os<<"int "<<structName<<"::decode_jer(asn1::context &ctx)\n{"<<std::endl;
+  m_os<<"\treturn asn1::wrong_tag;\n";
+  m_os<<"\n}"<<std::endl;
+}
+
diff --git a/libgen/cpp/cgcpph_integer.h b/libgen/cpp/cgcpph_integer.h
new file mode 100644 (file)
index 0000000..9f820fb
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef CGCPPH_INTEGER_H
+#define CGCPPH_INTEGER_H
+
+
+/**
+ *
+ */
+class cgcpph_integer : public cgh_construct
+{
+  protected:
+    cgcpph_integer(const  cgcpph_integer &s) :  cgh_construct(s)
+                                     , m_integer(s.m_integer) {}  
+  public:
+    cgcpph_integer(generate_codec_cpp &g,std::ostream &os,asn1::integer &s) ;
+    ~cgcpph_integer();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+  protected:
+    virtual void generate_ctors( );
+    virtual void generate_operators( );
+    virtual void generate_printf( );
+  protected:
+    asn1::integer       &m_integer;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_object.cpp b/libgen/cpp/cgcpph_object.cpp
new file mode 100644 (file)
index 0000000..df7bdda
--- /dev/null
@@ -0,0 +1,449 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "asn1_recursive_visitor.h"
+#include "cgh_object.h"
+#include "cgcpph_object.h"
+#include "adt/asn1_node.h"
+#include "adt/asn1_constraint.h"
+#include "asn1_visitor.h"
+
+/**
+ * Generate Missing Objects before instanciating them in the set. 
+ */ 
+class missing_object : public asn1::recursive_visitor<missing_object>
+{
+  public:
+    missing_object(std::ostream &os,cgcpph_object &h,generate_codec_cpp &g)
+      : m_os(os), m_cgh(h) , m_Gen(g), m_count(0)
+    {}
+
+    bool visit_celt_value(asn1::celt_value *cv)
+    {
+      asn1::node::iterator ref = std::find_if(m_Gen.get_module()->begin(),
+      m_Gen.get_module()->end(),
+      asn1::find_node(cv->value()->name()));
+      if (ref != m_Gen.get_module()->end())
+      {
+        asn1::node *ntype = *ref; 
+        if (ntype->parameters())
+        {
+          std::cerr<<"generate_codec_cpp::gen_const "<<ntype->name()<<" has parameters"<<std::endl;
+          m_os<<"//gen_const "<<ntype->name()<<" has parameters NO GEN YET"<<std::endl;
+          return true;
+        } else 
+        {
+          m_count++;
+          m_Gen.gen_object(m_os,(*ref)->as_assignment());
+        }
+      }
+      return true;
+    }
+   
+    long           m_count;
+    std::ostream  &m_os;
+    cgcpph_object &m_cgh;
+    generate_codec_cpp &m_Gen;
+};
+
+/**
+ * Generate Object sets in class:  
+ */ 
+class gen_objectset : public asn1::recursive_visitor<gen_objectset>
+{
+  public:
+    gen_objectset( std::ostream &os
+                 , const std::string field
+                 , const std::string sname
+                 , const long   nbelems 
+                 , cgcpph_object &h
+                 , generate_codec_cpp &g)
+      : m_os(os), m_cgh(h) , m_Gen(g),m_count(0),m_struct_name(sname),m_nb_elems(nbelems)
+    {}
+
+    bool visit_celt_value(asn1::celt_value *cv)
+    {
+      asn1::node::iterator ref = std::find_if(m_Gen.get_module()->begin(),
+      m_Gen.get_module()->end(),
+      asn1::find_node(cv->value()->name()));
+      if (ref != m_Gen.get_module()->end())
+      {
+        asn1::node *ntype = *ref; 
+        if (ntype->parameters())
+        {
+          std::cerr<<"generate_codec_cpp::gen_const "<<ntype->name()<<" has parameters"<<std::endl;
+          m_os<<"//gen_const "<<ntype->name()<<" has parameters NO GEN YET"<<std::endl;
+          return true;
+        } else 
+        {
+          if (m_count++)
+            m_os<<",";
+          m_os<<" {";
+          if (m_count< m_nb_elems)
+          {
+           m_os<<" &"<<m_struct_name<<"["<<m_count<<"]";
+          }else
+            m_os<<" NULL";
+          m_os<<",new "<<ntype->cpp_name()<<"()}\n";           
+        }
+      }
+      return true;
+    }
+    /**
+     *
+     */
+    bool traverse_objectset(asn1::objectset *S)
+    {
+      bool ret = asn1::recursive_visitor<gen_objectset>::traverse_objectset(S);
+      if (m_count)
+      {
+        m_os<<",{NULL,NULL}"; 
+      }else
+      {
+        m_os<<"{NULL,NULL} ";
+      }
+      return ret;
+    }
+
+  bool traverse_valueset(asn1::valueset *S)
+  {
+    bool ret = asn1::recursive_visitor<gen_objectset>::traverse_valueset(S);
+    if (m_count)
+    {
+      m_os<<",{NULL,NULL}"; 
+    }else
+    {
+      m_os<<"{NULL,NULL} ";
+    }
+    return ret;
+  }
+  long           m_count;
+  long           m_nb_elems;  
+  std::string    m_field;
+  std::string    m_struct_name;
+  std::ostream  &m_os;
+  cgcpph_object &m_cgh;
+  generate_codec_cpp &m_Gen;
+};
+
+/**
+* INTERNAL HELPER CLASS
+*/ 
+struct g_objectset
+{
+  g_objectset(std::ostream &os,cgcpph_object &h,generate_codec_cpp &g) 
+    : m_os(os) , m_cgh(h) , m_Gen(g) 
+  {
+  }
+
+  void operator ()(asn1::node *n)
+  {
+    if (n->type_id()() == asn1::type::ASN1_CLASSFIELD_OSF )
+    {
+      asn1::typeref *tref = dynamic_cast<asn1::classfield_osf *>(n)->get_typeref();
+      std::string name = n->cpp_name().substr(1);
+      asn1::node    *ident = m_Gen.resolver().resolve(*tref);
+      // Get field Loop over union ... 
+      m_os<<"// OBJECTSET "<<n->name()<<std::endl; 
+      asn1::objectset *type = NULL;
+      if ( (type =  m_cgh.get_object().get_objectset(n->name()) ) != NULL )
+      {
+        std::string sname = m_cgh.get_object().identifier()->cpp_name()+"_"+name;
+        m_os<<"// HAVE VALUES "<<n->name()<<" object set is element_set_spect "<<std::endl;
+        missing_object mo(m_os,m_cgh,m_Gen);
+        //mo.traverse_valueset(type);
+        mo.traverse_objectset(type);
+        // Now generate the set
+        if (! m_Gen.get_module()->name().compare(ident->get_parent()->name()))
+        {
+          m_os<<"struct ";
+          //<<name<<"Set ";
+        } else
+          m_os<<"struct "<<ident->get_parent()->cpp_name()<<"::";
+        m_os<<tref->cpp_name()<<"Set ";
+        m_os<<m_cgh.get_object().identifier()->cpp_name()<<"_"<<name;
+        m_os<<"[] = {\n";
+        gen_objectset gset(m_os,n->name(),sname,mo.m_count,m_cgh,m_Gen);
+        gset.traverse_objectset(type);
+        m_os<<"};\n";
+      }
+    }
+  }
+  std::ostream  &m_os;
+  cgcpph_object &m_cgh;
+  generate_codec_cpp &m_Gen;
+};
+
+
+/*
+* CLASS chgpph_object IMPLEMENTATION
+*/ 
+
+cgcpph_object::cgcpph_object( generate_codec_cpp &g
+                        , std::ostream &os
+                        , asn1::object &s
+                        , asn1::classdef &cdef)
+: m_Gen(g)
+, cgh_object(g,os,s,cdef) 
+, m_log(g.logger())
+{
+}
+
+cgcpph_object::~cgcpph_object()
+{
+}
+
+
+/** Helper functions
+* generate object template code
+*/ 
+void cgcpph_object::generate()
+{
+  asn1::node *n      = m_object.identifier();
+  asn1::node *type   = &m_object;
+  asn1::node *params = NULL;
+  std::string structName;
+
+  m_os<<"\n//\n// cgcpph_object helper launched "<<n->name()<<"\n";
+  if (!m_Gen.get_module()->name().compare("Remote-Operations-Useful-Definitions"))
+  {
+    m_os<<"// Dont generate anything For this module\n";
+    return;
+  }
+  gen_objectset();
+  // Generate template_specialisation
+  if (m_classdef.get_parent() ==  m_Gen.get_module())
+  {
+    m_os<<"template <>\n";
+    m_os<<m_classdef.cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.cpp_name()<<"();\n";
+    // Test project passes through here
+    //assert(0 && " CLASS and OBJECT in same module");
+  } else
+  {
+    m_os<<"}\n"; // Close current namespace   
+    // Open template namespace     
+    m_os<<"namespace "<<m_classdef.get_parent()->cpp_name()<<" {\n";
+    gen_ctors() ;
+    m_os<<"} // close namespace\n"; // Close template namespace   
+    // Reopen current namespace    
+    m_os<<"namespace "<<m_Gen.get_module()->cpp_name()<<" {\n";
+#if defined(_WINDOWS)
+    // Solve link issue in cstav1
+    m_os<<"static "<<n->cpp_name()<<" "<<n->cpp_name()<<"_instance;\n";
+#endif 
+  }
+
+  m_os<<"\n";
+
+}
+
+void 
+cgcpph_object::gen_ctors()
+{
+  asn1::node *n      = m_object.identifier();
+  m_os<<"template <>\n";
+  m_os<<m_classdef.identifier()->cpp_name();
+  m_os<<"<";
+  gen_template_args(true);
+  m_os<<">::"<<m_classdef.identifier()->cpp_name()<<"()\n";
+  m_os<<"{\n"; // Open function content
+  if (m_Gen.with_source_debug())
+    m_os<<"\tASN1_BER_LOG_DEBUG(\"ctor::"<<n->name()<<"\");\n";
+  gen_ctor_set_ftvf();
+  m_os<<"}\n"; // Close function content 
+  // Add copy ctor even if private
+  m_os<<"template <>\n";
+  m_os<<m_classdef.identifier()->cpp_name();
+  m_os<<"<";
+  gen_template_args(true);
+  m_os<<">::"<<m_classdef.identifier()->cpp_name()<<"(const ";
+  m_os<<m_classdef.identifier()->cpp_name();
+  m_os<<"<";
+  gen_template_args(true);
+  m_os<<"> &o )\n";
+  m_os<<"{\n"; // Open function content 
+  if (m_Gen.with_source_debug())
+    m_os<<"\tASN1_BER_LOG_DEBUG(\"cpctor::"<<n->name()<<"\");\n";
+  gen_ctor_set_ftvf();
+  m_os<<"}\n"; // Close function content 
+  // Add Create static function to check if yes or not
+
+}
+
+//
+void cgcpph_object::gen_printf(const std::string &scope)
+{
+}
+
+// generate codec part
+void cgcpph_object::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cgcpph_object::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_object;
+  //
+  m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  //
+  if (m_object.tagged())
+  {
+    if ( m_Gen.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+        m_os<<scope<<"\tvirtual void encode_preamble_ber(asn1::context &ctx);"<<std::endl;
+        m_os<<scope<<"\tvirtual void encode_epilogue_ber(asn1::context &ctx);"<<std::endl;
+        m_os<<scope<<"\tvirtual int decode_preamble_ber(asn1::streams::ber &ctx);"<<std::endl;
+        m_os<<scope<<"\tvirtual int decode_epilogue_ber(asn1::streams::ber &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cgcpph_object::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cgcpph_object::generate_jer()
+{
+}
+
+//
+void cgcpph_object::generate_xer()
+{
+}
+
+/**
+ *
+ */
+class ftvf_init : public node_visitor<ftvf_init>
+{
+  public:
+    ftvf_init(std::ostream &os,const std::string &s) : m_s(s),m_os(os) {};
+
+    void visit_integer(asn1::integer *_int)
+    {
+      //TODO This is wrong code
+      m_os<<"\t"<<m_s<<".set_local( INTEGER(asn1::prim::types::Integer(";
+      m_os<<_int->cpp_name();
+      m_os<<")));\n";  
+    }
+
+    void visit_object_identifier(asn1::object_identifier *_oid)
+    {
+      asn1::object_identifier::arcsType v;
+      _oid->arcs(v);
+      m_os<<"\t"<<m_s<<".set_global ( OBJECT_IDENTIFIER("<<v.size()<<",";
+      _oid->print_strhex(m_os,v);
+      m_os<<") ) ;\n";
+    }
+
+    void visit_choice(asn1::choice *type)
+    {
+      asn1::value *val = type->value(); 
+      m_os<<"\t// FTVF CHOICE "<<type->cpp_name()<<" "<<val->cpp_name()<<std::endl;
+      switch (val->m_node->type_id()())
+      {
+        case asn1::type::ASN1_OBJECT_IDENTIFIER:
+        {
+          asn1::object_identifier::arcsType v;
+          asn1::object_identifier *_oid = val->m_node->as_object_identifier();
+          _oid->arcs(v);
+          m_os<<"\t"<<m_s<<".set_"<<type->cpp_name();
+          m_os<<" ( OBJECT_IDENTIFIER("<<v.size()<<",";
+          _oid->print_strhex(m_os,v);
+          m_os<<") ) ;\n";
+        }
+        break;  
+        case asn1::type::ASN1_INTEGER:
+        {
+          m_os<<"\t"<<m_s<<".set_"<<type->cpp_name();
+          m_os<<"( INTEGER(";
+          m_os<<val->cpp_name();
+          m_os<<") );\n";
+        }
+        default:
+        ;
+      }  
+    }
+    // Default unhandled case
+    void visit_node(asn1::node *type)
+    {
+      m_os<<"\t// FTVF "<<type->cpp_name()<<" ID="<<type->type_id()()<<std::endl;  
+    }
+  protected:
+    std::string  m_s;
+    std::ostream &m_os;
+};
+
+/**
+ * Set Fixed Type Value Field values in CTOR
+ */ 
+void cgcpph_object::gen_ctor_set_ftvf()
+{
+  asn1::node::iterator fit = m_classdef.begin(); 
+  int count = 0;
+
+  for ( ; fit != m_classdef.end()
+        ; ++fit)
+  {
+    if ( (*fit)->type_id()() == asn1::type::ASN1_CLASSFIELD_OSF )
+    {
+      asn1::objectset *type = NULL;
+      if ( (type =  m_object.get_objectset((*fit)->name()) ) != NULL )
+      {
+        std::string s = (*fit)->name();
+        s[0] = '_'; 
+        m_os<<"\t// SET OBJECT SET "<<s<<std::endl;  
+      }
+    }
+    // Try to get code  
+    if ( (*fit)->type_id()() == asn1::type::ASN1_CLASSFIELD_FTVF )
+    {
+      asn1::valuetype *type = NULL;
+      if ( (type =  m_object.get_ftvf((*fit)->name()) ) != NULL )
+      {
+        std::string s = (*fit)->name();
+        s[0] = '_'; 
+        ftvf_init vint(m_os,s);
+        vint.visit(type);
+      }
+    }  
+  }
+}
+
+
+/**
+ *
+ */ 
+void cgcpph_object::gen_objectset()
+{
+  std::for_each(m_classdef.begin()
+                , m_classdef.end()
+                , g_objectset(m_os,*this,m_Gen));
+}
+
+/*
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/libgen/cpp/cgcpph_object.h b/libgen/cpp/cgcpph_object.h
new file mode 100644 (file)
index 0000000..b7cef09
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef CGCPPH_OBJECT_H
+#define CGCPPH_OBJECT_H
+
+
+/**
+ *
+ */
+class cgcpph_object : public cgh_object
+{
+  protected:
+    cgcpph_object(const  cgcpph_object &s) : cgh_object(s.m_Gencpp
+                                                      , s.m_os
+                                                      , s.m_object
+                                                      , s.m_classdef
+                                                       )
+                                      , m_Gen(s.m_Gen)
+                                     // , m_object(s.m_object)
+                                     // , m_classdef(s.m_classdef)
+                                      , m_log(s.m_log)
+    {}  
+  public:
+    cgcpph_object(  generate_codec_cpp &g
+                  , std::ostream &os
+                  , asn1::object &s 
+                  , asn1::classdef &c 
+                  ) ;
+   
+    ~cgcpph_object();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    //void gen_template_args(bool with_scope);
+    //
+    void gen_ctor_set_ftvf();
+
+    void gen_ctors();
+    /**
+     * CLASS might have object sets
+     */ 
+    void gen_objectset();
+  protected:
+    std::fstream          &m_log;
+    generate_codec_cpp    &m_Gen;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_objectset.cpp b/libgen/cpp/cgcpph_objectset.cpp
new file mode 100644 (file)
index 0000000..6ff590a
--- /dev/null
@@ -0,0 +1,123 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_object.h"
+#include "cgcpph_objectset.h"
+
+
+/**
+ * INTERNAL HELPER CLASS
+ */ 
+struct g_object
+{
+  g_object(std::ostream &os,cgcpph_objectset &h) 
+    : m_os(os) , m_cgh(h)
+  {
+  }
+
+  void operator ()(asn1::node *n)
+  {
+    if (n->type_id()() == asn1::type::ASN1_CLASSFIELD_OSF )
+    {
+      // Get field Loop over union ... 
+      asn1::node *type = NULL;
+      if ( (type =  m_cgh.get_object().get_field(n->name()) ) != NULL )
+      {
+        m_os<<"// HAVE VALUES "<<n->name()<<std::endl; 
+      }
+    }
+  }
+  std::ostream  &m_os;
+  cgcpph_objectset &m_cgh;
+};
+
+
+/*
+ * CLASS chgpph_objectset IMPLEMENTATION
+ */ 
+cgcpph_objectset::cgcpph_objectset( generate_codec_cpp &g
+                            , std::ostream &os
+                            , asn1::object &s
+                            , asn1::classdef &cdef)
+  : m_Gen(g)
+  , cgh_object(g,os,s,cdef) 
+  , m_log(g.logger())
+{
+}
+
+cgcpph_objectset::~cgcpph_objectset()
+{
+}
+
+
+/** Helper functions
+ * generate object template code
+ */ 
+void cgcpph_objectset::generate()
+{
+  asn1::node *n      = m_object.identifier();
+  asn1::node *type   = &m_object;
+  asn1::node *params = NULL;
+  std::string structName;
+  
+  m_os<<"\n//\n// cgcpph_objectset helper launched "<<n->name()<<"\n";
+  if (!m_Gen.get_module()->name().compare("Remote-Operations-Useful-Definitions"))
+  {
+    m_os<<"// Dont generate anything For this module\n";
+    return;
+  } 
+  gen_objectset();
+  // Generate template_specialisation
+  if (m_classdef.get_parent() ==  m_Gen.get_module())
+  {
+    m_os<<"template <>\n";
+    m_os<<m_classdef.cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.cpp_name()<<"();\n";
+  } else
+  {
+    m_os<<"}\n"; // Close current namespace   
+    // Open template namespace     
+    m_os<<"namespace "<<m_classdef.get_parent()->cpp_name()<<" {\n"; 
+    m_os<<"template <>\n";
+    m_os<<m_classdef.identifier()->cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.identifier()->cpp_name()<<"()\n";
+    m_os<<"{\n"; // Open function content 
+    m_os<<"\tASN1_BER_LOG_DEBUG(\"ctor::"<<n->name()<<"\");\n";
+    gen_ctor_set_ftvf();
+    m_os<<"}\n"; // Close function content 
+    
+    m_os<<"} // close namespace\n"; // Close template namespace   
+    // Reopen current namespace    
+    m_os<<"namespace "<<m_Gen.get_module()->cpp_name()<<" {\n"; 
+  }
+  
+  m_os<<"\n";
+
+}
+//
+void cgcpph_objectset::gen_printf(const std::string &scope)
+{
+}
+
+
+/**
+ *
+ */ 
+void cgcpph_objectset::gen_objectset()
+{
+  std::for_each(m_classdef.begin()
+                , m_classdef.end()
+                , g_objectset(m_os,*this));
+}
diff --git a/libgen/cpp/cgcpph_objectset.h b/libgen/cpp/cgcpph_objectset.h
new file mode 100644 (file)
index 0000000..deb5daf
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef CGCPPH_OBJECTSET_H
+#define CGCPPH_OBJECTSET_H
+
+
+/**
+ *
+ */
+class cgcppg_objectset : public cgh_object
+{
+  protected:
+    cgcppg_objectset(const  cgcppg_objectset &s) : cgh_object(s.m_Gencpp
+                                                      , s.m_os
+                                                      , s.m_object
+                                                      , s.m_classdef
+                                                       )
+                       , m_Gen(s.m_Gen)
+                       , m_log(s.m_log)
+    {}  
+  public:
+    cgcppg_objectset(  generate_codec_cpp &g
+                  , std::ostream &os
+                  , asn1::object &s 
+                  , asn1::classdef &c 
+                  ) ;
+   
+    ~cgcppg_objectset();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+
+  protected:
+    std::fstream          &m_log;
+    generate_codec_cpp    &m_Gen;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_octetstring.cpp b/libgen/cpp/cgcpph_octetstring.cpp
new file mode 100644 (file)
index 0000000..aa49313
--- /dev/null
@@ -0,0 +1,221 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_primitive.h"
+#include "cgcpph_octetstring.h"
+
+
+cgcpph_octet_string::cgcpph_octet_string(generate_codec_cpp &g,std::ostream &os,asn1::octet_string &s)
+  :  cgcpph_primitive(g,os,s)
+  , m_octet_string(s)
+{
+}
+
+cgcpph_octet_string::~cgcpph_octet_string()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgcpph_octet_string::generate_ctors()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_octet_string helper launched "<<std::endl;
+
+  m_os<<m_structName<<"::"<<m_structName<<"(const asn1::tag &t)\n";
+  m_os<<"\t: OCTET_STRING(t)\n";
+  m_os<<"{\n";
+  m_os<<"}\n";
+
+  m_os<<m_structName<<"::~"<<m_structName<<"()\n";
+  m_os<<"{\n";
+  m_os<<"}\n";
+  // copy
+  m_os<<m_structName<<"::"<<m_structName<<"(const "<<m_structName<<" &c)\n";
+  m_os<<" : OCTET_STRING(c)\n";
+  m_os<<"{\n";
+  m_os<<"}\n";
+
+  // Assignement 
+  m_os<<"\n"<<m_structName<<"&\n";
+  m_os<<m_structName<<"::operator =(const "<<m_structName<<" &c)\n";
+  m_os<<"{\n";
+  m_os<<"\tif ( &c != this)\n";
+  m_os<<"\t\t"<<"m_Prim = c.m_Prim;\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+  m_os<<"\n"<<m_structName<<" &\n";
+  m_os<<m_structName<<"::operator =(const asn1::prim::types::String &t"<<") \n";
+  m_os<<"{\n";
+  //m_os<<"\tif ( &t != this)\n";
+  m_os<<"\t"<<"m_Prim = t ;\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+}
+
+//
+void cgcpph_octet_string::generate_printf()
+{
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<(OCTET_STRING)s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_octet_string::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cgcpph_octet_string::generate_ber()
+{
+  std::string scope;
+  std::string structName = m_octet_string.identifier_cpp_name();
+  asn1::node *type       = &m_octet_string;
+  //
+  //
+  if (m_octet_string.tagged()) {
+    if ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<scope<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d BIG Issue \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_octet_string.tag().m_class<<","<<m_octet_string.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,4));\n";
+      m_os<<"\tctx.encode_octetstring(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<scope<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_octet_string.tag().m_class<<","<<m_octet_string.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\tOCTET_STRING tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp.get_value();\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+  /* Handler BER Codec */
+  if (m_gencpp.with_codec())
+  {
+    std::string ns(m_gencpp.get_module()->cpp_name());
+    std::string structName(ns + "::" + m_octet_string.identifier_cpp_name());
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+
+
+    cpp<<"// octet_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if ( m_octet_string.tagged() 
+         &&  ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+       )
+    {
+      cpp<<"\tasn1::tag t("<<m_octet_string.tag().m_class<<","<<m_octet_string.tag().m_value<<",true);\n";
+      cpp<<"\tstd::cout<<\"encode "<<structName<<" with BER explicit tag TODO \"<<std::endl;\n";
+    }
+    cpp<<"\tc.encode_octetstring(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_octetstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_octet_string::generate_oer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns(m_gencpp.get_module()->cpp_name());
+    std::string structName(ns + "::" + m_octet_string.identifier_cpp_name());
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+
+
+    cpp<<"// octet_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_octetstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+//
+void cgcpph_octet_string::generate_jer()
+{
+  std::string ns(m_gencpp.get_module()->cpp_name());
+  std::string structName(ns + "::" + m_octet_string.identifier_cpp_name());
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+
+    cpp<<"// octet_string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_octetstring(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_octet_string::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_octetstring.h b/libgen/cpp/cgcpph_octetstring.h
new file mode 100644 (file)
index 0000000..f4dec7d
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef CGCPPH_OCTETSTRING_H
+#define CGCPPH_OCTETSTRING_H
+
+
+/**
+ *
+ */
+class cgcpph_octet_string : public cgcpph_primitive
+{
+  protected:
+    cgcpph_octet_string(const  cgcpph_octet_string &s) : cgcpph_primitive(s)
+                                     , m_octet_string(s.m_octet_string) {}  
+  public:
+    //
+    cgcpph_octet_string(generate_codec_cpp &g,std::ostream &os,asn1::octet_string &s) ;
+    //
+    ~cgcpph_octet_string();
+    
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_printf();
+    
+    virtual void generate_ctors();
+
+    virtual void generate_operators() {};
+  protected:  
+    asn1::octet_string  &m_octet_string;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_oid.cpp b/libgen/cpp/cgcpph_oid.cpp
new file mode 100644 (file)
index 0000000..4531cb4
--- /dev/null
@@ -0,0 +1,240 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_construct.h"
+#include "cgcpph_oid.h"
+
+
+cgcpph_oid::cgcpph_oid( generate_codec_cpp &g
+                      , std::ostream &os
+                      , asn1::object_identifier &s)
+  : cgh_construct(g,os,s) , m_oid(s)
+{
+}
+
+cgcpph_oid::~cgcpph_oid()
+{
+}
+
+
+/** Helper functions
+ *
+ *  
+ */ 
+void cgcpph_oid::generate()
+{
+  
+  GEN_LOG_DEBUG("cgcpph_oid::generate node=%s\n",m_oid.identifier_cpp_name().c_str());
+  // May be just include each module ...
+  // Handles the call with condition of the different generate_xxx
+  cgcpp_helper::generate();
+}
+
+//
+void cgcpph_oid::generate_ctors()
+{
+  std::string structName = m_oid.identifier_cpp_name();
+
+  if (m_gencpp.with_source_comment())
+         m_os<<"// cgcpph_oid helper launched \n";
+  
+  // With tag
+  m_os<<"\n"<<structName;
+  m_os<<"::"<<structName<<"(const asn1::tag &t) : OBJECT_IDENTIFIER(t)\n{\n}\n";
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"\n// Copy Constructor "<<structName<<"\n//\n";
+  } else
+    m_os<<"\n";
+
+  m_os<<structName;
+  m_os<<"::"<<structName<<"(const "<<structName<<" &c) : OBJECT_IDENTIFIER(c)\n{\n}\n";
+  // Copy Assignment
+  m_os<<structName<<"& ";
+  m_os<<structName;
+  m_os<<"::operator =(const "<<structName<<" &c) \n";
+  m_os<<"{\n";
+  m_os<<"\t"<<m_oid.cpp_name()<<"::operator=(c);\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+  // Copy Assignment
+  m_os<<structName<<"& ";
+  m_os<<structName;
+  m_os<<"::operator =(const "<<m_oid.cpp_name()<<" &c) \n";
+  m_os<<"{\n";
+  m_os<<"\t"<<m_oid.cpp_name()<<"::operator=(c);\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+}
+
+
+
+//
+void cgcpph_oid::generate_printf()
+{
+  std::string structName = m_oid.identifier_cpp_name();
+  
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<structName<<" &s)\n{\n";
+  m_os<<"\tos<<(OBJECT_IDENTIFIER)s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+//
+void cgcpph_oid::generate_operators()
+{
+  std::string structName = m_oid.identifier_cpp_name();
+  
+  // With tag
+  m_os<<"\n// comparaison "<<structName<<"\n//\n";
+  m_os<<"bool\n"<<structName;
+  m_os<<"::operator =="<<"( "<<structName<<" &t)\n{\n";
+  m_os<<"\treturn "<<m_oid.cpp_name()<<"::operator == (t);\n";
+  m_os<<"}\n";
+}
+
+
+// generate codec part
+void cgcpph_oid::generate_per()
+{
+}
+
+//
+void cgcpph_oid::generate_ber()
+{
+  std::string structName = m_oid.identifier_cpp_name();
+  //
+  if (m_oid.tagged()
+     &&  m_gencpp.is_tag_explicit(m_oid))
+  {
+      m_os<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_oid.tag().m_class<<","<<m_oid.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,6));\n";
+      m_os<<"\tctx.encode_boolean(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_oid.tag().m_class<<","<<m_oid.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\tOBJECT_IDENTIFIER tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp;\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+  }
+  //
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  ( ns + "::" +m_oid.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+    // Generate Implementation
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecBER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    if ( m_oid.tagged() 
+         &&  m_gencpp.is_tag_explicit(m_oid))
+    {
+      cpp<<"\tstd::cout<<\"codecBER::encode "<<structName<<" explicitly tagged\"<<std::endl;\n";
+    }
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    if ( m_oid.tagged() 
+         &&  m_gencpp.is_tag_explicit(m_oid))
+    {
+      cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" explicitly tagged\"<<std::endl;\n";
+    }
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_oid::generate_oer()
+{
+  //
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  ( ns + "::" +m_oid.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+    // Generate Implementation
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecOER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecOER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_oid::generate_jer()
+{
+  //m_gencpp.gen_template_signature(m_os,type);
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  ( ns + "::" +m_oid.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+    // Generate Implementation
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecJER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecJER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_oid::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_oid.h b/libgen/cpp/cgcpph_oid.h
new file mode 100644 (file)
index 0000000..676c62c
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CGCPPH_OBJECT_IDENTIFIER_H
+#define CGCPPH_OBJECT_IDENTIFIER_H
+
+
+/**
+ *
+ */
+class cgcpph_oid : public cgh_construct
+{
+  protected:
+    cgcpph_oid(const  cgcpph_oid &s) : cgh_construct(s.m_gencpp,s.m_os,s.m_c)
+                                      , m_oid(s.m_oid)
+    {}  
+  public:
+    cgcpph_oid( generate_codec_cpp &g
+              , std::ostream &os
+              , asn1::object_identifier &s) ;
+   
+    ~cgcpph_oid();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_printf();
+    virtual void generate_ctors();
+    virtual void generate_operators();
+  protected:
+    asn1::object_identifier &m_oid;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_primitive.cpp b/libgen/cpp/cgcpph_primitive.cpp
new file mode 100644 (file)
index 0000000..b11827c
--- /dev/null
@@ -0,0 +1,292 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_primitive.h"
+
+
+cgcpph_primitive::cgcpph_primitive( generate_codec_cpp &g
+                           , std::ostream &os
+                           , asn1::primitive &s)
+  : cgcpp_helper(g,os) , m_primitive(s)
+{
+  m_structName  = m_primitive.identifier_cpp_name();
+}
+
+cgcpph_primitive::~cgcpph_primitive()
+{
+}
+
+
+/** Helper functions
+ *
+ *  
+ */ 
+void cgcpph_primitive::generate()
+{
+  
+  GEN_LOG_DEBUG("cgcpph_primitive::generate node=%s\n",m_primitive.identifier_cpp_name().c_str());
+  cgcpp_helper::generate();
+}
+
+/**
+ *
+ */
+void 
+cgcpph_primitive::generate_descriptor()
+{
+  std::string cn(m_primitive.identifier_cpp_name());
+  unsigned int _count = 0;
+  m_os<<"static asn1::tag TAGS_"<<m_primitive.identifier_cpp_name()<<"[] = {\n";
+  if (m_primitive.tagged())
+  {
+    m_os<<"asn1::tag("<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value;
+    if (m_gencpp.is_tag_explicit(m_primitive))
+           m_os<<",true";
+    m_os<<")\n";
+  } else {
+    m_os<<"asn1::tag("<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value;
+    m_os<<")\n";
+  }
+  m_os<<"};\n";
+
+  m_os<<"const asn1::types::descriptor "<<m_structName<<"::_meta = {\n";
+  if (m_primitive.tagged())
+  {
+  }
+  m_os<<"  TAGS_"<<cn<<",";
+  m_os<<"sizeof(TAGS_"<<cn<<")/sizeof(TAGS_"<<cn<<"[0]),\n"; /* Tag List */
+  m_os<<"  NULL,\n"; /* MEMBER List       */
+  m_os<<"  0,\n";    /* Member list count */
+  m_os<<"  NULL,\n"; /*tag to element */
+  m_os<<"  0\n"; /* tag to element count*/
+  m_os<<"};\n";
+  m_os<<std::endl;
+}
+
+void
+cgcpph_primitive::generate_operators()
+{
+  gen_equal();
+}
+//
+void cgcpph_primitive::generate_ctors()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_primitive helper launched ";
+  // With tag
+  m_os<<"\n"<<m_structName;
+  m_os<<"::"<<m_structName<<"(const asn1::tag &t)\n";
+  m_os<<"\t\t: "<<m_primitive.cpp_name()<<"(t)\n{\n}\n";
+  m_os<<"\n// Copy Constructor "<<m_structName<<"\n//\n";
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_structName<<" &c)\n";
+  m_os<<"\t\t: "<<m_primitive.cpp_name()<<"()\n{\n}\n";
+  //clone
+  m_os<<m_structName<<" *";
+  m_os<<m_structName;
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+  m_os<<"\treturn new "<<m_structName<<"(*this);\n";
+  m_os<<"}\n";
+
+}
+//
+void cgcpph_primitive::gen_equal()
+{
+  m_os<<"\n// comparaison "<<m_structName<<"\n//\n";
+  m_os<<"bool\n"<<m_structName;
+  m_os<<"::operator =="<<"( "<<m_structName<<" &t)\n{\n";
+  m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+
+//
+void cgcpph_primitive::generate_printf()
+{
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<("<<m_primitive.cpp_name()<<")s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_primitive::generate_per()
+{
+}
+
+//
+void cgcpph_primitive::generate_ber()
+{
+  std::string scope;
+  std::string structName = m_primitive.identifier_cpp_name();
+  //
+  if (m_primitive.tagged())
+  {
+    if ( m_gencpp.tag_mode(&m_primitive) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<scope<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value<<",true);\n";
+      // Why isn't the tag id in the class ? 
+      //  It is but than it can be modified. 
+      m_os<<"\tset_tag(asn1::tag(0,"<<m_primitive.primitive_tag()<<"));\n";
+      // !!!!!!!!!! WARNING
+      m_os<<"\tctx.encode_boolean(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<scope<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      //m_os<<"\t\tBOOLEAN tmp;\n";
+      m_os<<"\t\t"<<m_primitive.cpp_name()<<" tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp;\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+  if (m_gencpp.with_codec())
+  {
+    std::string ns(m_gencpp.get_module()->cpp_name());
+    std::string structName(ns + "::" + m_primitive.identifier()->cpp_name());
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// primitive generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    switch (m_primitive.type_id()())
+    {
+    case asn1::type::ASN1_NULL:
+      cpp<<"\tc.encode_null(_t);\n"; break;
+    case asn1::type::ASN1_BIT_STRING:
+      cpp<<"\tc.encode_bitstring(_t);\n"; break;
+    case asn1::type::ASN1_OCTET_STRING:
+      cpp<<"\tc.encode_octetstring(_t);\n"; break;
+    case asn1::type::ASN1_STRING:
+    case asn1::type::ASN1_STRING_VisibleString:
+    case asn1::type::ASN1_STRING_ISO646String:    /* aka VisibleString */
+    case asn1::type::ASN1_STRING_UniversalString:
+    case asn1::type::ASN1_STRING_BMPString:
+    case asn1::type::ASN1_STRING_UTF8String  :
+    case asn1::type::ASN1_STRING_GeneralString:
+    case asn1::type::ASN1_STRING_GraphicString:
+    case asn1::type::ASN1_STRING_T61String:
+    case asn1::type::ASN1_STRING_VideotexString:
+    case asn1::type::ASN1_STRING_ObjectDescriptor:
+    case asn1::type::ASN1_STRING_IA5String:
+    case asn1::type::ASN1_STRING_PrintableString:
+    case asn1::type::ASN1_STRING_NumericString:
+    case asn1::type::ASN1_STRING_TeletexString:
+      cpp<<"\tc.encode_string(_t);\n"; break;
+    //case asn1::type::ASN1_UNIVERSAL:
+    case asn1::type::ASN1_INTEGER:
+    case asn1::type::ASN1_BOOLEAN:
+    case asn1::type::ASN1_REAL:
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    case asn1::type::ASN1_RELATIVE_OID:
+      defautl:
+           ;
+    }
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+//
+void cgcpph_primitive::generate_oer()
+{
+  //
+}
+
+//
+void cgcpph_primitive::generate_jer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns(m_gencpp.get_module()->cpp_name());
+    std::string structName(ns + "::" + m_primitive.identifier()->cpp_name());
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// primitive generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    switch (m_primitive.type_id()())
+    {
+    case asn1::type::ASN1_NULL:
+      cpp<<"\tc.encode_null(_t);\n"; break;
+    case asn1::type::ASN1_BIT_STRING:
+      cpp<<"\tc.encode_bitstring(_t);\n"; break;
+    case asn1::type::ASN1_OCTET_STRING:
+      cpp<<"\tc.encode_octetstring(_t);\n"; break;
+    case asn1::type::ASN1_STRING:
+    case asn1::type::ASN1_STRING_VisibleString:
+    case asn1::type::ASN1_STRING_ISO646String:    /* aka VisibleString */
+    case asn1::type::ASN1_STRING_UniversalString:
+    case asn1::type::ASN1_STRING_BMPString:
+    case asn1::type::ASN1_STRING_UTF8String  :
+    case asn1::type::ASN1_STRING_GeneralString:
+    case asn1::type::ASN1_STRING_GraphicString:
+    case asn1::type::ASN1_STRING_T61String:
+    case asn1::type::ASN1_STRING_VideotexString:
+    case asn1::type::ASN1_STRING_ObjectDescriptor:
+    case asn1::type::ASN1_STRING_IA5String:
+    case asn1::type::ASN1_STRING_PrintableString:
+    case asn1::type::ASN1_STRING_NumericString:
+    case asn1::type::ASN1_STRING_TeletexString:
+      cpp<<"\tc.encode_string(_t);\n"; break;
+    //case asn1::type::ASN1_UNIVERSAL:
+    case asn1::type::ASN1_INTEGER:
+    case asn1::type::ASN1_BOOLEAN:
+    case asn1::type::ASN1_REAL:
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    case asn1::type::ASN1_RELATIVE_OID:
+      defautl:
+           ;
+    }
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_primitive::generate_xer()
+{
+}
diff --git a/libgen/cpp/cgcpph_primitive.h b/libgen/cpp/cgcpph_primitive.h
new file mode 100644 (file)
index 0000000..45ee899
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef CGCPPH_PRIMITIVE_H
+#define CGCPPH_PRIMITIVE_H
+
+
+/**
+ * Generic code generation for all primitive types.
+ * boolean, integer, object_identifier, all strings,
+ * real, bit_string, octet_string
+ * all primitive generators should inherit from this
+ * class. This will simplify the code generation. 
+ * Provides lesser specificities 
+ */
+class cgcpph_primitive : public cgcpp_helper
+{
+  protected:
+    cgcpph_primitive(const  cgcpph_primitive &s) : cgcpp_helper(s.m_gencpp,s.m_os)
+                                      , m_primitive(s.m_primitive)
+                                      , m_structName(s.m_structName)
+    {}  
+  public:
+    cgcpph_primitive(generate_codec_cpp &g
+                , std::ostream &os
+                , asn1::primitive &s) ;
+   
+    ~cgcpph_primitive();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_descriptor();
+    
+    virtual void generate_printf();
+    
+    virtual void generate_ctors();
+    
+    virtual void generate_operators();
+    
+    void gen_equal();
+
+  protected:
+    asn1::primitive       &m_primitive;
+    std::string            m_structName;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_real.cpp b/libgen/cpp/cgcpph_real.cpp
new file mode 100644 (file)
index 0000000..f16106b
--- /dev/null
@@ -0,0 +1,123 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_primitive.h"
+#include "cgcpph_real.h"
+
+
+cgcpph_real::cgcpph_real(generate_codec_cpp &g,std::ostream &os,asn1::real &s)
+  : cgcpph_primitive(g,os,s)
+  , m_real(s)
+{
+}
+
+cgcpph_real::~cgcpph_real()
+{
+}
+
+
+//
+void cgcpph_real::generate_ctors()
+{
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"// cgcpph_real ctors helper launched ";
+    m_os<<m_structName<<"\n";
+  }
+  GEN_LOG_DEBUG("cgcpph_real::generate node=%s\n",m_real.identifier_cpp_name().c_str());
+  // May be just include each module ...
+  m_os<<"\n"<<m_structName;
+  m_os<<"::"<<m_structName<<"(const asn1::tag &t) : REAL(t)\n{\n}\n";
+  m_os<<"\n// Copy Constructor "<<m_structName<<"\n//\n";
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_structName<<" &c) : REAL()\n{\n}\n";
+}
+
+void cgcpph_real::generate_operators()
+{
+  gen_equal();
+}
+//
+void cgcpph_real::gen_equal()
+{
+  m_os<<"\n// comparaison "<<m_structName<<"\n//\n";
+  m_os<<"bool\n"<<m_structName;
+  m_os<<"::operator =="<<"( "<<m_structName<<" &t)\n{\n";
+  m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+//
+void cgcpph_real::generate_printf()
+{
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<(REAL)s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_real::generate_per()
+{
+}
+
+//
+void cgcpph_real::generate_ber()
+{
+  //
+  if (m_real.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_real) )
+    {
+      m_os<<"void "<<m_structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_real.tag().m_class<<","<<m_real.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,1));\n";
+      m_os<<"\tctx.encode_real(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<"int "<<m_structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_real.tag().m_class<<","<<m_real.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\tBOOLEAN tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp.get_value();\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+}
+
+//
+void cgcpph_real::generate_oer()
+{
+  //
+}
+
+//
+void cgcpph_real::generate_jer()
+{
+}
+
+//
+void cgcpph_real::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_real.h b/libgen/cpp/cgcpph_real.h
new file mode 100644 (file)
index 0000000..8ca7aa3
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGCPPH_REAL_H
+#define CGCPPH_REAL_H
+
+
+/**
+ *
+ */
+class cgcpph_real : public cgcpph_primitive
+{
+  protected:
+    cgcpph_real(const  cgcpph_real &s) : cgcpph_primitive(s)
+                                      , m_real(s.m_real)
+    {}  
+  public:
+    cgcpph_real(generate_codec_cpp &g,std::ostream &os,asn1::real &s) ;
+   
+    ~cgcpph_real();
+    
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_ctors();
+
+    virtual void generate_operators();
+
+    void gen_equal();
+    
+    virtual void generate_printf();
+  protected:
+    asn1::real         &m_real;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_sequence.cpp b/libgen/cpp/cgcpph_sequence.cpp
new file mode 100644 (file)
index 0000000..e067eec
--- /dev/null
@@ -0,0 +1,598 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "asn1_visitor.h"
+#include "cgh_construct.h"
+#include "cgcpph_sequence.h"
+
+
+cgcpph_sequence::cgcpph_sequence(generate_codec_cpp &g,std::ostream &os,asn1::sequence &s)
+  :  m_seq(s) 
+    , cgh_construct(g,os,s)
+{
+}
+
+cgcpph_sequence::~cgcpph_sequence()
+{
+}
+
+
+// Helper functions
+void cgcpph_sequence::generate(const std::string &scope)
+{
+  bool        priv  = m_seq.is_private() ;
+
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"\n//\n// cgcpph_sequence helper launched ";
+    m_os<<"\n//\n";
+  }
+  /* Issue with parameterized types */
+  cgcpp_helper::generate();
+
+  if (m_gencpp.with_ber())
+    gen_data_length(); 
+
+  m_os<<std::endl;
+}
+
+/**
+ * @note if there are parameters, 
+ * don't generate the tables it does not work
+ * here.
+ * I need to review the parameterized types. 
+ * Introduce the notion of instance of parameterized type.
+ * It make more sense.
+ */
+void cgcpph_sequence::generate_descriptor()
+{
+  if (m_seq.identifier()->parameters())
+      return ; 
+  cgh_construct::gen_desc_seqset();
+}
+
+/**
+ *
+ */
+void cgcpph_sequence::generate_ctors()
+{
+  std::string scope("");
+  bool        priv( m_seq.is_private() );
+  gen_ctor(scope,priv);
+  
+  gen_clone(scope,priv);
+}
+
+/**
+ *  generate codec part
+ */
+void cgcpph_sequence::generate_per()
+{
+}
+
+//
+void cgcpph_sequence::generate_ber()
+{
+  bool        priv( m_seq.is_private() );
+
+  gen_nencode("",priv);
+  gen_ndecode("",priv);
+
+  if (m_gencpp.with_codec())
+  {
+    std::string  ns ( m_gencpp.get_module()->cpp_name() ) ;
+    std::string  structName ( ns + "::" +m_seq.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// sequence type "<<structName<<" priv="<<priv<<"\n";
+    hpp<<"template<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    /* Generate implementation */
+    gen_codec_ber_encode();
+    /* Implementation of decoding stream */
+#if 1
+    gen_codec_ber_decode();
+#else
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tif ( c.decode_sequence_preamble(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    /* loop over fields */
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+        } else
+        {
+          if (f->flags().is_optional() && (! f->flags().is_default()))
+          {
+            cpp<<"\tdecode(c,_t."<<f->cpp_name()<<".get());\n";
+          } else
+          {
+            cpp<<"\tdecode(c,_t."<<f->cpp_name()<<");\n";
+          }
+          //cpp<<"\t}\n";
+       }
+      }
+    }
+    cpp<<"\tif ( c.decode_sequence_epilogue(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+#endif
+
+    /**/
+  }
+}
+
+//
+void cgcpph_sequence::generate_oer()
+{
+}
+
+//
+void cgcpph_sequence::generate_xer()
+{
+}
+
+
+/**
+* Generate ctor code
+*/ 
+void
+cgcpph_sequence::gen_ctor(const std::string &scope,bool priv)
+{
+  asn1::node::iterator  lit       = m_seq.begin();
+  std::string           structName;
+
+  m_gencpp.gen_template_signature(m_os,&m_seq);
+
+  if (!priv)     
+  {
+    structName = m_seq.identifier_cpp_name();  
+  } else 
+  {
+    structName = m_seq.cpp_name();  
+  }
+
+  m_os<<structName;
+  m_gencpp.gen_template_signature_class(m_os,&m_seq);
+  m_os<<"::"<<structName<<"( ";
+  m_os<<"const asn1::tag &t) "<<std::endl;
+
+  m_os<<"  : asn1::types::sequence_type(t)\n";
+  
+  for ( asn1::node::iterator it = m_seq.begin()
+      ; it != m_seq.end() ; ++it)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL)
+    {
+      m_os<<"  , ";
+      if (attr_type->meta_id()() == asn1::meta::OBJECT)
+      {
+        m_os<<f->cpp_name()<<"(NULL)";
+      }
+      //std::cout<<"1 and HERE "<<(*it)->name()<<std::endl;
+      if ( f->flags().is_default() )
+      {
+        gen_ctor_init(f);
+      } else 
+      {
+        switch(attr_type->type_id()())
+        {
+           case asn1::type::ASN1_INTEGER:
+             if ( attr_type && attr_type->tagged())
+             { // Ok tagged value
+               if(attr_type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+               {
+                 asn1::node::tag_type lt = attr_type->tag();
+                 m_os<<(*it)->cpp_name()<<"(asn1::tag("<<lt.m_class<<","<<lt.m_value<<"))";
+               } else
+                 m_os<<(*it)->cpp_name()<<"(/*Explicit tag*/)";
+             } else
+               m_os<<(*it)->cpp_name()<<"()";
+             //os<<(*it)->cpp_name()<<"(asn1::prim::types::Integer(0))";
+             break;
+           case asn1::type::ASN1_BOOLEAN:
+             m_os<<(*it)->cpp_name()<<"()";
+             //os<<(*it)->cpp_name()<<"(asn1::prim::types::Boolean(false))";
+             break;
+           default:
+           {
+              if ( attr_type && attr_type->tagged())
+              { // Ok tagged value
+                if(attr_type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+                {
+                  asn1::node::tag_type lt = attr_type->tag();
+                  m_os<<(*it)->cpp_name()<<"(asn1::tag("<<lt.m_class<<","<<lt.m_value<<"))";
+                } else
+                  m_os<<(*it)->cpp_name()<<"(/*Explicit tag*/)";
+              } else
+                m_os<<(*it)->cpp_name()<<"(/*def no tag*/)";
+           }
+
+        } /* end switch */
+      }
+      if (  (*it)->flags().is_optional() )
+      {
+        m_os<<"/*optional*/";
+      }
+        m_os<<"\n";
+    }
+  } /* end for */
+
+  m_os<<"{"<<std::endl;
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_seq.identifier_name();
+    m_os<<"(%p) seq CREATE "<<m_seq.identifier_name()<<" \",this);\n";
+  }
+  m_os<<"}\n\n";
+  gen_copy_ctor(scope,priv);
+}
+
+/**
+*  Initialize member attributes in ctor
+*/ 
+void
+cgcpph_sequence::gen_ctor_init(asn1::field *field)
+{
+  asn1::typenode *attr_type = field->get_type();
+  switch(attr_type->type_id()()) {
+      case asn1::type::ASN1_INTEGER:
+          {
+            asn1::value::ptr val = field->flags().m_value1;
+            if (! val.is_nul()) {
+              m_os<<field->cpp_name()<<"(INTEGER("<< val->m_integer <<"))";
+            } else
+              m_os<<field->cpp_name()<<"()";
+          }
+          break;
+#if 0
+      case asn1::type::ASN1_BOOLEAN:
+        if (  !  (field->flags().m_value1).is_nul() )
+        {
+            switch ((field->flags().m_value1)->type)
+            {
+                case asn1::value::VT_TRUE:
+                  m_os<<field->cpp_name()<<"(BOOLEAN(asn1::prim::types::Boolean(true)))";
+                 break;
+                case asn1::value::VT_FALSE:
+                  m_os<<field->cpp_name()<<"(BOOLEAN(asn1::prim::types::Boolean(false)))";
+                 break;
+                default:
+                  m_os<<field->cpp_name()<<"(false) /*no*/";
+            }
+        } else 
+          m_os<<field->cpp_name()<<"(false) /*m_value1 NULL "<<field->name()<<"*/";
+          break;
+#endif
+        case asn1::type::ASN1_STRING:
+        case asn1::type::ASN1_STRING_IA5String:
+        case asn1::type::ASN1_STRING_PrintableString:
+        case asn1::type::ASN1_STRING_VisibleString:
+        case asn1::type::ASN1_STRING_ISO646String:
+        case asn1::type::ASN1_STRING_NumericString:
+        case asn1::type::ASN1_STRING_UniversalString:
+        case asn1::type::ASN1_STRING_BMPString:
+        case asn1::type::ASN1_STRING_UTF8String  :
+        case asn1::type::ASN1_STRING_GeneralString:
+        case asn1::type::ASN1_STRING_GraphicString:
+        case asn1::type::ASN1_STRING_TeletexString:
+        case asn1::type::ASN1_STRING_T61String:
+        case asn1::type::ASN1_STRING_VideotexString:
+        case asn1::type::ASN1_STRING_ObjectDescriptor:
+          {
+            asn1::value::ptr val = field->flags().m_value1;
+            if (! val.is_nul()) {
+              m_os<<field->cpp_name()<<"(asn1::prim::types::String("<< val->m_string <<"))";
+            } else
+              m_os<<field->cpp_name()<<"()";
+          }
+            break;
+      
+      default:
+      {
+      if ( attr_type && attr_type->tagged())
+      { // Ok tagged value
+        if(attr_type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+        {
+          asn1::node::tag_type lt = attr_type->tag();
+            m_os<<field->cpp_name()<<"(asn1::tag("<<lt.m_class<<","<<lt.m_value<<"))";
+        } else
+            m_os<<field->cpp_name()<<"(/*Explicit tag*/)";
+      } else
+        m_os<<field->cpp_name()<<"(/*def no tag*/)";
+      }
+  }
+}
+#if 1
+
+/**
+ * Helper class to generate parameter 
+ * initialization per attribute.
+ */
+class gco_pc 
+{
+  public:
+    gco_pc(std::ostream &_os,generate_codec_cpp &_g,asn1::sequence &_c)
+      : m_os(_os) , m_log(_g.logger()), m_Gen(_g), m_seq(_c)
+    {
+      m_assign = m_seq.identifier()->as_assignment();
+      assert( (m_assign != NULL ) && " m_assign should not be NULL for choice type");
+    }
+
+    void do_parameters(asn1::assignment *_a)
+    {
+      if ( ! _a)
+        return;
+      asn1::constructed *aplist = _a->parameters();
+      if ( ! aplist)
+        return;
+      for ( asn1::node::iterator it = aplist->begin() ;
+            it != aplist->end(); ++it)
+      {
+        /* either value_set, object_set value, typeref */
+        asn1::parameter *p = dynamic_cast<asn1::parameter *>(*it);
+        if (asn1::node *g = p->get_governor())
+        {
+          asn1::typeref *objr = dynamic_cast<asn1::typeref *>(g);      
+          if (objr)
+          {
+            m_os<<"\t// "<<g->name()<<" "<<p->name()<<std::endl;
+            if (!objr->is_simple())
+            {
+              m_os<<"\t"<<p->cpp_name()<<" = t."<<p->cpp_name()<<";"<<std::endl;
+            }
+          }else
+          {
+            m_os<<"\t// "<<g->name()<<" "<<p->name()<<std::endl;
+          }
+        }
+      }
+    }
+  protected:
+    asn1::node            *m_rt;
+    asn1::assignment       *m_assign;
+    std::fstream          &m_log;
+    std::ostream          &m_os;
+    generate_codec_cpp    &m_Gen;
+    asn1::sequence        &m_seq;
+};
+
+#endif
+/**
+*
+* Generate code for copy ctor
+*/ 
+void
+cgcpph_sequence::gen_copy_ctor(const std::string &scope,bool priv)
+{
+  std::string          name;
+  asn1::node::iterator lit   = m_seq.begin();
+  asn1::assignment    *ident = m_seq.identifier()->as_assignment();
+  asn1::sequence      *type  = &m_seq;
+  bool                 first = true;
+
+  m_gencpp.gen_template_signature(m_os,&m_seq);
+  if (!priv)     
+  {
+      name=type->identifier_cpp_name();
+      m_os<<""<<type->identifier_cpp_name();
+      m_gencpp.gen_template_signature_class(m_os,type);
+      m_os<<"::"<<type->identifier_cpp_name()<<"(const ";
+      m_os<<type->identifier_cpp_name()<<" &t)"<<"\t"<<std::endl;
+  } else 
+  {
+      name = type->cpp_name();
+      m_os<<""<<type->cpp_name();
+      m_gencpp.gen_template_signature_class(m_os,type);
+      m_os<<"::"<<type->cpp_name()<<"(const ";
+      m_os<<type->cpp_name()<<" &t)"<<"\t"<<std::endl;
+  }
+
+  m_os<<"  : asn1::types::sequence_type(t)\n";
+  for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+
+    if (attr_type != NULL)
+    {
+      m_os<<"  , ";
+      m_os<<(*it)->cpp_name()<<"(t."<<(*it)->cpp_name()<<")";
+      if (  (*it)->flags().is_optional() ) {
+        m_os<<"/*optional*/";
+      }
+      m_os<<"\n";
+    }
+  }
+
+  m_os<<"{"<<std::endl;
+  if (m_gencpp.with_source_debug())
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<name<<" copy ctor\");"<<std::endl;
+  if (ident->parameters() && ident->parameters()->size()>0)
+  {
+    gco_pc docp_params(m_os,m_gencpp,m_seq);
+    docp_params.do_parameters(m_seq.identifier()->as_assignment());
+  }
+  m_os<<"}\n\n";
+}
+
+/**
+ *
+ */ 
+void
+cgcpph_sequence::gen_clone(const std::string &scope,bool priv)
+{
+  std::string lscope;
+  asn1::node  *type         = &m_seq;
+  asn1::node  *ident        = m_seq.identifier();
+  asn1::constructed *params = NULL;
+  std::string  structName ; 
+
+  if (ident != NULL) 
+  {
+    params = ident->parameters();
+  } 
+
+  if (!priv)     
+  {
+    structName = type->identifier_cpp_name();  
+  } else 
+  {
+    structName = type->cpp_name();  
+  }
+
+  m_os<<"\n";
+  m_gencpp.gen_template_signature(m_os,type);
+  
+  m_os<<""<<scope<<structName;
+  m_gencpp.gen_template_signature_class(m_os,type);
+  m_os<<"* ";
+  
+  m_os<<scope<<structName;
+  m_gencpp.gen_template_signature_class(m_os,type);
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+
+  if (m_gencpp.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name();
+    m_os<<"::clone "<<type->identifier_name()<<" \");\n";
+  }
+  m_os<<"\treturn new "<<structName;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<"(*this);\n}\n"<<std::endl; 
+}
+
+/**
+ *
+ */ 
+void
+cgcpph_sequence::generate_operators( )
+{
+  cgh_construct::gen_equal();
+}
+
+
+/**
+ * Generate printf code
+ */ 
+void 
+cgcpph_sequence::generate_printf( )
+{
+  std::string     scope("");
+  asn1::sequence *type = &m_seq;
+  m_os<<"#if 1\n";
+  /*
+   * Try to handler sequence of sequence 
+   */
+  m_gencpp.gen_template_signature(m_os,type);
+  m_os<<"\nvoid\n";
+  m_os<<m_structName;
+  m_gencpp.gen_template_signature_class(m_os,type);
+  m_os<<"::printf(std::ostream &os) const\n{\n";
+  m_os<<"\tos<<*this;\n"<<std::endl;
+  m_os<<"}\n"; 
+
+  // friend operator <<
+  m_gencpp.gen_template_signature(m_os,type);
+  m_os<<"std::ostream &operator <<(std::ostream &os,const ";
+    
+  m_os<<m_gencpp.get_module()->cpp_name();
+  m_os<<"::"<<m_structName;
+
+      m_gencpp.gen_template_signature_class(m_os,type);
+  m_os<<" ";
+  /**
+   * TODO very wrong type should not have parameter except if its a private
+   * type
+   */ 
+  if (type->parameters() && m_gencpp.is_template(type->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,type->parameters());
+  }
+  m_os<<" &s"<<")\n{\n";
+  m_os<<"\tstd::streamsize indent = os.precision() + 2;"<<std::endl;
+  m_os<<"\tos<<std::setw(indent+10)<<\"SEQUENCE (\\n\";\n";
+  
+  for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL)
+    {
+      if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+      {
+        m_os<<"\t// Extensible marker"<<std::endl;
+      } else
+      {
+        m_os<<"\tos<<";
+        m_gencpp.gen_composite_attribute_printf(m_os,scope,*f);
+     }
+    }
+  }
+  m_os<<"\tos<<std::setw(indent)<<std::setprecision(indent-2)<<\")\";\n"; 
+  m_os<<"\treturn os;\n";
+  m_os<<"};\n\n";
+  
+  m_os<<"#endif\n";
+}
+
+/**
+ *
+ */ 
+void
+cgcpph_sequence::gen_codec(const std::string &scope,bool priv)
+{
+  std::string structName ;
+  structName = m_gencpp.get_module()->cpp_name();
+  structName  = structName + "::" +m_seq.identifier()->cpp_name();
+  
+  std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+  //m_gencpp.gen_template_signature(m_os,type);
+  hpp<<"\n// sequence type "<<scope<<"::"<<structName<<" priv="<<priv<<"\n";
+#if 0
+  hpp<<"template<>\n";
+  hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+  hpp<<"\ntemplate<>\n";
+  hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+#endif
+  if (m_gencpp.with_jer())
+  {
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+  }
+}
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/libgen/cpp/cgcpph_sequence.h b/libgen/cpp/cgcpph_sequence.h
new file mode 100644 (file)
index 0000000..78713a0
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef CGCPPH_SEQUENCE_H
+#define CGCPPH_SEQUENCE_H
+
+
+/**
+ *
+ */
+class cgcpph_sequence : public cgh_construct
+{
+  protected:
+    cgcpph_sequence(const  cgcpph_sequence &s)
+           : cgh_construct(s.m_gencpp,s.m_os,s.m_seq)
+             , m_seq(s.m_seq)
+    {}   
+  public:
+    cgcpph_sequence(generate_codec_cpp &g,std::ostream &os,asn1::sequence &s) ;
+    ~cgcpph_sequence();
+    
+    // Helper functions wrong signature !!!
+    virtual void generate(const std::string &scope) ;
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    /**
+     * Generate ctor code
+     */ 
+    void gen_ctor(const std::string &scope,bool priv);
+    /**
+     * Generate printf code
+     */ 
+    virtual void generate_printf( );
+    /**
+     *  Initialize member attributes in ctor
+     */ 
+    void gen_ctor_init(asn1::field *field);
+    /**
+     *
+     * Generate code for copy ctor
+     */ 
+    void gen_copy_ctor(const std::string &scope , bool priv);
+    /**
+     * Generate clone
+     */ 
+    void gen_clone(const std::string &scope , bool priv);
+    /**
+     *
+     */
+    virtual void generate_operators();
+    /**
+     *
+     */
+    virtual void generate_ctors();
+    /**
+     *
+     */
+    virtual void generate_descriptor();
+    /**
+     * Generate codec
+     */ 
+    void gen_codec(const std::string &scope,bool priv);
+  protected:     
+    asn1::sequence     &m_seq;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_sequenceof.cpp b/libgen/cpp/cgcpph_sequenceof.cpp
new file mode 100644 (file)
index 0000000..2ba62c2
--- /dev/null
@@ -0,0 +1,311 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_sequenceof.h"
+
+
+cgcpph_sequenceof::cgcpph_sequenceof( generate_codec_cpp &g
+                                    , std::ostream &os
+                                    , asn1::sequence_of &s)
+  :  cgcpp_helper(g,os) , m_seqof(s) 
+{
+}
+
+cgcpph_sequenceof::~cgcpph_sequenceof()
+{
+}
+
+void cgcpph_sequenceof::generate()
+{
+  std::string structName  = m_seqof.identifier()->cpp_name();
+  
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_sequenceof helper launched \n";
+  
+  GEN_LOG_DEBUG("cgcpph_sequenceof::generate node=%s\n",m_seqof.identifier_cpp_name().c_str());
+
+  gen_ctors();
+  
+  gen_equal();
+  
+  gen_printf();
+  // Generate generators
+  cgcpp_helper::generate();
+}
+//
+void cgcpph_sequenceof::gen_ctors()
+{
+  asn1::node     *ns     = NULL;
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  std::string structName = m_seqof.identifier_cpp_name();
+  std::string eltypeName;
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+    eltypeName = eltype->cpp_name();
+  
+  // With tag
+  m_os<<"\n"<<structName;
+  m_os<<"::"<<structName<<"(const asn1::tag &t)\n";
+  m_os<<"\t\t: Seq<"<<eltypeName<<">(t)\n{\n}\n";
+  m_os<<"\n// Copy Constructor "<<structName<<"\n//\n";
+  m_os<<structName;
+  m_os<<"::"<<structName<<"(const "<<structName<<" &c)\n";
+  m_os<<"\t\t: Seq<"<<eltypeName<<">(c)\n{\n}\n";
+  //clone
+  m_os<<structName<<" *";
+  m_os<<structName;
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+  m_os<<"\treturn new "<<structName<<"(*this);\n";
+  m_os<<"}\n";
+
+}
+//
+void cgcpph_sequenceof::gen_equal()
+{
+  asn1::typenode *type   = &m_seqof;
+  std::string structName = type->identifier()->cpp_name();
+  
+  // With tag
+  m_os<<"\n// comparaison "<<structName<<"\n//\n";
+  m_os<<"bool\n"<<structName;
+  m_os<<"::operator =="<<"(const "<<structName<<" &t)\n{\n";
+  m_os<<"\treturn false;\n";
+  //m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+
+//
+void cgcpph_sequenceof::gen_printf()
+{
+  std::string structName = m_seqof.identifier_cpp_name();
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  std::string eltypeName;
+  asn1::node     *ns     = NULL;
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+    eltypeName = eltype->cpp_name();
+  
+  
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<structName<<" &s)\n{\n";
+  m_os<<"\toperator <<(os,(Seq<"<<eltypeName<<"> &)s);\n";
+  //m_os<<"\tos<<\"SEQUENCE OF PERSO TODO\";\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+
+void 
+cgcpph_sequenceof::generate_ber()
+{
+  std::string NameS = m_gencpp.get_module()->cpp_name();
+  std::string eltypeName;
+  std::string structName( NameS + "::" +m_seqof.identifier()->cpp_name());
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  asn1::node     *ns     = NULL;
+
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+  {
+    if (eltype->is_primitive())
+    {
+      eltypeName =  eltype->cpp_name();
+    } else
+      eltypeName = m_gencpp.get_module()->cpp_name() +"::" + eltype->cpp_name();
+  }
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    /* Implementation */
+    cpp<<"// type sequence of "<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if ( m_seqof.tagged()
+         && ( m_gencpp.tag_mode(&m_seqof) == asn1::node::tag_type::TM_EXPLICIT))
+    {
+      cpp<<"\tstd::cout<<\"codecBER::encode sequence of "<<structName<<" UW \"<<std::endl;\n";
+    }
+    cpp<<"\tencode(c,( const Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    if ( m_seqof.tagged()
+         && ( m_gencpp.tag_mode(&m_seqof) == asn1::node::tag_type::TM_EXPLICIT))
+    {
+      cpp<<"\tstd::cout<<\"codecBER::decode sequence of "<<structName<<" UW \"<<std::endl;\n";
+    }
+    cpp<<"\treturn decode(c,( Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+// generate per
+//
+void 
+cgcpph_sequenceof::generate_per()
+{
+  std::string NameS = m_gencpp.get_module()->cpp_name();
+  std::string eltypeName;
+  std::string structName( NameS + "::" +m_seqof.identifier()->cpp_name());
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  asn1::node     *ns     = NULL;
+
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+  {
+    if (eltype->is_primitive())
+    {
+      eltypeName =  eltype->cpp_name();
+    } else
+      eltypeName = m_gencpp.get_module()->cpp_name() +"::" + eltype->cpp_name();
+  }
+
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t);\n";
+    /* Implementation */
+    cpp<<"// type sequence of "<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.put_char(\"[\",1);\n";
+    cpp<<"\tencode(c,( const Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"\tc.put_char(\"] \",2);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    //cpp<<"\tstd::cout<<\"codecPER::decode sequence of "<<structName<<" UW \"<<std::endl;\n";
+    cpp<<"\treturn decode(c,( Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+// Generate oer
+//
+void 
+cgcpph_sequenceof::generate_oer()
+{
+  std::string NameS = m_gencpp.get_module()->cpp_name();
+  std::string eltypeName;
+  std::string structName( NameS + "::" +m_seqof.identifier()->cpp_name());
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  asn1::node     *ns     = NULL;
+
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+  {
+    if (eltype->is_primitive())
+    {
+      eltypeName =  eltype->cpp_name();
+    } else
+      eltypeName = m_gencpp.get_module()->cpp_name() +"::" + eltype->cpp_name();
+  }
+
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t);\n";
+    /* Implementation */
+    cpp<<"// type sequence of "<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.put_char(\"[\",1);\n";
+    cpp<<"\tencode(c,( const Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"\tc.put_char(\"] \",2);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    //cpp<<"\tstd::cout<<\"codecOER::decode sequence of "<<structName<<" UW \"<<std::endl;\n";
+    cpp<<"\treturn decode(c,( Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+
+
+
+//
+void 
+cgcpph_sequenceof::generate_jer()
+{
+  std::string NameS = m_gencpp.get_module()->cpp_name();
+  std::string eltypeName;
+  std::string structName( NameS + "::" +m_seqof.identifier()->cpp_name());
+  asn1::typenode *eltype = m_seqof.get_eltype();
+  asn1::node     *ns     = NULL;
+
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+  {
+    if (eltype->is_primitive())
+    {
+      eltypeName =  eltype->cpp_name();
+    } else
+      eltypeName = m_gencpp.get_module()->cpp_name() +"::" + eltype->cpp_name();
+  }
+
+
+  if (m_gencpp.with_codec())
+  {
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+    /* Implementation */
+    cpp<<"// type sequence of "<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.put_char(\"[\",1);\n";
+    cpp<<"\tencode(c,( const Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"\tc.put_char(\"] \",2);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    //cpp<<"\tstd::cout<<\"codecJER::decode sequence of "<<structName<<" UW \"<<std::endl;\n";
+    cpp<<"\treturn decode(c,( Seq<"<<eltypeName<<"> &)_t);\n";
+    cpp<<"}\n";
+  }
+
+}
diff --git a/libgen/cpp/cgcpph_sequenceof.h b/libgen/cpp/cgcpph_sequenceof.h
new file mode 100644 (file)
index 0000000..bd68601
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef CODE_GEN_CPP_HELPER_SEQOF_H
+#define CODE_GEN_CPP_HELPER_SEQOF_H
+
+/**
+ * This class defines the interface that each 
+ */ 
+class cgcpph_sequenceof : public cgcpp_helper
+{
+  public:
+    cgcpph_sequenceof(cgcpph_sequenceof &s) : cgcpp_helper(s.m_gencpp,s.m_os) 
+                                            , m_seqof(s.m_seqof)
+       { } ;
+    cgcpph_sequenceof(generate_codec_cpp &g
+                , std::ostream &os
+                , asn1::sequence_of &s) ;
+
+    virtual ~cgcpph_sequenceof();
+    // generate entry point
+    virtual void generate()  ;
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber();
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() {};
+
+    // generate encoder
+    // generate decoder
+    // generate constructor
+    // generate 
+  protected:
+    void gen_ctors();
+    void gen_equal();
+    void gen_printf();
+  protected:
+    asn1::sequence_of     &m_seqof;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_set.cpp b/libgen/cpp/cgcpph_set.cpp
new file mode 100644 (file)
index 0000000..c2b617d
--- /dev/null
@@ -0,0 +1,254 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_construct.h"
+#include "cgcpph_set.h"
+
+//#undef GEN_LOG_DEBUG
+//#define GEN_LOG_DEBUG
+
+cgcpph_set::cgcpph_set(generate_codec_cpp &g,std::ostream &os,asn1::set &s)
+  :  cgh_construct(g,os,s)
+  , m_set(s) 
+{
+}
+
+cgcpph_set::~cgcpph_set()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgcpph_set::generate(const std::string &scope)
+{
+  asn1::node *n      = m_set.identifier();
+  asn1::node *params = NULL;
+  
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_set helper launched "<<m_set.identifier_name()<<std::endl;
+#if 0
+  if (n)
+  {
+    m_os<<n->name()<<std::endl;
+  } else
+  {
+    m_os<<std::endl;     
+  }
+#endif
+  //compute scope
+  // Does not work for know see CHOICE SET why path2module asserts
+  //m_gencpp.path2modulestring(type,scope);
+  GEN_LOG_DEBUG("cgcpph_set::generate node=%s\n",m_set.identifier_cpp_name().c_str());
+  // I should probably loop over all attributes as I do for sequence and choice
+  m_gencpp.gen_private(m_os,scope,&m_set);
+  
+  if (m_gencpp.with_codec())
+  {
+    gen_codec();
+  }
+  cgcpp_helper::generate();
+}
+
+/**
+ *
+ */ 
+void
+cgcpph_set::generate_descriptor()
+{
+  cgh_construct::gen_desc_seqset();
+}
+/**
+ *
+ */ 
+void
+cgcpph_set::generate_ctors()
+{
+    m_os<<m_structName<<"::"<<m_structName<<"(const asn1::tag &t)\n\t";
+    m_os<<" : asn1::types::sequence_type(t)\n{\n}"<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+cgcpph_set::generate_operators()
+{
+  cgh_construct::gen_equal();
+}
+
+//
+void cgcpph_set::generate_printf()
+{
+  std::string           scope("");
+  asn1::set            *type   = &m_set;
+  asn1::node           *ident  = m_set.identifier();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  
+  m_os<<"#if 1\n";
+  //m_os<<scope<<"\tfriend ";
+  m_os<<"std::ostream &operator <<(std::ostream &os,const ";
+  m_os<<m_structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<")\n{\n";
+  m_os<<"\tstd::streamsize indent = os.precision() + 2;"<<std::endl;
+  m_os<<"\tos<<std::setw(indent+5)<<\"SET (\\n\";\n";
+
+  for (asn1::node::iterator it = type->begin()
+                 ; it != type->end() 
+                 ; it++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL)
+    {
+        m_os<<"\tos<<\"\"<<";
+        m_gencpp.gen_composite_attribute_printf(m_os,scope,*f);
+    }
+  }
+  m_os<<"\tos<<std::setw(indent)<<std::setprecision(indent-2)<<\")\";\n"; 
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+  m_os<<"#endif\n";
+
+}
+
+// generate codec part
+void cgcpph_set::generate_per()
+{
+  std::string scope;
+  //
+}
+
+//
+void cgcpph_set::generate_ber()
+{
+  std::string scope;
+  bool priv = m_set.is_private();
+  //
+  // Start generating code for this function
+  gen_nencode(scope,priv);
+  gen_ndecode(scope,priv);
+  if (m_gencpp.with_codec())
+  {
+    std::string  ns ( m_gencpp.get_module()->cpp_name() ) ;
+    std::string  structName ( ns + "::" +m_set.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// sequence type "<<structName<<" priv="<<priv<<"\n";
+    hpp<<"template<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    /* Generate implementation */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_sequence_preamble(_t);\n";
+
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+        } else
+        {
+          if (f->flags().is_optional() && (! f->flags().is_default()))
+          {
+            cpp<<"\tif ( ! _t."<<f->cpp_name()<<".is_nul())\n\t{\n";
+            cpp<<"\t\tencode(c,_t."<<f->cpp_name()<<".get());\n\t}\n";
+          } else
+          {
+            cpp<<"\tencode(c,_t."<<f->cpp_name()<<");\n";
+          }
+       }
+      }
+   
+    } /* end for */
+    cpp<<"\tc.encode_sequence_epilogue(_t);\n";
+    cpp<<"}\n";
+    /* Implementation of decoding stream */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tif ( c.decode_sequence_preamble(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    /* loop over fields */
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+        } else
+        {
+          if (f->flags().is_optional() && (! f->flags().is_default()))
+          {
+            cpp<<"\tdecode(c,_t."<<f->cpp_name()<<".get());\n";
+          } else
+          {
+            cpp<<"\tdecode(c,_t."<<f->cpp_name()<<");\n";
+          }
+          //cpp<<"\t}\n";
+       }
+      }
+    }
+    cpp<<"\tif ( c.decode_sequence_epilogue(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+
+
+    /**/
+  }
+}
+
+//
+void cgcpph_set::generate_oer()
+{
+  //
+  if (m_gencpp.with_codec())
+  {
+    std::string  ns ( m_gencpp.get_module()->cpp_name() ) ;
+    std::string  structName ( ns + "::" +m_set.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+  }
+}
+
+//
+void cgcpph_set::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_set.h b/libgen/cpp/cgcpph_set.h
new file mode 100644 (file)
index 0000000..3c018ad
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef CGCPPH_SET_H
+#define CGCPPH_SET_H
+
+
+/**
+ *
+ */
+class cgcpph_set : public cgh_construct
+{
+  protected:
+    cgcpph_set(const  cgcpph_set &s) : 
+                                      cgh_construct(s.m_gencpp,s.m_os,s.m_set)
+                                      , m_set(s.m_set)
+    {}  
+  public:
+    cgcpph_set(generate_codec_cpp &g,std::ostream &os,asn1::set &s) ;
+   
+    ~cgcpph_set();
+    
+    // Helper functions
+    virtual void generate(const std::string &scope) ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    
+    virtual void generate_jer() { };
+    
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_descriptor() ;
+    virtual void generate_ctors() ;
+    virtual void generate_operators();
+    virtual void generate_printf();
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    asn1::set             &m_set;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_setof.cpp b/libgen/cpp/cgcpph_setof.cpp
new file mode 100644 (file)
index 0000000..adba791
--- /dev/null
@@ -0,0 +1,218 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_setof.h"
+
+
+cgcpph_setof::cgcpph_setof( generate_codec_cpp &g
+                          , std::ostream &os
+                          , asn1::set_of &s)
+  : cgcpp_helper(g,os) , m_setof(s) 
+{
+}
+
+cgcpph_setof::~cgcpph_setof()
+{
+}
+
+void cgcpph_setof::generate()
+{
+  std::string structName  = m_setof.identifier_cpp_name();
+  m_os<<"//cgcpph_setof::generate "<<structName<<std::endl;
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_setof helper launched \n";
+  
+  GEN_LOG_DEBUG("cgcpph_setof::generate node=%s\n",m_setof.identifier_cpp_name().c_str());
+
+  gen_ctors();
+  gen_equal();
+  gen_printf();
+  // Generate codec codec
+  cgcpp_helper::generate();
+}
+//
+void cgcpph_setof::gen_ctors()
+{
+  asn1::node     *ns     = NULL;
+  asn1::typenode *eltype = m_setof.get_eltype();
+  std::string structName = m_setof.identifier_cpp_name();
+  std::string eltypeName;
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+    eltypeName = eltype->cpp_name();
+  
+  // With tag
+  m_os<<"\n"<<structName;
+  m_os<<"::"<<structName<<"(const asn1::tag &t)\n";
+  m_os<<"\t\t: Set<"<<eltypeName<<">(t)\n{\n}\n";
+
+  m_os<<"\n"<<structName;
+  m_os<<"::"<<structName<<"(const "<<eltypeName<<" &t)\n";
+  m_os<<"\t\t: Set<"<<eltypeName<<">(t)\n\t";
+  m_os<<"{\n}\n";
+#if  0
+  m_os<<" asn1::types::container<"<<eltypeName<<">(asn1::tag(asn1::types::UNIVERSAL,17)\n";
+  m_os<<"{ this->m_.push_back(t);\n}\n";
+#endif
+  m_os<<"\n// Copy Constructor "<<structName<<"\n//\n";
+  m_os<<structName;
+  m_os<<"::"<<structName<<"(const "<<structName<<" &c)\n";
+  m_os<<"\t\t: Set<"<<eltypeName<<">(c)\n{\n}\n";
+  //clone
+  m_os<<structName<<" *";
+  m_os<<structName;
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+  m_os<<"\treturn new "<<structName<<"(*this);\n";
+  m_os<<"}\n";
+
+}
+//
+void cgcpph_setof::gen_equal()
+{
+  std::string structName = m_setof.identifier_cpp_name();
+  
+  // With tag
+  m_os<<"\n// comparaison "<<structName<<"\n//\n";
+  m_os<<"bool\n"<<structName;
+  m_os<<"::operator =="<<"(const "<<structName<<" &t)\n{\n";
+  m_os<<"\treturn false;\n";
+  //m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+//
+void cgcpph_setof::gen_printf()
+{
+  asn1::node     *ns     = NULL;
+  std::string structName = m_setof.identifier_cpp_name();
+  asn1::typenode *eltype = m_setof.get_eltype();
+  std::string eltypeName;
+  if (m_gencpp.type_in_imports(eltype,&ns) )
+  {
+    eltypeName = ns->cpp_name() + "::" + eltype->cpp_name();
+  } else
+    eltypeName = eltype->cpp_name();
+  
+  
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<structName<<" &s)\n{\n";
+  m_os<<"\toperator<<(os, (Set<"<<eltypeName<<"> &)s);\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+
+
+void 
+cgcpph_setof::generate_ber()
+{
+  asn1::node *type        = &m_setof;
+  std::string structName  = m_setof.identifier()->cpp_name();
+  //
+  if (m_setof.tagged())
+  {
+    if ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      //
+      m_os<<"\t void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tstd::cout<<\"encode "<<structName<<" TODO in generator\"<<std::endl;\n";
+      m_os<<"}\n;";
+      m_os<<"\t int  "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tstd::cout<<\"decode "<<structName<<" TODO in generator\"<<std::endl;\n";
+      m_os<<"\treturn asn1::ok;\n;";
+      m_os<<"}\n;";
+    }
+  }
+  // Generate code for codec way
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  (ns + "::" +m_setof.identifier()->cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    cpp<<"// type set of "<<std::endl;
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecBER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+void 
+cgcpph_setof::generate_oer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  (ns + "::" +m_setof.identifier()->cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    cpp<<"// type set of "<<std::endl;
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t);\n";
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecOER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecOER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+
+
+void 
+cgcpph_setof::generate_jer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns (m_gencpp.get_module()->cpp_name());
+    std::string structName  (ns + "::" +m_setof.identifier()->cpp_name());
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    cpp<<"// type set of "<<std::endl;
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+    // Implementation part
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecJER::encode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"codecJER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
diff --git a/libgen/cpp/cgcpph_setof.h b/libgen/cpp/cgcpph_setof.h
new file mode 100644 (file)
index 0000000..518eda1
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef CODE_GEN_CPP_HELPER_SETOF_H
+#define CODE_GEN_CPP_HELPER_SETOF_H
+
+/**
+ * This class defines the interface that each 
+ */ 
+class cgcpph_setof : public cgcpp_helper
+{
+  public:
+    cgcpph_setof(cgcpph_setof &s) : cgcpp_helper(s.m_gencpp,s.m_os) 
+                                            , m_setof(s.m_setof)
+       { } ;
+    cgcpph_setof(generate_codec_cpp &g
+                , std::ostream &os
+                , asn1::set_of &s) ;
+
+    virtual ~cgcpph_setof();
+    // generate entry point
+    virtual void generate()  ;
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() {};
+
+    // generate encoder
+    // generate decoder
+    // generate constructor
+    // generate 
+  protected:
+    void gen_ctors();
+    void gen_equal();
+    void gen_printf();
+  protected:
+    asn1::set_of          &m_setof;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_string.cpp b/libgen/cpp/cgcpph_string.cpp
new file mode 100644 (file)
index 0000000..8c7a8b2
--- /dev/null
@@ -0,0 +1,297 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_primitive.h"
+#include "cgcpph_string.h"
+
+
+cgcpph_string::cgcpph_string( generate_codec_cpp &g
+                           , std::ostream &os
+                           , asn1::primitive &s)
+  : cgcpph_primitive(g,os,s) , m_string(s)
+{
+}
+
+cgcpph_string::~cgcpph_string()
+{
+}
+
+
+
+/**
+ *
+ */
+void cgcpph_string::generate_operators()
+{
+  gen_equal();
+}
+/**
+ *
+ */
+void cgcpph_string::generate_ctors()
+{
+  asn1::node *type       = &m_string;
+  
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_string helper launched ";
+  
+  GEN_LOG_DEBUG("cgcpph_string::generate node=%s\n",m_string.identifier_cpp_name().c_str());
+  
+  // With tag
+  m_os<<"\n"<<m_structName;
+  m_os<<"::"<<m_structName<<"(const asn1::tag &t)\n";
+  m_os<<"\t\t: "<<m_string.cpp_name()<<"(t)\n{\n}\n";
+  // Two other ctors
+  m_os<<m_structName<<"::"<<m_structName<<"(const std::string &s)\n";
+  m_os<<"\t\t: "<<m_string.cpp_name()<<"(s)\n{\n}\n";
+  
+  //m_os<<structName<<"::"<<structName<<"(const char *s)\n";
+  //m_os<<"\t\t: "<<type->cpp_name()<<"(t)\n{\n}\n";
+  //
+  m_os<<"\n// Copy Constructor "<<m_structName<<"\n//\n";
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_structName<<" &c)\n";
+  m_os<<"\t\t: "<<m_string.cpp_name()<<"(c)\n{\n}\n";
+  // Copy 
+  m_os<<"\n// Copy Constructor from "<<m_string.cpp_name()<<"\n//\n";
+  m_os<<m_structName;
+  m_os<<"::"<<m_structName<<"(const "<<m_string.cpp_name()<<" &c";
+  m_os<<",const asn1::tag &t)\n";
+  m_os<<"\t\t: "<<m_string.cpp_name()<<"(t)\n{\n";
+  m_os<<"\t"<<m_string.cpp_name()<<"::operator =(c);\n";
+  m_os<<"}\n\n";
+  // copy assignment
+  //
+  m_os<<m_structName<<" & ";
+  m_os<<m_structName;
+  m_os<<"::operator =(const "<<m_string.cpp_name()<<" &c)\n";
+  m_os<<"{\n";
+  m_os<<"\t"<<m_string.cpp_name()<<"::operator =(c)\n;";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+  m_os<<m_structName<<" & ";
+  m_os<<m_structName;
+  m_os<<"::operator =(const std::string &c)\n";
+  m_os<<"{\n";
+  m_os<<"\tm_Prim = c;\n;";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+  m_os<<m_structName<<" & ";
+  m_os<<m_structName;
+  m_os<<"::operator =(const char *c)\n";
+  m_os<<"{\n";
+  m_os<<"\tm_Prim = std::string(c);\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+  // clone
+  m_os<<m_structName<<" * ";
+  m_os<<m_structName;
+  m_os<<"::clone()\n";
+  m_os<<"{\n";
+  m_os<<"\treturn new "<<m_structName<<"(*this)\n;";
+  m_os<<"}\n";
+}
+
+
+//
+void cgcpph_string::gen_equal()
+{
+  // With tag
+  m_os<<"\n// comparaison "<<m_structName<<"\n//\n";
+  m_os<<"bool\n"<<m_structName;
+  m_os<<"::operator =="<<"( "<<m_structName<<" &t)\n{\n";
+  m_os<<"\treturn get_value() == t.get_value();\n";
+  m_os<<"}\n";
+}
+
+
+//
+void cgcpph_string::generate_printf()
+{
+  m_os<<"\nstd::ostream & operator <<(std::ostream &os,const ";
+  m_os<<m_structName<<" &s)\n{\n";
+  m_os<<"\tos<<("<<m_string.cpp_name()<<")s;\n";
+  m_os<<"\treturn os;\n";
+  m_os<<"}\n";
+}
+
+// generate codec part
+void cgcpph_string::generate_per()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    // hpp content
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// string type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t);\n";
+    // cpp content
+    cpp<<"// string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_string(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_string(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_string::generate_ber()
+{
+  std::string scope;
+  std::string structName = m_string.identifier_cpp_name();
+  //
+  if (m_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_string))
+    {
+      m_os<<scope<<"void "<<structName<<"::encode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::encode(ctx) tag=%d \",this->tag().byte());\n";
+      m_os<<"\tb[pos++] = tag().byte();\n";
+      m_os<<"\tctx.nb_bits(16);\n";
+      m_os<<"\tasn1::tag t("<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true);\n";
+      m_os<<"\tset_tag(asn1::tag(0,"<<m_string.primitive_tag()<<"));\n";
+      m_os<<"\tctx.encode_string(*this);\n";
+      m_os<<"\tset_tag(t);\n";
+      m_os<<"\tb[pos] = ctx.bytes() -pos -1;\n";
+      m_os<<"}\n\n";
+      m_os<<scope<<"int "<<structName<<"::decode(asn1::context &ctx)\n{\n"<<std::endl;
+      m_os<<"\tasn1::tag t("<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true);\n";
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<structName<<"::decode(ctx) exp tag= %d tag=%d \",t.byte(),this->tag().byte());\n";
+      m_os<<"\tif (ctx.decode_tag(t))\n\t{\n";
+      m_os<<"\t\t"<<m_string.cpp_name()<<" tmp;\n";
+      m_os<<"\t\tint rest = tmp.decode(ctx);\n";
+      m_os<<"\t\tthis->get_value() = tmp;\n";
+      m_os<<"\t\treturn rest;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    }
+  }
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    // hpp content
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// string type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+    // cpp content
+    cpp<<"// string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    if ( m_string.tagged() 
+         && (m_gencpp.is_tag_explicit(m_string) )
+       )
+    {
+      cpp<<"\tasn1::tag t("<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true);\n";
+      cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    }
+    cpp<<"\tc.encode_string(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    if ( m_string.tagged() 
+         && (m_gencpp.is_tag_explicit(m_string) )
+       )
+    {
+      cpp<<"\tasn1::tag t("<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true);\n";
+      cpp<<"\tstd::cout<<\"codecBER::decode "<<structName<<" TODO\"<<std::endl;\n";
+    }
+    cpp<<"\treturn c.decode_string(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_string::generate_oer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    // hpp content
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// string type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t);\n";
+    // cpp content
+    cpp<<"// string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_string(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_string(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_string::generate_jer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName ( ns + "::" + m_string.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    // hpp content
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// string type "<<structName<<""<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void asn1::codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+    // cpp content
+    cpp<<"// string generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_string(_t);\n";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\treturn c.decode_string(_t);\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_string::generate_xer()
+{
+}
diff --git a/libgen/cpp/cgcpph_string.h b/libgen/cpp/cgcpph_string.h
new file mode 100644 (file)
index 0000000..329f9af
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef CGCPPH_STRING_H
+#define CGCPPH_STRING_H
+
+
+/**
+ *
+ */
+class cgcpph_string : public cgcpph_primitive 
+{
+  protected:
+    cgcpph_string(const  cgcpph_string &s) : cgcpph_primitive(s.m_gencpp,s.m_os,s.m_string)
+                                      , m_string(s.m_string)
+    {}  
+  public:
+    cgcpph_string(generate_codec_cpp &g
+                , std::ostream &os
+                , asn1::primitive &s) ;
+   
+    ~cgcpph_string();
+    
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_printf();
+    virtual void generate_operators();
+    virtual void generate_ctors();
+    void gen_equal();
+  protected:
+    asn1::primitive       &m_string;
+};
+
+#endif
diff --git a/libgen/cpp/cgcpph_typeref.cpp b/libgen/cpp/cgcpph_typeref.cpp
new file mode 100644 (file)
index 0000000..000771e
--- /dev/null
@@ -0,0 +1,443 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgcpph_typeref.h"
+
+
+/**
+ *
+ *
+ */ 
+cgcpph_typeref::cgcpph_typeref(generate_codec_cpp &g,std::ostream &os,asn1::typeref &s)
+  : cgcpp_helper(g,os)
+    , m_typeref(s)
+    //, m_log(g.logger())
+{
+}
+
+/**
+ *
+ *
+ */ 
+cgcpph_typeref::~cgcpph_typeref()
+{
+}
+
+
+/** Helper functions
+ *
+ */ 
+void cgcpph_typeref::generate(const std::string &scope)
+{
+  asn1::node *n      = m_typeref.identifier();
+  asn1::node *type   = &m_typeref;
+
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cgcpph_typeref helper launched "<<n->name()<<std::endl;
+  
+  if (m_typeref.is_simple())
+  {
+    cgcpp_helper::generate();
+  } else if (m_typeref.is_objectclass())
+  {
+    generate_objectclass();  
+  } else 
+  {
+    assert(0);  
+  }
+}
+
+struct TyperefPrintTag {
+  TyperefPrintTag(generate_codec_cpp &_g,std::ostream &os,unsigned int &c)
+         : m_gencpp(_g), m_os(os), m_count(c) {}
+  void operator ()(asn1::node *_node)
+  {
+    m_os<<"\t";
+    if (m_count++)
+      m_os<<", ";
+    m_os<<"asn1::tag("<<_node->tag().m_class<<","<<_node->tag().m_value;
+    if (m_gencpp.is_tag_explicit(*_node->as_typenode()))
+           m_os<<",true";
+    m_os<<")\n";
+  }
+  std::ostream &m_os;
+  unsigned int &m_count;
+  generate_codec_cpp &m_gencpp;
+};
+
+void
+cgcpph_typeref::generate_descriptor()
+{
+  std::string cn(m_typeref.identifier_cpp_name());
+  unsigned int _count = 0;
+  std::list<asn1::node *> refs;
+  TyperefPrintTag pt(m_gencpp,m_os,_count); 
+  m_gencpp.reference_chaine(&m_typeref,refs);
+  m_os<<"static asn1::tag TAGS_"<<m_typeref.identifier_cpp_name()<<"[] = {\n";
+  std::for_each(refs.rbegin(),refs.rend(),pt);
+  if (m_typeref.tagged())
+  {
+    if (_count)
+      m_os<<"\t, ";
+    m_os<<"asn1::tag("<<m_typeref.tag().m_class<<","<<m_typeref.tag().m_value;
+    if (m_gencpp.is_tag_explicit(m_typeref))
+           m_os<<",true";
+    m_os<<")\n";
+
+  }
+  m_os<<"};\n";
+
+  m_os<<"const asn1::types::descriptor "<<m_typeref.identifier_cpp_name()<<"::_meta = {\n";
+  m_os<<"  TAGS_"<<cn<<",";
+  m_os<<"sizeof(TAGS_"<<cn<<")/sizeof(TAGS_"<<cn<<"[0]),\n"; /* Tag List */
+  m_os<<"  NULL,\n"; /* MEMBER List       */
+  m_os<<"  0,\n";    /* Member list count */
+  m_os<<"  NULL,\n"; /*tag to element */
+  m_os<<"  0\n"; /* tag to element count*/
+  m_os<<"};\n";
+  m_os<<std::endl;
+}
+
+/**
+ *
+ */
+void
+cgcpph_typeref::generate_ctors()
+{
+  gen_simple_ctors();
+}
+/**
+ *
+ */
+void
+cgcpph_typeref::generate_operators()
+{
+  gen_simple_equal();
+}
+
+//
+void
+cgcpph_typeref::gen_simple_equal()
+{
+  std::string refName;   
+  asn1::node  *ns     = NULL;
+  asn1::node  *n      = m_typeref.identifier();
+  asn1::typeref  *type   = &m_typeref;
+  std::string structName =n->cpp_name();
+  
+  
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();     
+  } else
+  {
+    refName   = type->cpp_name();     
+  }
+  
+  m_os<<"bool "<<structName<<"::operator==(";
+  m_os<<structName<<" &o)\n{\n";
+  m_os<<"\tstd::cerr<<\""<<structName<<"::operator== TOBE CODED\\n\";\n";
+  m_os<<"\treturn false;\n";
+  //m_os<<"\treturn this->get_value() == o.get_value();\n";
+  m_os<<"}\n";
+}
+
+//
+void
+cgcpph_typeref::gen_simple_ctors()
+{
+  std::string refName;   
+  std::list<asn1::node *> refs;
+  asn1::node  *ns     = NULL;
+  asn1::node  *n      = m_typeref.identifier();
+  asn1::typeref  *type   = &m_typeref;
+  std::string structName = n->cpp_name();
+  
+  m_gencpp.reference_chaine(type,refs);
+  
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();     
+  } else
+  {
+    refName   = type->cpp_name();     
+  }
+  
+  // Basic ctor
+  m_os<<structName<<"::"<<structName;
+  m_os<<"(const asn1::tag &_t)";
+  if ( type->tagged() 
+       && (type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT))
+   {
+      m_os<<"\t:  "<<refName<<"(_t)\n{\n" ;
+   } else
+      m_os<<"\t:  "<<refName<<"(_t)\n{\n" ;
+  m_os<<"\n}\n";
+  if (!type->tagged())
+  {
+    m_os<<structName<<"::"<<structName;
+    m_os<<"( )";
+    m_os<<"\t:  "<<refName<<"()\n{\n" ;
+    m_os<<"\n}\n";
+  } 
+  // Copy ctor
+  m_os<<structName<<"::"<<structName;
+  m_os<<"(const "<<structName<<" &_t)";
+  m_os<<"\t:  "<<refName<<"(_t)\n{\n" ;
+  m_os<<"\n}\n";
+  // Check Type of Initial type
+#if 1
+  if ( refs.size()>0 && 
+       refs.back()->type_id()() == asn1::type::ASN1_CHOICE)
+  {
+    m_os<<structName<<"::"<<structName<<"(unsigned int i, const asn1::tag &_t) "<<std::endl;
+    m_os<<"\t:  "<<refName<<"(i,_t)\n{\n" ;
+    m_os<<"\n}\n";
+  }
+#endif
+  
+  // Add an operator
+  m_os<<"//\n// Operator\n"<<structName<<" &\n";
+  m_os<<""<<structName<<"::operator =(const "<<refName<<" &_v)\n";
+  m_os<<"{\n";
+  m_os<<"\tthis->get_value() = _v.get_value();\n";
+  m_os<<"\treturn *this;\n";
+  m_os<<"}\n";
+
+}
+
+
+// This method will be used to deal with
+// TYPE-IDENTIFIER and OBJECT CLASS 
+void
+cgcpph_typeref::generate_objectclass()
+{
+  asn1::node  *n      = m_typeref.identifier();
+  m_os<<"// cgcpph_typeref::generate_objectclass helper launched "<<n->name();
+  if (n->parameters())
+  {
+    m_os<<" SHOULD ONLY GENERATE WITH ACTUAL_PARAMETERS ";  
+  }
+  if (m_typeref.act_parameters())
+  {
+    m_os<<" "<<m_typeref.name()<<" has actual parameters ";  
+  }
+  m_os<<std::endl;
+  ;
+}
+
+//
+void cgcpph_typeref::gen_printf(const std::string &scope)
+{
+}
+
+// generate codec part
+void cgcpph_typeref::generate_per()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName( ns + "::" + m_typeref.identifier_cpp_name() );
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecPER::encode(streams::per &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecPER::decode(streams::per &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecPER::encode(asn1::streams::per &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"encode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecPER::decode(asn1::streams::per &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"decode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+/**
+ *
+ *
+ */ 
+void cgcpph_typeref::generate_ber()
+{
+  std::string scope;
+  std::string refName;
+  asn1::node *ns         = NULL;
+  std::list<asn1::node *> refs;
+  asn1::node *ident      = m_typeref.identifier(); 
+  asn1::typeref *type    = &m_typeref;
+  std::string structName = ident->cpp_name();
+  
+  m_gencpp.reference_chaine(type,refs);
+  
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();     
+  } else
+  {
+    refName   = type->cpp_name();     
+  }
+  
+  //
+  if (m_typeref.tagged())
+  {
+    if ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      asn1::node *refnode = refs.front(); 
+      // encoder
+      m_os<<"void\n"<<scope<<structName<<"::encode(asn1::context &ctx)\n{"<<std::endl;
+      m_os<<"\tunsigned long pos = ctx.bytes();\n";
+      m_os<<"\tunsigned char *b = ctx.buffer();\n";
+      m_os<<"\tasn1::tag tg(tag());\n";
+      m_os<<"\ttg.set_constructed();\n";
+      m_os<<"\tb[pos] = tg.byte();\n";
+      m_os<<"\tctx.nb_bits(+ (2<<3) );"; 
+      m_os<<"\tset_tag(asn1::tag("<<refnode->tag().m_class<<","<<refnode->tag().m_value<<"));\n";
+      m_os<<"\tthis->"<<refName<<"::encode(ctx);\n";
+      m_os<<"\tint len = ctx.bytes() - pos - 2;\n";
+      m_os<<"\tassert( len < 127); // Restriction.\n";
+      m_os<<"\tb[++pos] = len ;\n";
+      m_os<<"}\n";
+      // decoder
+      m_os<<"\nint\n"<<scope<<structName<<"::decode(asn1::context &ctx)\n{"<<std::endl;
+      m_os<<"\tint len;\n";
+      m_os<<"\tasn1::tag tg(tag());\n";
+      m_os<<"\ttg.set_constructed();\n";
+      m_os<<"\tif (ctx.decode_tag(tg))\n\t{\n";
+      // Set tag to ref tag
+      m_os<<"\t\tset_tag(asn1::tag("<<refnode->tag().m_class<<","<<refnode->tag().m_value<<"));\n";
+      m_os<<"\t\tthis->"<<refName<<"::decode(ctx);\n";
+      m_os<<"\t\treturn asn1::ok;\n";
+      m_os<<"\t}\n";
+      m_os<<"\treturn asn1::wrong_tag;\n";
+      m_os<<"}\n";
+    } else 
+    {
+      // IMPLICIT Case
+      // encoder
+      m_os<<"void\n"<<scope<<structName<<"::encode(asn1::context &ctx)\n{"<<std::endl;
+      m_os<<"\tthis->"<<refName<<"::encode(ctx);\n";
+      m_os<<"}\n";
+      // decoder
+      m_os<<"\nint\n"<<scope<<structName<<"::decode(asn1::context &ctx)\n{"<<std::endl;
+      m_os<<"\treturn this->"<<refName<<"::decode(ctx);\n";
+      m_os<<"}\n";
+    }
+  }
+  //m_gencpp.gen_template_signature(m_os,type);
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName( ns + "::" + m_typeref.identifier_cpp_name() );
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecBER::encode(streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecBER::decode(streams::ber &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"encode typeref "<<structName<<"\"<<std::endl;\n";
+    if ( m_typeref.tagged() 
+         && ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+       )
+    {
+      cpp<<"\tstd::cout<<\"encode typeref explicit tag "<<refName<<"\"<<std::endl;\n";
+    }
+    //cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"decode typeref "<<structName<<"\"<<std::endl;\n";
+    if ( m_typeref.tagged() 
+         && ( m_gencpp.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+       )
+    {
+      cpp<<"\tstd::cout<<\"decode typeref explicit tag "<<refName<<"\"<<std::endl;\n";
+    }
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_typeref::generate_oer()
+{
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName( ns + "::" + m_typeref.identifier_cpp_name() );
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecOER::encode(streams::oer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecOER::decode(streams::oer &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecOER::encode(asn1::streams::oer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"encode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecOER::decode(asn1::streams::oer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"decode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_typeref::generate_jer()
+{
+  //m_gencpp.gen_template_signature(m_os,type);
+  if (m_gencpp.with_codec())
+  {
+    std::string ns( m_gencpp.get_module()->cpp_name() );
+    std::string structName( ns + "::" + m_typeref.identifier_cpp_name() );
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+
+    cpp<<"// typeref generator todo"<<std::endl;
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"encode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\tc.encode_octetstring(_t);";
+    cpp<<"}\n";
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tstd::cout<<\"decode typeref "<<structName<<"\"<<std::endl;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+
+}
+
+//
+void cgcpph_typeref::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cgcpph_typeref.h b/libgen/cpp/cgcpph_typeref.h
new file mode 100644 (file)
index 0000000..96d0f9d
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef CGCPPH_TYPEREF_H
+#define CGCPPH_TYPEREF_H
+
+
+/**
+ *
+ */
+class cgcpph_typeref : public cgcpp_helper
+{
+  protected:
+    cgcpph_typeref(const  cgcpph_typeref &s) :  cgcpp_helper(s.m_gencpp,s.m_os)
+                                     , m_typeref(s.m_typeref) {}  
+  public:
+    cgcpph_typeref(generate_codec_cpp &g,std::ostream &os,asn1::typeref &s) ;
+    ~cgcpph_typeref();
+    
+    // Helper functions
+    virtual void generate(const std::string &scope) ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    //
+    virtual void generate_descriptor() ;
+    virtual void generate_ctors() ;
+    virtual void generate_operators() ;
+  protected:
+    void gen_simple_ctors() ;
+    void gen_simple_equal() ;
+    void generate_external_type() {} ;
+    void generate_external_value() {} ;
+    // This method will be used to deal with
+    // TYPE-IDENTIFIER and OBJECT CLASS 
+    void generate_objectclass() ;
+    void gen_objectclass_ctors() {} ;
+  protected:  
+    asn1::typeref         &m_typeref;
+};
+
+#endif
diff --git a/libgen/cpp/cgh_construct.cpp b/libgen/cpp/cgh_construct.cpp
new file mode 100644 (file)
index 0000000..22e07c9
--- /dev/null
@@ -0,0 +1,1097 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgh_construct.h"
+#include "asn1_recursive_visitor.h"
+
+
+cgh_construct::cgh_construct( generate_codec_cpp &g
+                      , std::ostream &os
+                      , asn1::constructed &cdef)
+  : cgcpp_helper(g,os) ,m_c(cdef)
+  , m_elcount(0)
+  , m_t2elcount(0)
+{
+  m_gencpp.struct_name(&m_c,m_structName);
+}
+
+cgh_construct::~cgh_construct()
+{
+}
+
+/**
+ * I'm not yet convinced about what to put in here.
+ * below construct, there are simple types like
+ * integer, enumerated, oid, bit_string
+ * and real constructed type like
+ * choice, set, sequence
+ *
+ * Let's use the implementation below for the simple types.
+ */
+void 
+cgh_construct::generate_descriptor()
+{
+
+  std::string cn(m_c.identifier_cpp_name());
+  unsigned int _count = 0;
+  m_os<<"static asn1::tag TAGS_"<<m_c.identifier_cpp_name()<<"[] = {\n";
+  if (m_c.tagged())
+  {
+    m_os<<"asn1::tag("<<m_c.tag().m_class<<","<<m_c.tag().m_value;
+    if (m_gencpp.is_tag_explicit(m_c))
+      m_os<<",true";
+    m_os<<")\n";
+  } else {
+    m_os<<"asn1::tag("<<m_c.tag().m_class<<","<<m_c.tag().m_value;
+    m_os<<")\n";
+  }
+  m_os<<"};\n";
+
+/**/
+
+  m_os<<"const asn1::types::descriptor "<<m_structName<<"::_meta = {\n";
+  if (m_c.tagged())
+  {
+  }
+  m_os<<"  TAGS_"<<cn<<",";
+  m_os<<"sizeof(TAGS_"<<cn<<")/sizeof(TAGS_"<<cn<<"[0]),\n"; /* Tag List */
+  m_os<<"  NULL,\n"; /* MEMBER List       */
+  m_os<<"  0,\n";    /* Member list count */
+  m_os<<"  NULL,\n"; /*tag to element */
+  m_os<<"  0\n"; /* tag to element count*/
+  m_os<<"};\n";
+  m_os<<std::endl;
+}
+
+void
+cgh_construct::gen_desc_seqset()
+{
+  std::string cn(m_c.identifier_cpp_name());
+  unsigned int _count = 0;
+  
+  gen_member_table();
+  m_os<<"static asn1::tag TAGS_"<<m_c.identifier_cpp_name()<<"[] = {\n";
+  if (m_c.tagged())
+  {
+    m_os<<"asn1::tag("<<m_c.tag().m_class<<","<<m_c.tag().m_value;
+    if (m_gencpp.is_tag_explicit(m_c))
+      m_os<<",true";
+    m_os<<")\n";
+  } else {
+    m_os<<"asn1::tag("<<m_c.tag().m_class<<","<<m_c.tag().m_value;
+    m_os<<")\n";
+  }
+  m_os<<"};\n";
+
+/**/
+
+  m_os<<"const asn1::types::descriptor "<<m_structName<<"::_meta = {\n";
+  if (m_c.tagged())
+  {
+  }
+  m_os<<"  TAGS_"<<cn<<",";
+  m_os<<"sizeof(TAGS_"<<cn<<")/sizeof(TAGS_"<<cn<<"[0]),\n"; /* Tag List */
+  m_os<<"  MEMBER_"<<m_structName<<",\n"; /* MEMBER List       */
+  m_os<<"  sizeof(MEMBER_"<<m_structName<<")/sizeof(MEMBER_"<<m_structName<<"[0]),\n";    /* Member list count */
+  m_os<<"  NULL,\n"; /*tag to element */
+  m_os<<"  0\n"; /* tag to element count*/
+  m_os<<"};\n";
+  m_os<<std::endl;
+}
+
+void
+cgh_construct::gen_equal()
+{
+  std::string          lscope;
+  asn1::node          *type = &m_c;
+  asn1::node::iterator lit  = m_c.begin();
+  //
+
+  // let s start
+  m_gencpp.gen_template_signature(m_os,&m_c);
+  
+  lscope =  m_structName;
+  m_os<<"bool "<<m_structName;
+  m_gencpp.gen_template_signature_class(m_os,&m_c);
+  m_os<<"::"<<"operator ==";
+  m_os<<"("<<m_structName;
+  m_gencpp.gen_template_signature_class(m_os,&m_c);
+  m_os<<" &o) \n{\n";
+  m_os<<"\tstd::cerr<<\""<<m_structName<<"::operator == NEEDS TO BE CODED\\n\";\n"; 
+  m_os<<"\treturn false;\n"; 
+  m_os<<"}\n";
+  /**/
+}
+
+void
+cgh_construct::gen_data_length()
+{
+  int _count = 0;
+
+  m_gencpp.gen_template_signature(m_os,&m_c);
+  m_os<<"size_t "<<m_structName;
+  m_gencpp.gen_template_signature_class(m_os,&m_c);
+  m_os<<"::get_data_length() const\n{\n";
+  m_os<<"\treturn ";
+  for ( asn1::node::iterator it = m_c.begin()
+      ; it != m_c.end()
+      ; ++it )
+  {
+    asn1::field     *f    = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode  *type = f->get_type();
+    if (!type)
+    {
+      continue;
+    }
+    if (it != m_c.begin() )
+      m_os<<"\t\t+ ";
+    m_os<<""<<f->cpp_name()<<".get_length()\n";
+    _count++;
+  }
+  if (! _count)
+  {
+    m_os<<"0 ;\n";
+  }else
+    m_os<<"\t;\n";
+  m_os<<"};\n";
+}
+    
+struct ConstructPrintTag
+{
+  ConstructPrintTag(generate_codec_cpp &_g,std::ostream &os,unsigned int &c)
+  : m_gencpp(_g), m_os(os), m_count(c) {}
+  void operator ()(asn1::node *_node)
+  {
+    if (asn1::typenode *tn = _node->as_typenode())
+    {
+      m_os<<"\t";
+        if (m_count++)
+      m_os<<", ";
+      m_os<<"asn1::tag("<<_node->tag().m_class<<","<<_node->tag().m_value;
+      if (m_gencpp.is_tag_explicit(*_node->as_typenode()))
+        m_os<<",true";
+      m_os<<")\n";
+     }
+  }
+  std::ostream &m_os;
+  unsigned int &m_count;
+  generate_codec_cpp &m_gencpp;
+};
+
+/**
+ *
+ */
+void 
+cgh_construct::gen_member_tags(std::ostream &_os_tags,asn1::field &_f,asn1::typenode &_type)
+{
+  std::string cls(m_c.identifier()->cpp_name());
+  unsigned int _count = 0;
+  ConstructPrintTag pt(m_gencpp,_os_tags,_count); 
+
+  _os_tags<<"static asn1::tag MTAGS_"<<cls<<"_"<<_f.cpp_name()<<"[] = {\n";
+  if (_type.tagged())
+  {
+    _os_tags<<"asn1::tag("<<_type.tag().m_class<<","<<_type.tag().m_value;
+    if (m_gencpp.is_tag_explicit(_type))
+      _os_tags<<",true";
+    _os_tags<<")\n";
+  } else {
+    if (asn1::typeref *tref = _type.as_typeref())
+    {
+      asn1::node::tag_type tg = tref->otag(m_gencpp.resolver());
+      std::list<asn1::node *> refs;
+      _os_tags<<"// Is private "<<_f.cpp_name()<<"\n";
+      m_gencpp.reference_chaine(tref,refs);
+      std::for_each(refs.rbegin(),refs.rend(),pt);
+    } else
+    {
+      _os_tags<<"asn1::tag("<<_type.tag().m_class<<","<<_type.tag().m_value;
+      _os_tags<<")\n";
+    }
+  }
+  _os_tags<<"};\n";
+}
+/**
+ *
+ */
+void
+cgh_construct::gen_member_desc(std::ostream &_os_desc,asn1::field &_f,asn1::typenode &_type)
+{
+  std::string cls(m_c.identifier()->cpp_name());
+  std::string cn("MTAGS_"+cls+"_"+_f.cpp_name());
+
+  _os_desc<<"static asn1::types::descriptor DESC_"<<cls<<"_"<<_f.cpp_name()<<" = {\n";
+  _os_desc<<"  "<<cn<<",\n";
+  _os_desc<<"  sizeof("<<cn<<")/sizeof("<<cn<<"[0]),\n"; /* Tag List */
+  _os_desc<<"  NULL,\n"; /* MEMBER List       */
+  _os_desc<<"  0,\n";    /* Member list count */
+  _os_desc<<"  NULL,\n"; /*tag to element */
+  _os_desc<<"  0\n"; /* tag to element count*/
+  _os_desc<<"};\n";
+}
+
+void 
+cgh_construct::gen_member_table()
+{
+  size_t _count = 0;
+  bool   is_choice = (m_c.as_choice() == NULL)?false:true;
+  std::string cls(m_c.identifier()->cpp_name());
+  std::ostringstream _os("");
+  std::ostringstream _os_tags("");
+  std::ostringstream _os_desc("");
+  _os<<"static asn1::types::member_desc MEMBER_"<<cls<<"[] = {\n";
+
+  for ( asn1::node::iterator it = m_c.begin()
+      ; it != m_c.end()
+      ; ++it , _count++)
+  {
+    asn1::field     *f    = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode  *type = f->get_type();
+    if (!type)
+    {
+      _os<<"  /*...*/\n";
+      continue;
+    }
+    std::ostringstream mos("");
+    gen_member_tags(_os_tags,*f,*type);
+    gen_member_desc(_os_desc,*f,*type);
+    std::string desc("DESC_"+cls+"_"+f->cpp_name());
+    //mos<<"MEMBER_OFFSET("<<cls<<",m_choice)";
+    // No member offset for choice type
+    mos<<"0";
+    std::string tf("asn1::types::TF_POINTER");
+    // try to set appropriate tag
+    if (!is_choice)
+    {
+        if (f->flags().is_optional())
+          tf="asn1::types::TF_SHARED_POINTER";
+        else
+          tf="asn1::types::TF_NONE";
+    }
+    m_elcount++;
+    if ( type
+        && type->tagged()
+       )
+    {
+      std::string _mode = (m_gencpp.is_tag_explicit(*type))?" 1":"-1";
+      _os<<"  { "<<tf<<",\n    ";
+      _os<<_mode<<" , ("<<type->tag().m_value<<"<<2) | ";
+      _os<<type->tag().m_class<<" ,\n    "<<mos.str()<<","<<_count;
+      _os<<",\n    &"<<desc<<",\n    \""<<f->name()<<"\"}, /* "<<f->name()<<" */\n";
+    } else
+    {
+      if (asn1::typeref *ref = type->as_typeref())
+      {
+        asn1::node::tag_type tg = ref->otag(m_gencpp.resolver());
+        if ( ref->get_canonical_typenode() 
+             && dynamic_cast<asn1::choice *>(ref->get_canonical_typenode()))
+        {
+          _os<<"  { "<<tf<<",0 ,\n    -1        "<<" ,";
+          _os<<mos.str()<<","<<_count<<",\n    ";
+          _os<<"&"<<desc<<",\n    \""<<f->name()<<"\"}, /* Choice ...*/\n";
+        } else if (ref->is_complex() && (tg.m_value == -1))
+        {
+          tf = "asn1::types::TF_OPEN_TYPE";
+          _os<<"  { "<<tf<<",\n    0 , -1"<<",\n    ";
+          _os<<mos.str()<<","<<_count<<",\n    ";
+          _os<<"&"<<desc<<",\n    \""<<f->name()<<"\"}, /* Cplx ...*/\n";
+        } else 
+        {
+          _os<<"  { "<<tf<<",\n";
+          _os<<"    -1 , ("<<tg.m_value<<"<<2) | "<<tg.m_class<<" ,\n";
+          _os<<"    "<<mos.str()<<","<<_count<<",\n";
+          _os<<"    &"<<desc<<",\n    \""<<f->name()<<"\"},";
+          _os<<" /* cano:"<<ref->get_canonical_typenode()->name()<<"*/\n";
+        }
+      } else
+      {
+        if (f->flags().is_optional())
+          tf="asn1::types::TF_SHARED_POINTER";
+        else
+          tf="asn1::types::TF_NONE";
+#if 0
+        // 2017/07/26 Generated too many compiler warning
+        if (! is_choice)
+        {
+          mos.str("");
+          mos<<"MEMBER_OFFSET("<<cls<<","<<f->cpp_name()<<")";
+        }
+#endif
+        _os<<"  { "<<tf<<",-1 , 0 ,"<<mos.str()<<","<<_count<<",NULL,\""<<f->name()<<"\"},\n";
+      }
+    }
+
+  }
+  _os<<"};\n";
+  m_os<<_os_tags.str()<<std::endl;
+  m_os<<_os_desc.str()<<std::endl;
+  m_os<<_os.str()<<std::endl;
+}
+
+
+class tag2glv : public asn1::recursive_visitor<tag2glv>
+{
+  protected:
+    std::fstream         &m_log;
+    generate_cpp         &m_gencpp;
+    asn1::constructed    &m_c;
+    std::ostream         &m_os;
+    std::string           m_current_choice;
+    int &m_t2elcount;
+    int m_elcount;
+  public:
+
+    tag2glv( generate_cpp &g
+                      , std::ostream &os
+                      , asn1::constructed &cdef
+                      , int &_t2elc)
+      : m_gencpp(g), m_os(os) ,m_c(cdef)
+      , m_log(g.logger())
+      , m_t2elcount(_t2elc)
+      , m_elcount(0)
+    {
+    }
+
+  bool visit_alternative_choice(asn1::field *f)
+  {
+    asn1::typenode *type = f->get_type();
+    if (f->get_parent()->name() == m_c.name())
+    {
+      m_current_choice = f->cpp_name();
+      m_elcount++;
+    }
+    if (f->is_extensible())
+      return false;
+    if (type && type->tagged())
+    {
+      asn1::node::tag_type tg = type->tag();
+      print_entry(tg,f);
+      m_t2elcount++;
+      return false;
+    } else if (asn1::typeref *r = type->as_typeref()) 
+    {
+      if (asn1::node *rt = r->get_real_type())
+      {
+        if (r->is_complex())
+        {
+          traverse_type(rt);
+          return false;
+        }
+        if (asn1::choice *c = dynamic_cast<asn1::choice *>(rt))
+        {
+          traverse_type(rt);
+          return false;
+        }
+        if (asn1::typeref *oref = rt->as_typeref())
+        {
+          asn1::node::tag_type tg = oref->otag(m_gencpp.resolver());
+          print_entry(tg,f);
+          m_t2elcount++;
+          return false;
+        }
+        asn1::node::tag_type tg = rt->tag();
+        assert( (tg.m_value != -1) && "Tag must be other than -1");
+        print_entry(tg,f);
+        m_t2elcount++;
+        return false;
+      } else {
+        asn1::node *nrt = m_gencpp.resolver().resolve(*r);
+        if (nrt && nrt->tagged())
+        {
+          asn1::node::tag_type tg = nrt->tag();
+          print_entry(tg,f);
+          m_t2elcount++;
+          return false;
+        }
+      }
+      //m_os<<"n";
+    } else if (type ) {
+      asn1::node::tag_type tg = type->tag();
+      print_entry(tg,f);
+      m_t2elcount++;
+      return false;
+    }
+    m_os<<"/*end "<<__FUNCTION__<<"*/";
+    return true;
+  }
+  //
+  bool visit_primitive(asn1::node *p)
+  {
+    return true;
+  }
+  //
+  bool visit_reference(asn1::node *type)
+  {
+    if (type->tagged())
+      return true;
+    if (asn1::typeref *r = type->as_typeref())
+    {
+      if (asn1::node *rt = r->get_real_type())
+      {
+        if (asn1::choice *c = dynamic_cast<asn1::choice *>(rt))
+          return traverse_type(rt);
+        if (r->is_complex())
+            return traverse_type(rt);
+        m_os<<".";
+      } 
+    }
+    m_os<<"/* "<<__FUNCTION__<<" : "<<type->cpp_name();
+    m_os<<"*/"<<std::endl;
+    return true;
+  }
+  /* I'm somewhere else */
+  bool visit_component_type(asn1::field *f)
+  {
+    return true;
+  }
+  /* */
+  void print_entry(asn1::node::tag_type &tg,asn1::field *f)
+  {
+    m_os<<"  {"<<"( ("<<tg.m_value<<"<<2) | "<<tg.m_class<<"),";
+    m_os<<m_c.identifier()->cpp_name()<<"::"<<"typeof_"<<m_current_choice;
+    m_os<<","<<(m_elcount-1)<<" }, /*"<<f->name()<<" */"<<std::endl;
+  }
+};
+
+
+void 
+cgh_construct::gen_tag2el_table()
+{
+  size_t _count = 0;
+  tag2glv glv(m_gencpp,m_os,m_c,m_t2elcount);
+
+  m_os<<"static asn1::types::tag2member_desc MAP_"<<m_c.identifier()->cpp_name()<<"_tag2el[] = {\n";
+  bool r= glv.traverse_type(&m_c);
+  m_os<<"};\n";
+}
+
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_codec_ber_encode()
+{
+    std::string  ns ( m_gencpp.get_module()->cpp_name() ) ;
+    std::string  structName ( ns + "::" +m_c.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+#if 0
+    //m_gencpp.gen_template_signature(m_os,type);
+    hpp<<"\n// sequence type "<<structName<<" priv="<<priv<<"\n";
+    hpp<<"template<>\n";
+    hpp<<"void asn1::codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int asn1::codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t);\n";
+#endif
+    /* Generate implementation */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecBER::encode(asn1::streams::ber &c,const "<<structName<<" &_t)\n{\n";
+    cpp<<"\tc.encode_sequence_preamble(_t);\n";
+
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+          continue;
+        }
+        /* */
+        if (attr_type->tagged()
+            && (m_gencpp.is_tag_explicit(*attr_type)))
+        {
+          asn1::node::tag_type lt = attr_type->tag();
+          cpp<<"\t{\n";
+          cpp<<"\t\t"<<"asn1::tag t("<<lt.m_class<<","<<lt.m_value<<",true); "<<std::endl;
+          cpp<<"\t\t"<<"encode_tag(c,t,_t."<<f->cpp_name()<<".get_length());\n";
+        }
+
+        if (f->flags().is_optional() && (! f->flags().is_default()))
+        {
+          cpp<<"\tif ( ! _t."<<f->cpp_name()<<".is_nul())\n\t{\n";
+          cpp<<"\t\tencode(c,_t."<<f->cpp_name()<<".get());\n\t}\n";
+        } else
+        {
+          cpp<<"\tencode(c,_t."<<f->cpp_name()<<");\n";
+        }
+        /* end explicit */
+        if (attr_type->tagged()
+            && (m_gencpp.is_tag_explicit(*attr_type)))
+          cpp<<"\t}\n";
+      }
+   
+    } /* end for */
+    cpp<<"\tc.encode_sequence_epilogue(_t);\n";
+    cpp<<"}\n";
+}
+/**
+ *
+ */ 
+void
+cgh_construct::gen_codec_ber_decode()
+{
+    std::string  ns ( m_gencpp.get_module()->cpp_name() ) ;
+    std::string  structName ( ns + "::" +m_c.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecBER::decode(asn1::streams::ber &c,"<<structName<<" &_t)\n{\n";
+    //cpp<<"\tint len = 0;"<<""<<std::endl;
+    cpp<<"\tif ( c.decode_sequence_preamble(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    /* loop over fields */
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+          continue;
+        } 
+
+        /* */
+        if (attr_type->tagged()
+            && (m_gencpp.is_tag_explicit(*attr_type)))
+        {
+          asn1::node::tag_type lt = attr_type->tag();
+          cpp<<"\t{\n";
+          cpp<<"\t\tasn1::tag t("<<lt.m_class<<","<<lt.m_value<<",true);\n";
+          cpp<<"\t\t"<<"if (c.decode_tag(t))\n\t\t{\n\t\t";
+        }
+
+        if (f->flags().is_optional() && (! f->flags().is_default()))
+        {
+          cpp<<"\tdecode(c,_t."<<f->cpp_name()<<".get());\n";
+        } else
+        {
+          cpp<<"\tdecode(c,_t."<<f->cpp_name()<<");\n";
+        }
+        if (attr_type->tagged()
+            && (m_gencpp.is_tag_explicit(*attr_type)))
+        {
+          cpp<<"\t\t}\n";
+          cpp<<"\t}\n";
+        }
+      }
+    }
+    cpp<<"\tif ( c.decode_sequence_epilogue(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_ndecode(const std::string &scope,bool priv)
+{
+  asn1::constructed *type = &m_c;
+  asn1::node::iterator lit = type->begin();
+  asn1::node::iterator end = type->end();
+  std::string lscope;
+
+  gen_ndecode_preamble(scope,priv);
+  gen_ndecode_epilogue(scope,priv);
+  m_gencpp.gen_template_signature(m_os,type);
+  
+  if (!priv)     
+  {
+    lscope = type->identifier_cpp_name();
+    m_os<<"int "<<type->identifier_cpp_name();
+  } else 
+  {
+    lscope = scope + type->cpp_name();
+    m_os<<"int "<<scope<<type->cpp_name();
+  }
+
+  m_gencpp.gen_template_signature_class(m_os,type);
+  m_os<<"::decode(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+  if (m_gencpp.with_source_debug())
+    m_os<<"\tASN1_BER_LOG_DEBUG(\""<<lscope<<"::decode SEQ \");"<<std::endl;
+  // Core of the function
+  m_os<<"\tif (decode_preamble(ctx) != asn1::ok)\n\t{\n"<<std::endl;
+  if (m_gencpp.with_source_debug())
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\""<<lscope<<"::decode SEQ FAILED decode preamble\");"<<std::endl;
+  m_os<<"\t\treturn asn1::unknown;"<<std::endl;
+  m_os<<"\t}\n";
+  //
+  for (; lit != end ; lit++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+    if (f->get_type() != NULL)
+    {
+      asn1::typenode *attribute_type = f->get_type();
+          
+      if (f->flags().m_flags == asn1::node::marker_type::FL_OPTIONAL)
+      {
+            m_os<<"\t// DEF OPTIONAL ATTRIBUTE"<<std::endl;
+      }
+      if ( attribute_type->tagged())
+      { // Ok tagged value
+          asn1::node::tag_type lt = attribute_type->tag();
+          if(attribute_type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+          {
+            m_os<<"\t"<<f->cpp_name()<<".decode(ctx);";
+            m_os<<"// IMPLICIT DEF="<<attribute_type->type_id()()<<std::endl;
+          } else 
+          {
+            m_os<<"\t{\n";
+            m_os<<"\t\t"<<"asn1::tag t("<<lt.m_class<<","<<lt.m_value<<",true); "<<std::endl;
+            m_os<<"\t\t"<<"if ( ctx.decode_tag(t))\n";
+            m_os<<"\t\t{"<<std::endl;
+            if (attribute_type->has_constraints() )
+            {
+              std::string indent("\t\t");
+              m_gencpp.gen_attribute_constrained_ndecode(m_os,scope,indent ,f);
+            } else if (f->flags().is_default() )
+            {  
+              m_os<<"\t"<<f->cpp_name()<<".decode(ctx);";
+              m_os<<"// EXPLICIT DEF D ="<<attribute_type->type_id()()<<std::endl;
+            } else
+            {
+              m_os<<"\t\t\t";
+              if (f->flags().is_optional())
+                m_os<<"ASN1_ATTRIBUTE_OPTIONAL_DECODE(";
+              m_os<<f->cpp_name();
+              if (! f->flags().is_optional())
+                m_os<<".decode(ctx";
+              m_os<<");// EXPLICIT DEF O ="<<attribute_type->type_id()()<<std::endl;
+            }
+            m_os<<"\t\t}\n";
+            m_os<<"\t}"<<std::endl;
+          }
+      } else 
+      {
+        std::string indent("");
+        if (attribute_type->has_constraints() )
+        {
+          m_gencpp.gen_attribute_constrained_ndecode(m_os,scope,indent ,f);
+        } else if (f->flags().is_default() )
+        {
+          // gen_attribute_default_encode(os,scope,indent ,(*lit));
+          m_os<<"\t"<<""<<f->cpp_name()<<".decode(ctx);//DEF D =";
+          m_os<<attribute_type->type_id()()<<" - "<<std::endl;
+        } else if (f->flags().is_optional() )
+        {
+          // gen_attribute_optional_encode(os,scope,indent ,(*lit));
+          m_os<<"\t"<<"ASN1_ATTRIBUTE_OPTIONAL_DECODE(";
+          m_os<<f->cpp_name()<<");//DEF O =";
+          m_os<<attribute_type->type_id()()<<" - "<<std::endl;
+        }
+        else
+        {
+          m_os<<"\t"<<""<<f->cpp_name()<<".decode(ctx);//DEF=";
+          m_os<<attribute_type->type_id()()<<" - "<<std::endl;
+        }
+      }
+    }
+  }
+  m_os<<"\tdecode_epilogue(ctx);"<<std::endl;
+
+  m_os<<"\treturn asn1::ok;"<<std::endl;
+  m_os<<"\n}"<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_ndecode_preamble(const std::string &scope,bool priv)
+{
+  asn1::constructed *type = &m_c;
+  
+  //
+  if (type->tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_c) )
+    {
+      if (!priv)     
+      {
+        m_os<<"int "<<type->identifier_cpp_name();
+        m_gencpp.gen_template_signature_class(m_os,type);
+        m_os<<"::decode_preamble_ber(asn1::streams::ber &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name()<<"::decode_preamble_ber EXPLICIT  tag:%d\",this->tag().byte());\n";
+      } else 
+      {
+        m_os<<"int "<<scope<<type->cpp_name();
+        m_gencpp.gen_template_signature_class(m_os,type);
+        m_os<<"::decode_preamble_ber(asn1::streams::ber &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->cpp_name()<<"::decode_preamble_ber EXPLICIT  tag:%d\",this->tag().byte());\n";
+      }
+      //
+      m_os<<"\tctx.nb_bits((1)<<3);"<<std::endl;
+      m_os<<"\tlong len = 0;"<<std::endl;
+      m_os<<"\tunsigned char *b = ctx.buffer();"<<std::endl;
+      m_os<<"\tm_pos = ctx.bytes();"<<std::endl;
+      m_os<<"\tctx.decode_length(&b[m_pos],&len);"<<std::endl;
+      m_os<<"\tctx.nb_bits((len)<<3);"<<std::endl;
+      m_os<<"\treturn asn1::ok;"<<std::endl;
+      m_os<<"}"<<std::endl;
+    }
+  }
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_ndecode_epilogue(const std::string &scope,bool priv)
+{
+  asn1::constructed *type = &m_c;
+    //
+  if (type->tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_c) )
+    {
+      if (!priv)     
+      {
+        m_os<<"int "<<type->identifier_cpp_name();
+        m_gencpp.gen_template_signature_class(m_os,type);
+        m_os<<"::decode_epilogue_ber(asn1::streams::ber &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+        {
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name();
+          m_os<<"::decode_epilogue_ber EXPLICIT SEQUENCE tag:%d\",this->tag().byte());\n";
+        }
+      } else 
+      {
+        m_os<<"int "<<scope<<type->cpp_name();
+        m_gencpp.gen_template_signature_class(m_os,type);
+        m_os<<"::decode_epilogue_ber(asn1::streams::ber &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+       {
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->cpp_name();
+          m_os<<"::decode_epilogue_ber EXPLICIT SEQUENCE tag:%d\",this->tag().byte());\n";
+       }
+      }
+      //
+      m_os<<"\tunsigned long pos = ctx.bytes();"<<std::endl;
+      m_os<<"\tunsigned char *b = ctx.buffer();"<<std::endl;
+      m_os<<"\treturn asn1::ok;"<<std::endl;
+      m_os<<"}"<<std::endl;
+    }
+  }
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_nencode(const std::string &scope,bool priv)
+{
+  asn1::constructed     *type = &m_c;
+  asn1::node::iterator lit = (type)->begin();
+  asn1::node::iterator end = (type)->end();
+
+  gen_nencode_preamble(scope,priv);
+  gen_nencode_epilogue(scope,priv);
+
+  m_gencpp.gen_template_signature(m_os,type);
+  if (!priv)     
+  {
+    m_os<<"void "<<type->identifier_cpp_name();
+    m_gencpp.gen_template_signature_class(m_os,type);
+    m_os<<"::encode(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+    if (m_gencpp.with_source_debug())
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name()<<"::encode SEQUENCE \");\n";
+  } else 
+  {
+    m_os<<"void "<<scope<<type->cpp_name();
+    m_gencpp.gen_template_signature_class(m_os,type);
+    m_os<<"::encode(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+    if (m_gencpp.with_source_debug())
+      m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->cpp_name()<<"::encode SEQUENCE\");\n";
+  }
+  //
+  m_os<<"\tencode_preamble(ctx);"<<std::endl;
+  for (; lit != end ; lit++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+    if (f->get_type() != NULL)
+    {
+      asn1::typenode *attribute_type = f->get_type();
+          
+      if ((*lit)->flags().m_flags == asn1::node::marker_type::FL_OPTIONAL)
+      {
+            m_os<<"\t\t// DEF OPTIONAL ATTRIBUTE"<<std::endl;
+      }
+      if ( attribute_type->tagged())
+      { // Ok tagged value
+          if(attribute_type->tag().m_mode == asn1::node::tag_type::TM_IMPLICIT)
+          {
+            asn1::node::tag_type lt = attribute_type->tag();
+            m_os<<"\t\t"<<f->cpp_name()<<".encode(ctx);// IMPLICIT DEF="<<attribute_type->type_id()()<<std::endl;
+          } else {
+            asn1::node::tag_type lt = attribute_type->tag();
+            m_os<<"\t\t"<<f->cpp_name()<<".encode(ctx);// EXPLICIT DEF="<<attribute_type->type_id()()<<std::endl;
+          }
+      } else 
+      {
+          std::string indent("\t");
+          if (attribute_type->has_constraints() )
+          {
+            // gen_attribute_constrained_encode(os,scope,indent ,(*lit));
+            std::string indent("\t\t");
+            m_gencpp.gen_attribute_constrained_nencode(m_os,scope,indent ,f);
+          } else if (f->flags().is_default() )
+          {
+            // gen_attribute_default_encode(os,scope,indent ,(*lit));
+            m_os<<"\tif (bit_mask.test("<<m_c.identifier()->cpp_name()<<"::";
+            m_os<<f->cpp_name()<<"_present))\n"; 
+            m_os<<"\t\t"<<""<<f->cpp_name()<<".encode(ctx);//DEF D =";
+            m_os<<f->get_type()->type_id()()<<" - "<<std::endl;
+          } else if (f->flags().is_optional() ) 
+          {
+            // gen_attribute_optional_encode(os,scope,indent ,(*lit));
+            m_os<<"\t\t"<<"ASN1_ATTRIBUTE_OPTIONAL_ENCODE(";
+            m_os<<f->cpp_name()<<");//DEF O =";
+            m_os<<attribute_type->type_id()()<<" - "<<std::endl;
+          }
+          else
+          {
+            m_os<<"\t\t"<<""<<f->cpp_name()<<".encode(ctx);//DEF=";
+            m_os<<attribute_type->type_id()()<<" - "<<std::endl;
+          }
+      }
+    }
+  }
+  m_os<<"\tencode_epilogue(ctx);"<<std::endl;
+
+  m_os<<"\n}"<<std::endl;
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_nencode_preamble(const std::string &scope,bool priv)
+{
+  asn1::node *type = &m_c;
+  //
+  if (type->tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_c) )
+    {
+      if (!priv)     
+      {
+        m_os<<"void "<<type->identifier_cpp_name()<<"::encode_preamble_ber(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->identifier_name()<<"::encode_preamble_ber EXPLICIT tag:%d\",this->tag().byte());\n";
+      } else 
+      {
+        m_os<<"void "<<scope<<type->cpp_name()<<"::encode_preamble_ber(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<type->cpp_name()<<"::encode_preamble_ber EXPLICIT tag:%d\",this->tag().byte());\n";
+      }
+      //
+      m_os<<"\tunsigned char *b = ctx.buffer();"<<std::endl;
+      m_os<<"\tm_pos = ctx.bytes();"<<std::endl;
+      m_os<<"\tasn1::tag t("<<type->tag().m_class<<","<<type->tag().m_value<<",true);"<<std::endl;
+      m_os<<"\tb[m_pos] = t.byte() | 0x20; //encode tag constructed "<<std::endl;
+      if (type->type_id()() == asn1::type::ASN1_SET)
+      {
+        m_os<<"\tb[m_pos+2] = MAKE_TAG(0,1,17);\n";
+      } else
+        m_os<<"\tb[m_pos+2] = MAKE_TAG(0,1,16);\n";
+      
+      m_os<<"\tctx.nb_bits((4)<<3);"<<std::endl;
+      m_os<<"}"<<std::endl;
+    }
+  }
+}
+
+/**
+ *
+ */ 
+void
+cgh_construct::gen_nencode_epilogue(const std::string &scope,bool priv)
+{
+  //
+  if (m_c.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_c) )
+    {
+      if (!priv)     
+      {
+        m_os<<"void "<<m_c.identifier_cpp_name()<<"::encode_epilogue_ber(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_c.identifier_name()<<"::encode_epilogue_ber EXPLICIT  tag:%d\",this->tag().byte());\n";
+      } else 
+      {
+        m_os<<"void "<<scope<<m_c.cpp_name()<<"::encode_epilogue_ber(asn1::context &ctx)"<<std::endl<<"{"<<std::endl;
+        if (m_gencpp.with_source_debug())
+          m_os<<"\tASN1_BER_LOG_DEBUG(\""<<m_c.cpp_name()<<"::encode_epilogue_ber EXPLICIT  tag:%d\",this->tag().byte());\n";
+      }
+      //
+      m_os<<"\tunsigned long pos = ctx.bytes();"<<std::endl;
+      m_os<<"\tunsigned char *b = ctx.buffer();"<<std::endl;
+      m_os<<"\tb[m_pos+1] = pos - m_pos - 2;"<<std::endl;
+      m_os<<"\tb[m_pos+3] = pos - m_pos - 4;\n";
+      m_os<<"}"<<std::endl;
+    }
+  }
+}
+
+void cgh_construct::gen_codec()
+{
+
+  std::string structName = m_gencpp.get_module()->cpp_name();
+  structName  = structName + "::" +m_c.identifier()->cpp_name();
+  std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+  //m_Gen.gen_template_signature(m_os,type);
+  hpp<<"\n// construct type "<<structName<<""<<"\n";
+#if 0
+  hpp<<"template<>\n";
+  hpp<<"void asn1::codecBER::encode(asn1::codec::ber &c,const "<<structName<<" &_t);\n";
+  hpp<<"\ntemplate<>\n";
+  hpp<<"int asn1::codecBER::decode(asn1::codec::ber &c,"<<structName<<" &_t);\n";
+#endif
+  if (m_gencpp.with_jer())
+  {
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(streams::jer &c,"<<structName<<" &_t);\n";
+  }
+}
+
+
+/**
+ * @brief same code for set and sequence for JER
+ * encoding and decoding
+ *
+ */
+void cgh_construct::generate_jer()
+{
+
+
+  if (m_gencpp.with_codec())
+  {
+    std::string MName = m_gencpp.get_module()->cpp_name();
+    std::string structName ( MName + "::" + m_c.identifier_cpp_name() );
+    std::fstream &hpp(m_gencpp.get_streams().m_os_codec_hpp);
+    std::fstream &cpp(m_gencpp.get_streams().m_os_codec_cpp);
+
+
+    hpp<<"\n// cgh_construct sequence or set type "<<structName<<"\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t);\n";
+    hpp<<"\ntemplate<>\n";
+    hpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t);\n";
+
+    /* Implementation part */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"void codecJER::encode(asn1::streams::jer &c,const "<<structName<<" &_t)\n{\n";
+
+    cpp<<"\tc.put_char(\"{\",1);\n";
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+        } else
+        {
+          if (it != m_c.begin())
+          {
+            if (f->flags().is_optional() )
+            {
+              cpp<<"\tif ( ! _t."<<f->cpp_name()<<".is_nul())\n\t";
+            }
+            cpp<<"\tc.put_char(\", \",2);\n";
+          }
+          if (f->flags().is_optional() )
+          {
+            cpp<<"\tif ( ! _t."<<f->cpp_name()<<".is_nul())\n\t{\n";
+            cpp<<"\t\tc.put_field(\"";
+            cpp<<f->cpp_name()<<"\","<<f->cpp_name().size()<<");\n";
+            cpp<<"\t\tc.put_char(\": \",2);\n";
+            cpp<<"\t\tencode(c,_t."<<f->cpp_name()<<".get());\n\t}\n";
+          } else
+          {
+            cpp<<"\tc.put_field(\"";
+            cpp<<f->cpp_name()<<"\","<<f->cpp_name().size()<<");\n";
+            cpp<<"\tc.put_char(\": \",2);\n";
+            cpp<<"\tencode(c,_t."<<f->cpp_name()<<");\n";
+          }
+       }
+      }
+   
+    }
+    cpp<<"\tc.put_char(\"}\",1);\n";
+
+    cpp<<"}\n";
+    /* Implementation of decoding stream */
+    cpp<<"\ntemplate<>\n";
+    cpp<<"int codecJER::decode(asn1::streams::jer &c,"<<structName<<" &_t)\n{\n";
+    cpp<<"\tif ( c.decode_sequence_preamble(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    /* loop over fields */
+    for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+    {
+      asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+      asn1::typenode *attr_type = f->get_type();
+      if (attr_type != NULL)
+      {
+        if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+        {
+          cpp<<"\t// Extensible marker"<<std::endl;
+        } else
+        {
+          if (it != m_c.begin())
+            cpp<<"\tc.get_token(asn1::streams::jer::jer_tok_comma);\n";
+          cpp<<"\tif (c.get_token(\"";
+          cpp<<f->cpp_name()<<"\"))\n\t{\n";
+          cpp<<"\t\tc.get_token(asn1::streams::jer::jer_tok_colon);\n";
+          if (f->flags().is_optional())
+          {
+            cpp<<"\t\tdecode(c,_t."<<f->cpp_name()<<".get());\n";
+          } else
+          {
+            cpp<<"\t\tdecode(c,_t."<<f->cpp_name()<<");\n";
+          }
+          cpp<<"\t}\n";
+       }
+      }
+    }
+    cpp<<"\tif ( c.decode_sequence_epilogue(_t) != asn1::ok)\n";
+    cpp<<"\t\treturn asn1::wrong_type;\n";
+    cpp<<"\treturn asn1::ok;\n";
+    cpp<<"}\n";
+  }
+}
+
+
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/libgen/cpp/cgh_construct.h b/libgen/cpp/cgh_construct.h
new file mode 100644 (file)
index 0000000..d1293cc
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef CGH_CONSTRUCT_H
+#define CGH_CONSTRUCT_H
+
+
+/**
+ *
+ */
+class cgh_construct : public cgcpp_helper
+{
+  protected:
+    int m_elcount;
+    int m_t2elcount;
+    cgh_construct(const  cgh_construct &s ) 
+            : cgcpp_helper(s.m_gencpp,s.m_os)
+            , m_c(s.m_c)
+    {}  
+  public:
+    cgh_construct( generate_codec_cpp &g
+              , std::ostream &os
+              , asn1::constructed &cdef) ;
+    ~cgh_construct();
+    
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() {};
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() {} ;
+
+  protected:
+    //
+    virtual void generate_descriptor() ;
+    /**
+     * Generate descriptor for set and sequence 
+     */
+    void gen_desc_seqset();
+    void gen_codec();
+    void gen_equal();
+    void gen_data_length();
+    void gen_codec_ber_encode();
+    void gen_codec_ber_decode();
+  protected:
+    void gen_member_tags(std::ostream &os,asn1::field &_f,asn1::typenode &_type);
+    void gen_member_desc(std::ostream &os,asn1::field &_f,asn1::typenode &_type);
+    // Usefull 
+    void gen_member_table();
+    // Generate a table for choice to be able to compute
+    // the appropriate m_kind from the tag
+    void gen_tag2el_table();
+    // 2017/06/06 Lets say I'm going to use same way for 
+    // sequence and set even if it's not the same
+    void gen_ndecode(const std::string &scope,bool priv);
+    void gen_ndecode_preamble(const std::string &scope,bool priv);
+    void gen_ndecode_epilogue(const std::string &scope,bool priv);
+    void gen_nencode(const std::string &scope,bool priv);
+    void gen_nencode_preamble(const std::string &scope,bool priv);
+    void gen_nencode_epilogue(const std::string &scope,bool priv);
+  protected:
+    asn1::constructed    &m_c;
+    std::string           m_structName;
+};
+
+#endif
diff --git a/libgen/cpp/cgh_hconstruct.cpp b/libgen/cpp/cgh_hconstruct.cpp
new file mode 100644 (file)
index 0000000..d6eaab7
--- /dev/null
@@ -0,0 +1,65 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgh_hconstruct.h"
+#include "asn1_recursive_visitor.h"
+
+
+cgh_hconstruct::cgh_hconstruct( generate_header   &g
+                              , std::ostream      &os
+                              , asn1::constructed &cdef)
+  : cghpp_helper(g,os) ,m_c(cdef)
+{
+  m_gencpp.struct_name(&m_c,m_structName);
+}
+
+cgh_hconstruct::~cgh_hconstruct()
+{
+}
+
+void 
+cgh_hconstruct::generate()
+{
+#if 1
+  cghpp_helper::generate();
+#else
+  generate_prolog( );
+  
+  // Missing constructors
+  generate_descriptor( );
+  // Initial ctor
+  generate_ctors( );
+  
+  generate_operators( );
+  
+  generate_members( );
+  //
+  generate_ber();
+  //
+  generate_printf( );
+
+  m_os<<"};\n";
+#endif
+}
+
+void
+cgh_hconstruct::generate_descriptor()
+{
+  cghpp_helper::generate_descriptor( );
+}
+
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/libgen/cpp/cgh_hconstruct.h b/libgen/cpp/cgh_hconstruct.h
new file mode 100644 (file)
index 0000000..44a7ffe
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef CGH_HCONSTRUCT_H
+#define CGH_HCONSTRUCT_H
+
+
+/**
+ *
+ */
+class cgh_hconstruct : public cghpp_helper
+{
+  protected:
+    cgh_hconstruct(const  cgh_hconstruct &s ) 
+            : cghpp_helper(s.m_gencpp,s.m_os)
+            , m_c(s.m_c) , m_structName(s.m_structName)
+    {}  
+  public:
+    cgh_hconstruct( generate_header &g
+              , std::ostream &os
+              , asn1::constructed &cdef) ;
+    ~cgh_hconstruct();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() {};
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {} ;
+
+  protected:
+    // Usefull 
+    /**
+     * @brief implement the code that generated
+     * the begin of the structure. example:
+     *   struct type : public primary type  \n {\n
+     */
+    virtual void generate_prolog( ) { } ;
+    /**
+     * @ brief add a static descriptor attribute to each datatype
+     * this static variable contains the asn1 type meta data
+     * static const types::descriptor _meta;
+     */
+    void generate_descriptor();
+    /**
+     * @brief generate constructors for the type
+     *
+     */
+    virtual void generate_ctors() { };
+    /**
+     * @brief  generique function to generate printf 
+     */ 
+    virtual void generate_printf() { };
+    /**
+     * @brief for choice, sequence and set this
+     * can be useful
+     */
+    virtual void generate_members() { };
+    /**
+     * @brief use this function to generate code related to 
+     * c++ operator like equal, + - * / etc...
+     */
+    virtual void generate_operators() { };
+
+  protected:
+    asn1::constructed    &m_c;
+    std::string           m_structName;
+};
+
+#endif
diff --git a/libgen/cpp/cgh_object.cpp b/libgen/cpp/cgh_object.cpp
new file mode 100644 (file)
index 0000000..b86d5a0
--- /dev/null
@@ -0,0 +1,220 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_object.h"
+#include "asn1_visitor.h"
+
+
+cgh_object::cgh_object( generate_cpp &g
+                      , std::ostream &os
+                      , asn1::object &s
+                      , asn1::classdef &cdef)
+  : m_Gencpp(g), generator_helper(os) , m_object(s) ,m_classdef(cdef)
+       , m_log(g.logger())
+{
+}
+
+cgh_object::~cgh_object()
+{
+}
+
+
+/**
+ * Helper functions
+ *
+ */ 
+void cgh_object::generate()
+{
+}
+
+// generate codec part
+void cgh_object::generate_per()
+{
+}
+
+//
+void cgh_object::generate_ber()
+{
+}
+
+//
+void cgh_object::generate_oer()
+{
+}
+
+//
+void cgh_object::generate_jer()
+{
+}
+
+//
+void cgh_object::generate_xer()
+{
+}
+
+/**
+ *
+ */ 
+class cgho_gtplt_args : public node_visitor<cgho_gtplt_args>
+{
+  protected:
+    asn1::classdef &m_classdef;
+    asn1::object   &m_object;
+    generate_cpp   &m_gen;
+    std::stringstream m_os;
+    std::fstream    &m_log;
+    long            m_count;
+    bool           m_with_scope;
+  public:
+    cgho_gtplt_args(generate_cpp &_gen,asn1::object &_obj,asn1::classdef &_cdef,bool with_scope)
+      : m_count(0), m_classdef(_cdef),m_object(_obj),m_gen(_gen)
+      , m_log(_gen.logger()) , m_with_scope(with_scope)
+    { m_os.str(""); } ;
+
+    std::string result() { return m_os.str() ; }
+
+#define ASN1_CLASSFIELD_TYPE(cf,code) \
+   void visit_##cf(asn1::cf *field) code
+
+ASN1_CLASSFIELD_TYPE(classfield_tf,{
+      asn1::node *type = NULL;    
+      if ( (type =  m_object.get_field(field->name()) ) != NULL)
+      { 
+        if (m_count++)
+          m_os<<" ,";
+        if (m_with_scope)
+        {
+          asn1::typeref *ref = dynamic_cast<asn1::typeref *>(type);  
+          asn1::node *rtype = (ref)?ref->get_real_type():NULL;
+          if(ref && !rtype) 
+          {
+              ref->resolve(m_gen.resolver());
+             rtype = ref->get_real_type();
+          } else
+          {
+            std::cerr<<"gen_template_args type= ";
+            std::cerr<<type->name()<<" NOT TYPEREF\n";
+          }
+          if (rtype)
+          {
+            m_os<<" "<<rtype->get_parent()->cpp_name()<<"::";
+          }  
+        } else
+          m_os<<" ";
+        switch (type->type_id()())
+        {
+          case asn1::type::ASN1_SET_OF:
+         {
+            asn1::node *seqof_type = type->as_typenode()->get_eltype();                  
+           std::string strtype;
+           if (m_gen.type2cppstring(type->as_typenode(),strtype))
+           {
+             m_os<<type->cpp_name()<<"<";
+              m_os<<strtype;
+             m_os<<"/*s */ > ";
+           } else
+           {
+             m_os<<type->cpp_name()<<"<";
+              m_os<<seqof_type->cpp_name();
+             m_os<<"> ";
+           }
+         }
+          break;    
+          default:  
+            GEN_LOG_ERROR( "gen_template_args TFT %s %s\n"
+                        , field->name().c_str()
+                        , type->cpp_name().c_str());
+            m_os<<type->cpp_name();
+        }
+      } else 
+      { // Undefined type. replace with asn1::type 
+        if (m_count++)
+          m_os<<" ,";
+        m_os<<" asn1::types::type";
+      }
+               
+})
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,{
+      asn1::valuetype *type = NULL;
+      if ( (type =  m_object.get_ftvf(field->name()) ) != NULL )
+      {
+        std::string s = field->name();
+        s[0] = '_'; 
+        switch (type->type_id()())
+        {
+          case asn1::type::ASN1_INTEGER:
+          {
+            GEN_LOG_DEBUG( "gen_template_args INT %s %s\n"
+                         , field->name().c_str()
+                         , type->cpp_name().c_str());
+            if (m_count++)
+              m_os<<" ,";
+            m_os<<" "<<type->cpp_name();
+          }
+          break;
+          case asn1::type::ASN1_OBJECT_IDENTIFIER:  
+          {
+            GEN_LOG_DEBUG( "gen_template_args OID %s %s\n"
+                         ,field->name().c_str(),type->cpp_name().c_str());
+            asn1::object_identifier *oid = type->as_object_identifier();
+            long size = oid->hash();
+            if (m_count++)
+              m_os<<" ,";
+            m_os<<" "<<size;
+          }
+          break;
+          case asn1::type::ASN1_CHOICE:  
+          {
+            asn1::value *v = type->value();
+            GEN_LOG_DEBUG( "gen_template_args CHOICE %s %s\n"
+                         , field->name().c_str(),type->cpp_name().c_str());
+            if (m_count++)
+              m_os<<" ,";
+            m_os<<" "<<v->cpp_name();
+          }
+          default:
+          GEN_LOG_ERROR( "gen_template_args %s id %s\n"
+                       , field->name().c_str()
+                       , type->type_id().name());
+        }
+      }
+               
+})
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,{})
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,{})
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,{})
+ASN1_CLASSFIELD_TYPE(classfield_of,{})
+ASN1_CLASSFIELD_TYPE(classfield_osf,{})
+#undef ASN1_CLASSFIELD_TYPE
+};
+
+/**
+ * Needs some reworking for SET_OF type in CMIP
+ */ 
+void 
+cgh_object::gen_template_args(bool with_scope) 
+{
+  asn1::node::iterator fit = m_classdef.begin(); 
+  int count = 0;
+
+  cgho_gtplt_args cgho(m_Gencpp,m_object,m_classdef,with_scope);
+  //std::cout<<"\n\nBEGIN FUNCTION get_template_args with_scope="<<with_scope<<"\n\n";
+  GEN_LOG_DEBUG("gen_template_args start with_scope = %d\n",with_scope);
+  for ( ; fit != m_classdef.end()
+        ; ++fit)
+  {
+    cgho.visit(*fit);
+  }
+  m_os<<cgho.result();
+  GEN_LOG_DEBUG("gen_template_args end count = %d\n",count);
+}
diff --git a/libgen/cpp/cgh_object.h b/libgen/cpp/cgh_object.h
new file mode 100644 (file)
index 0000000..6738c71
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef CGH_OBJECT_H
+#define CGH_OBJECT_H
+
+
+/**
+ *
+ */
+class cgh_object : public generator_helper
+{
+  protected:
+    cgh_object(const  cgh_object &s ) 
+            : generator_helper(s.m_os)
+            , m_Gencpp(s.m_Gencpp)
+            , m_object(s.m_object)
+            , m_classdef(s.m_classdef)
+           , m_log(s.m_log)
+    {}  
+  public:
+    cgh_object( generate_cpp &g
+              , std::ostream &os
+              , asn1::object &s
+              , asn1::classdef &cdef) ;
+    ~cgh_object();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+    asn1::object   &get_object()    { return m_object;}
+
+    asn1::classdef &get_classdef()  { return m_classdef;}
+  protected:
+    // Generate template arguments for object
+    void gen_template_args(bool with_scope=false); 
+  protected:
+    std::fstream          &m_log;
+    generate_cpp         &m_Gencpp;
+    asn1::object         &m_object;
+    asn1::classdef       &m_classdef;
+};
+
+#endif
diff --git a/libgen/cpp/cgh_value.cpp b/libgen/cpp/cgh_value.cpp
new file mode 100644 (file)
index 0000000..ab27c3f
--- /dev/null
@@ -0,0 +1,77 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cgh_value.h"
+
+
+cgh_value::cgh_value( generate_header &g
+                    , std::ostream &os
+                    , asn1::value &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_value(s)
+  , m_log(g.logger())
+{
+}
+
+cgh_value::~cgh_value()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cgh_value::generate()
+{
+  asn1::node *n      = m_value.identifier();
+  asn1::node *type   = &m_value;
+  asn1::node *params = NULL;
+  std::string structName;
+  std::string scope("");
+  
+  if (m_Gen.with_source_comment())
+    m_os<<"// cgh_value helper launched "<<std::endl;
+
+}
+//
+void cgh_value::gen_printf()
+{
+}
+
+// generate codec part
+void cgh_value::generate_per()
+{
+}
+
+//
+void cgh_value::generate_ber()
+{
+}
+
+//
+void cgh_value::generate_oer()
+{
+}
+
+//
+void cgh_value::generate_jer()
+{
+}
+
+//
+void cgh_value::generate_xer()
+{
+}
diff --git a/libgen/cpp/cgh_value.h b/libgen/cpp/cgh_value.h
new file mode 100644 (file)
index 0000000..3920b21
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef CGH_VALUE_H
+#define CGH_VALUE_H
+
+
+/**
+ *
+ */
+class cgh_value : public generator_helper
+{
+  protected:
+    cgh_value(const  cgh_value &s) :  generator_helper(s.m_os)
+                                     , m_Gen(s.m_Gen) 
+                                     , m_log(s.m_log) 
+                                     , m_value(s.m_value) {}  
+  public:
+    cgh_value(generate_header &g,std::ostream &os,asn1::value &s) ;
+    ~cgh_value();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_printf();
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::value        &m_value;
+};
+
+#endif
diff --git a/libgen/cpp/cghpp_helper.cpp b/libgen/cpp/cghpp_helper.cpp
new file mode 100644 (file)
index 0000000..506be7d
--- /dev/null
@@ -0,0 +1,77 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_hpp.h"
+#include "cghpp_helper.h"
+
+
+/**
+ * constructor
+ */
+cghpp_helper::cghpp_helper( generate_header    &g
+                          , std::ostream       &os
+          )
+  : m_gencpp(g), generator_helper(os),m_log(g.logger())
+{
+}
+
+/**
+ *
+ * @brief common way to generate the required code depending
+ * on the global settings given to the asn1 parser.
+ */
+void
+cghpp_helper::generate()
+{
+  // generate class begin
+  generate_prolog();
+  // descriptor is a static attribute named _meta
+  generate_descriptor();
+  // generate ctors
+  generate_ctors();
+  // generate members
+  generate_members();
+  // generate ber
+  generate_ber();
+  // generate jer
+  // generate oer
+  // generate per
+  generate_operators();
+  //
+  generate_printf();
+  // generate class end
+  m_os<<"};\n";
+}
+
+void 
+cghpp_helper::generate_descriptor()
+{
+  m_os<<"\tstatic const asn1::types::descriptor _meta;\n";
+}
+
+void 
+cghpp_helper::generate_prolog()
+{
+}
+
+void 
+cghpp_helper::generate_ctors()
+{
+}
+
+/* Only valid for choice, set ,and sequence */
+void 
+cghpp_helper::generate_members()
+{
+}
+
+void 
+cghpp_helper::generate_printf()
+{
+}
diff --git a/libgen/cpp/cghpp_helper.h b/libgen/cpp/cghpp_helper.h
new file mode 100644 (file)
index 0000000..19bbf33
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef CODE_GEN_HPP_HELPER_H
+#define CODE_GEN_HPP_HELPER_H
+
+/**
+ * This class defines the interface that each 
+ *    asn1 type generation should implement ....
+ * Unlike generator_helper, this class provides a first
+ * level of functions dedicated to c++ code generation. The goal is
+ * to move the generation from one unique file to one file per type.
+ *   -> provide streams for cpp,h and hpp.
+ *   -> provide generic preamble et epilog
+ *   -> open /close stream 
+ */ 
+class cghpp_helper : public generator_helper
+{
+  public:
+    cghpp_helper( generate_header    &g
+                , std::ostream       &os
+                );
+  
+    /**
+     * @brief entry point to generate the structure. Should
+     * follow the same pattern for all asn1 types.
+     * @TODO This function should not be virtual when you think
+     * of it.
+     */
+    virtual void generate()  ;
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() {};
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {};
+
+    // generate encoder
+    // generate decoder
+    // generate constructor
+    // generate 
+  protected:
+    /**
+     * @brief implement the code that generated
+     * the begin of the structure. example:
+     *   struct type : public primary type  \n {\n
+     */
+    virtual void generate_prolog();
+    /**
+     * @ brief add a static descriptor attribute to each datatype
+     * this static variable contains the asn1 type meta data
+     * static const types::descriptor _meta;
+     */
+    void generate_descriptor();
+    /**
+     * @brief generate constructors for the type
+     *
+     */
+    virtual void generate_ctors();
+    /**
+     * @brief  generique function to generate printf 
+     */ 
+    virtual void generate_printf();
+    /**
+     * @brief for choice, sequence and set this
+     * can be useful
+     */
+    virtual void generate_members();
+    /**
+     * @brief use this function to generate code related to 
+     * c++ operator like equal, + - * / etc...
+     */
+    virtual void generate_operators() {};
+  protected:
+    std::fstream          &m_log;
+    generate_header       &m_gencpp;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_bitstring.cpp b/libgen/cpp/cghpph_bitstring.cpp
new file mode 100644 (file)
index 0000000..90ef8b4
--- /dev/null
@@ -0,0 +1,122 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_bitstring.h"
+
+
+cghpph_bit_string::cghpph_bit_string(generate_header &g,std::ostream &os,asn1::bit_string &s)
+  : cgh_hconstruct(g,os,s) , m_bit_string(s)
+{
+}
+
+cghpph_bit_string::~cghpph_bit_string()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_bit_string::generate()
+{
+  cgh_hconstruct::generate( );
+}
+
+/**
+ *
+ */
+void cghpph_bit_string::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_bit_string helper launched "<<std::endl;
+
+  m_os<<"struct "<<m_bit_string.identifier_cpp_name()<<" : public BIT_STRING\n{\n";
+}
+
+/**
+ *
+ */
+void cghpph_bit_string::generate_ctors()
+{
+ // Initial ctor
+  m_os<<"\t"<<m_c.identifier_cpp_name()<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_bit_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_bit_string) )
+    {
+      m_os<<m_bit_string.tag().m_class<<","<<m_bit_string.tag().m_value<<",true));\n";
+    } else
+    {
+      m_os<<m_bit_string.tag().m_class<<","<<m_bit_string.tag().m_value<<",false));\n";
+    }
+  }else
+    m_os<<"0,3)) ;\n";
+  // copy 
+  m_os<<"\t"<<m_c.identifier_cpp_name()<<"(const "<<m_c.identifier_cpp_name()<<" &t"<<") ;\n";
+  
+}
+/**
+ *
+ */
+void cghpph_bit_string::generate_members()
+{
+  for (asn1::node::iterator it = m_c.begin(); it != m_c.end() ; it++)
+  {
+    asn1::valuetype *tv = dynamic_cast<asn1::valuetype *>(*it);
+    if ((*it)->type_id()()== asn1::type::ASN1_INTEGER /*&& (*it)->value_long()<31*/)
+    {
+      m_os<<"\tstatic unsigned long const "<<(*it)->cpp_name();
+      long dest= tv->value_long();
+      m_os<<"\t= "<<dest<<";";
+    } else {
+      m_os<<"\t//static unsigned long const "<<(*it)->cpp_name();
+      long dest= tv->value_long();
+      m_os<<"\t= "<<dest<<";";
+    }
+    if (it != m_c.end())
+    {
+      m_os<<"\n";
+    } else
+    { 
+      m_os<<"\n";
+    }
+  }
+}
+
+/**
+ *
+ */
+void cghpph_bit_string::generate_printf()
+{
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const ";
+  m_os<<m_bit_string.identifier_cpp_name()<<" &s);\n";
+}
+
+//
+void cghpph_bit_string::generate_ber()
+{
+  //
+  if (m_bit_string.tagged()
+      && m_gencpp.is_tag_explicit(m_bit_string) )
+  {
+    {
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
diff --git a/libgen/cpp/cghpph_bitstring.h b/libgen/cpp/cghpph_bitstring.h
new file mode 100644 (file)
index 0000000..ee3082f
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CGHPPH_BITSTRING_H
+#define CGHPPH_BITSTRING_H
+
+
+/**
+ *
+ */
+class cghpph_bit_string : public cgh_hconstruct
+{
+  protected:
+    cghpph_bit_string(const  cghpph_bit_string &s) :  cgh_hconstruct(s.m_gencpp,s.m_os,s.m_c)
+                                     , m_bit_string(s.m_bit_string) {}  
+  public:
+    cghpph_bit_string(generate_header &g,std::ostream &os,asn1::bit_string &s) ;
+    ~cghpph_bit_string();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    virtual void generate_prolog();
+
+    virtual void generate_printf();
+    
+    virtual void generate_ctors();
+    
+    virtual void generate_members();
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {};
+
+  protected:  
+    asn1::bit_string   &m_bit_string;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_boolean.cpp b/libgen/cpp/cghpph_boolean.cpp
new file mode 100644 (file)
index 0000000..2d757d6
--- /dev/null
@@ -0,0 +1,105 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_primitive.h"
+#include "cghpph_boolean.h"
+
+
+cghpph_boolean::cghpph_boolean(generate_header &g,std::ostream &os,asn1::boolean &s)
+  :  cghpph_primitive(g,os,s)
+  , m_boolean(s)
+{
+}
+
+cghpph_boolean::~cghpph_boolean()
+{
+}
+
+/**
+ *
+ */
+void cghpph_boolean::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_boolean helper launched "<<std::endl;
+
+  assert(m_boolean.type_id()() == asn1::type::ASN1_BOOLEAN); 
+
+  if (m_gencpp.with_source_comment())
+    m_os<<"\n//\n// struct "<<m_structName<<"\n//\n";
+  m_os<<"struct "<<m_structName<<" : public BOOLEAN\n{\n";
+}
+
+/**
+ *
+ */
+void cghpph_boolean::generate_ctors()
+{
+  // Initial ctor
+  m_os<<"\t"<<m_structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_boolean.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_boolean) )
+    {
+      m_os<<m_boolean.tag().m_class<<","<<m_boolean.tag().m_value<<",true));\n";
+    } else
+    {
+      m_os<<m_boolean.tag().m_class<<","<<m_boolean.tag().m_value<<",false));\n";
+    }
+  }else
+    m_os<<"0,1)) ;\n";
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+}
+
+/**
+ *
+ */
+void cghpph_boolean::generate_operators()
+{
+  // equal operator
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+
+/**
+ *
+ */
+void cghpph_boolean::generate_printf()
+{
+  asn1::node           *ident  = m_boolean.identifier();
+  asn1::node           *params = ident->parameters();
+  
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<");";
+  m_os<<"\n";
+}
+
+/**
+ *
+ */
+void cghpph_boolean::generate_ber()
+{
+  //
+  if (m_boolean.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_boolean) )
+    {
+      //
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
diff --git a/libgen/cpp/cghpph_boolean.h b/libgen/cpp/cghpph_boolean.h
new file mode 100644 (file)
index 0000000..b37c553
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef CGHPPH_BOOLEAN_H
+#define CGHPPH_BOOLEAN_H
+
+
+/**
+ *
+ */
+class cghpph_boolean : public cghpph_primitive
+{
+  protected:
+    cghpph_boolean(const  cghpph_boolean &s) :  cghpph_primitive(s.m_gencpp,s.m_os,s.m_boolean)
+                                     , m_boolean(s.m_boolean) {}  
+  public:
+    cghpph_boolean(generate_header &g,std::ostream &os,asn1::boolean &s) ;
+    ~cghpph_boolean();
+    
+    // Helper functions
+
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {};
+
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    virtual void generate_printf();
+    virtual void generate_operators();
+  protected:
+    asn1::boolean      &m_boolean;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_choice.cpp b/libgen/cpp/cghpph_choice.cpp
new file mode 100644 (file)
index 0000000..7ec7abd
--- /dev/null
@@ -0,0 +1,417 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_choice.h"
+
+#undef GEN_LOG_DEBUG
+#define GEN_LOG_DEBUG
+
+cghpph_choice::cghpph_choice(generate_header &g,std::ostream &os,asn1::choice &s)
+  : cgh_hconstruct(g,os,s) , m_choice(s) 
+{
+}
+
+cghpph_choice::~cghpph_choice()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_choice::generate()
+{
+  asn1::node *ident         = m_choice.identifier();
+  asn1::constructed *params = (ident) ? ident->parameters() : NULL;
+
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"\n//\n// cghpph_choice helper launched ";
+    m_os<<m_structName<<"\n//"<<std::endl;
+  }
+  // Rework Old code ...
+  // 
+  if ( ! m_gencpp.add_symbol(m_structName,&m_choice) )
+  {
+    m_os<<"//cghpph_choice Structure already in map, skip\n";
+    return;
+  }
+
+  cgh_hconstruct::generate();
+}
+
+
+void
+cghpph_choice::generate_prolog( )
+{
+  asn1::node *ident         = m_choice.identifier();
+  asn1::constructed *params = (ident) ? ident->parameters() : NULL;
+  
+  // Handle parameter stuff
+  if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_os<<"//"<<__FUNCTION__<<" parameterized\n";
+    // Forward declaration for ostream function
+    m_os<<"template ";
+    m_gencpp.gen_template_signature(m_os,params);
+    m_os<<" struct "<<m_structName<<" /* : public asn1::types::type */ ;\n";
+    m_os<<"template ";
+    m_gencpp.gen_template_signature(m_os,params);
+    m_os<<"\nstd::ostream & operator<<(std::ostream &m_os,const "<<m_structName;
+    m_gencpp.gen_template_params(m_os,params);
+    m_os<<" &s) ;\n";
+   
+    // Real declaration
+    m_os<<"template ";
+    m_gencpp.gen_template_signature(m_os,params);
+  }
+  m_os<<"struct "<<m_structName<<"  : public asn1::types::choice_type\n";
+  m_os<<"{\n";
+}
+
+/**
+ *
+ */
+void
+cghpph_choice::generate_operators( )
+{
+  // == operator 
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+/**
+ *
+ */
+void
+cghpph_choice::generate_ctors( )
+{
+  asn1::node::iterator  it;
+  asn1::node           *ident  = m_choice.identifier();
+  asn1::constructed    *params = (ident) ? ident->parameters() : NULL;
+
+  // Constructor
+  // Initialize tag , with first aleternative choice 
+  // First alternative choice
+  it = m_choice.begin();
+  asn1::field *first = dynamic_cast<asn1::field *>(*it);
+
+  if (first->get_type()->tagged())
+  {
+    asn1::node::tag_type lt = first->get_type()->tag();
+    
+    m_os<<"\t"<<m_structName<<"(unsigned int _kind ,const asn1::tag t = asn1::tag("<<lt.m_class<<","<<lt.m_value<<"));\n";
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag("<<lt.m_class<<","<<lt.m_value<<"));\n";
+  } else if (asn1::typeref *tref = first->get_type()->as_typeref())
+  {
+    // get outer most tag
+    //asn1::node::tag_type  o_tag = tref->otag();
+    asn1::node::tag_type  o_tag = m_choice.get_tag(m_gencpp.resolver());
+    m_os<<"\t"<<m_structName<<"(unsigned int _kind ,const asn1::tag t = asn1::tag(";
+    m_os<<o_tag.m_class<<","<<o_tag.m_value<<"/*ref*/));\n";
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(";
+    m_os<<o_tag.m_class<<","<<o_tag.m_value<<"/*ref*/));\n";
+   
+  } else {
+    m_os<<"\t"<<m_structName<<"(unsigned int _kind ,const asn1::tag t = asn1::tag(0,";
+    m_os<<""<<first->get_type()->tag().m_value<<"));\n";
+    // Why ...
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(0,";
+    m_os<<""<<first->get_type()->tag().m_value<<"));\n";
+  }
+
+  // Missing Copy constructor
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName;
+  if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s) ;\n";
+  // Clone
+  m_os<<"\tvirtual "<<m_structName;;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<" *clone() ;\n";
+  
+  // Missing Destructor 
+  // m_choice is deleted by choice_type.
+  //m_os<<"\t//virtual ~"<<m_structName<<"();\n";
+  // Create object 
+  m_os<<"\tvirtual bool create_object();\n";
+  
+}
+
+/**
+ *
+ *
+ */ 
+void 
+cghpph_choice::generate_members()
+{
+  std::string       scope("");
+  asn1::node       *ident      = m_choice.identifier();
+  asn1::parameters *params     = dynamic_cast<asn1::parameters *>(ident->parameters());
+
+  // Ok, loop over attributes
+  // to generate setter and getter
+  for ( asn1::node::iterator it = m_choice.begin() 
+      ; it != m_choice.end() ; ++it)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    m_gencpp.gen_composite_attribute(m_os,scope,*f,ident->parameters(),false);
+    // Setter
+    gen_setter(f);
+  }
+  // Now add an enum to identifie type
+  gen_enum_type();
+  // Gen attribute parameters (OPERATION ....)
+
+
+  if (params)
+  {
+    for (asn1::node::iterator it = params->begin();
+       it != params->end();
+       ++it)
+    {
+      asn1::parameter *p = dynamic_cast<asn1::parameter *>(*it);
+      if (asn1::node *g = p->get_governor())
+      {
+        asn1::typeref *objr = dynamic_cast<asn1::typeref *>(g);      
+        asn1::node *obj     = m_gencpp.resolver().resolve(*objr);
+        asn1::module *m     = dynamic_cast<asn1::module *>(obj->get_parent()); 
+        m_os<<"\t// "<<g->name()<<" "<<p->name()<<std::endl;
+        if (!objr->is_simple())
+        {
+          m_os<<"\t"<<m->cpp_name()<<"::I"<<g->name()<<" **"<<p->name()<<";"<<std::endl;
+        }
+      }
+    }
+  }
+}
+
+/**
+* generate setter and getter
+*   - attribute an attribute of choice
+*   - params    the potential parameters stored in choice ident 
+*/ 
+void cghpph_choice::gen_setter(asn1::field *attribute )
+{
+  std::string scope;         // TODO make this deprecated
+  asn1::node *ident          = m_choice.identifier();
+  asn1::node *params         = ident->parameters();
+  asn1::typenode *attr_type  = attribute->get_type();
+  m_os<<"\n";
+  //
+  if (attr_type != NULL)
+  {
+    switch (attr_type->type_id()())
+    {
+      case asn1::type::ASN1_ENUMERATED:
+      case asn1::type::ASN1_CHOICE:
+      {
+          assert( 0 && "cghpph_choice::gen_setter ENUM OR CHOICE should not happend");
+      } 
+      break;
+      case asn1::type::ASN1_REFERENCE:
+      {
+        asn1::typeref *tref = dynamic_cast<asn1::typeref *>(attr_type); 
+        asn1::node *rt = m_gencpp.resolver().resolve(*tref);
+        if ( tref->is_simple()
+             || (rt && rt->type_node())
+            )
+        {
+          m_os<<"\tvoid set_"<<attribute->cpp_name()<<"(const ";
+          m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+          m_os<<" &s);\n";
+          m_os<<"\t";
+          m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+          m_os<<"& get_"<<attribute->cpp_name()<<"();\n";
+          
+          m_os<<"\tconst ";
+          m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+          m_os<<" &get_"<<attribute->cpp_name()<<" () const ; \n";
+        }else
+        {
+          m_os<<"// Complex reference "<<attribute->name()<<std::endl;
+          m_os<<"\tvoid set_"<<attribute->cpp_name()<<"(const ";
+          m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+          m_os<<" *s);\n";
+          m_os<<"\t";
+          m_gencpp.gen_composite_attribute_ref(m_os,scope,attribute,params);
+          m_os<<"* get_"<<attribute->cpp_name()<<"();\n";
+
+        }
+      } 
+      break;
+      default:
+      {
+        std::string strtype;
+        if (m_gencpp.type2cppstring(attr_type,strtype) )
+        {
+          m_os<<"\tvoid set_"<<attribute->cpp_name()<<"(const ";
+          m_os<<strtype;
+          m_os<<" &s);\n";
+          m_os<<"\t"<<strtype<<" &get_"<<attribute->cpp_name()<<" () ;\n";
+          m_os<<"\tconst "<<strtype<<" &get_"<<attribute->cpp_name()<<" () const;\n";
+        } else 
+        {
+          assert(0);
+        }
+      }
+      break;
+    }
+  } else 
+  {
+    GEN_LOG_ERROR("attr_type is NULL\n");
+  }
+}
+/**
+ *
+ */ 
+void cghpph_choice::gen_enum_type()
+{
+  asn1::choice *type  = &m_choice;  
+  // Now add an enum to identifie type
+  m_os<<"\tenum { "<<std::endl;
+  asn1::node::iterator lit = type->begin();
+
+  for (; lit != (type)->end() ; lit++)
+  {
+    asn1::field     *f = dynamic_cast<asn1::field *>(*lit); 
+    asn1::typenode  *attribute_type = f->get_type();
+    if (f->is_extensible())
+      continue;
+    if (attribute_type && attribute_type->tagged())
+    { 
+      /* tagged */ 
+      m_os<<"\t\ttypeof_"<<(*lit)->cpp_name();
+      if (m_gencpp.is_tag_explicit(*attribute_type)  )
+      {
+        m_os<<"\t="<<attribute_type->tag().get_tag()<<", ";
+        m_os<<" // Explicit + "<<(int)attribute_type->tag().byte(); 
+      } else
+      {
+        m_os<<"\t="<<attribute_type->tag().get_tag()<<", ";
+        m_os<<" // Implicit + "<<(int)attribute_type->tag().byte(); 
+      }
+      m_os<<std::endl;
+    } else if (attribute_type  && attribute_type->type_id()() == asn1::type::ASN1_REFERENCE) 
+    {
+      /* reference type */  
+      std::list<asn1::node *>lst;
+      m_gencpp.reference_chaine(attribute_type->as_typeref(),lst);
+      
+      if ((lst.size() > 0) && lst.back() != NULL)
+      {
+        if (lst.back()->tag().m_value >= 0)
+        {
+          m_os<<"\t\ttypeof_"<<(*lit)->cpp_name();
+          if (m_gencpp.is_tag_explicit(* dynamic_cast<asn1::typenode *>(lst.back())) )
+          {
+            m_os<<"\t="<<lst.back()->tag().get_tag()<<", ";
+            m_os<<" // Explicit "<<(int)lst.back()->tag().byte(); 
+          } else
+          {
+            m_os<<"\t="<<lst.back()->tag().get_tag()<<", ";
+            m_os<<" // Implicit "<<(int)lst.back()->tag().byte(); 
+          }
+          m_os<<", /*ref tag*/"<<std::endl;
+        } else {
+          m_os<<"\t\ttypeof_"<<(*lit)->cpp_name()<<", ";
+          m_os<<"// ref type no tag "<<lst.back()->name()<<std::endl;
+        }
+      } else
+      {
+        m_os<<"\t\ttypeof_"<<(*lit)->cpp_name()<<",/*ext ref missing*/ "<<std::endl;
+      }
+    } else if (attribute_type )
+    {
+      /* untagged type */  
+      if (attribute_type->tag().m_value > 0)
+      {
+        m_os<<"\t\ttypeof_"<<(*lit)->cpp_name()<<"\t="<<attribute_type->tag().get_tag()<<" ,";
+        m_os<<"// m_value > 0";
+        m_os<<std::endl;
+      } else
+        m_os<<"\t\ttypeof_"<<(*lit)->cpp_name()<<",/*no tag */ "<<std::endl;
+    } else
+    {
+      m_os<<"\t\ttypeof_"<<(*lit)->cpp_name()<<", "<<std::endl;
+    }
+  }
+
+  m_os<<"\t\ttypeof_end\n\t};"<<std::endl;
+
+}
+//
+void cghpph_choice::generate_printf( )
+{
+  asn1::node *ident = m_choice.identifier();
+
+  m_os<<"\tfriend std::ostream & operator<< ";
+  if (ident && ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_os<<"<>";
+  }
+  m_os<<"(std::ostream &os,const ";
+  m_os<<""<<m_structName;
+  // Parameter stuff here
+  if (ident && ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<")"; 
+  m_os<<";\n";
+}
+
+// generate codec part
+void cghpph_choice::generate_per()
+{
+}
+
+//
+void cghpph_choice::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_choice;
+
+  if ( m_gencpp.with_ber() 
+      && m_choice.tagged()  
+      && m_gencpp.is_tag_explicit(m_choice) )
+  {
+    m_os<<"\tvirtual void encode_ber(asn1::streams::ber &ctx);"<<std::endl;
+    m_os<<"\tvirtual int  decode_ber(asn1::streams::ber &ctx);"<<std::endl;
+  }
+}
+
+//
+void cghpph_choice::generate_oer()
+{
+}
+
+//
+void cghpph_choice::generate_jer()
+{
+}
+
+//
+void cghpph_choice::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cghpph_choice.h b/libgen/cpp/cghpph_choice.h
new file mode 100644 (file)
index 0000000..6e5a1d3
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef CGHPPH_CHOICE_H
+#define CGHPPH_CHOICE_H
+
+
+/**
+ *
+ */
+class cghpph_choice : public cgh_hconstruct
+{
+  protected:
+    cghpph_choice(const  cghpph_choice &s) : cgh_hconstruct(s.m_gencpp,s.m_os,s.m_choice)
+                                           , m_choice(s.m_choice)
+                                               {}  
+  public:
+    cghpph_choice(generate_header &g,std::ostream &os,asn1::choice &s) ;
+    ~cghpph_choice();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+  protected:
+    /**
+     * generate setter and getter 
+     */ 
+    void gen_setter(asn1::field *attribute);
+
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    virtual void generate_printf();
+    virtual void generate_operators();
+    /**
+     * @brief Generate member attributes for
+     *   Parameterized types
+     */ 
+    virtual void generate_members();
+    /**
+     * enum in choice of all type for selection purpose
+     */ 
+    void gen_enum_type();
+  protected:
+    asn1::choice       &m_choice;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_classdef.cpp b/libgen/cpp/cghpph_classdef.cpp
new file mode 100644 (file)
index 0000000..98694ac
--- /dev/null
@@ -0,0 +1,608 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "cghpph_classdef.h"
+#include "asn1_visitor.h"
+
+
+cghpph_classdef::cghpph_classdef(generate_header &g,std::ostream &os,asn1::classdef &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_classdef(s)
+  , m_log(g.logger())
+{
+}
+
+cghpph_classdef::~cghpph_classdef()
+{
+}
+
+
+struct gen_iattr : public node_visitor<gen_iattr>
+{
+  std::string fieldname;
+  bool        m_istemplate; // Use same generator for template
+  gen_iattr( std::ostream &os,generate_header &h,bool _istplt=false)
+   : m_os(os) , m_Gen(h),m_istemplate(_istplt)
+  {
+  }
+  void operator ()(asn1::node *n)
+  {
+    fieldname = n->cpp_name();
+    fieldname[0] = '_';
+    visit(n);
+  }
+#define ASN1_CLASSFIELD_TYPE(cls,code) \
+    void visit_##cls(asn1::cls *f) code 
+
+ASN1_CLASSFIELD_TYPE(classfield_tf,{
+  if (!m_istemplate)
+    return ;
+  //m_os<<" type "<<f->cpp_name()<<std::endl;
+  m_os<<"\t\t"<<fieldname<<" m"<<fieldname<<";\n";
+})       
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,{
+  std::string strtype;
+  // For templates ftvf are interface attributes
+  if (m_istemplate)
+    return;
+  m_Gen.type2cppstring(f->get_type(),strtype);
+  m_os<<"\t\t"<<strtype<<"\t"<<fieldname<<";\n";   
+})   
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,{})   
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,{
+  m_os<<"\t\tSet<"<<f->get_type()->cpp_name()<<">\t"<<fieldname<<";\n";   
+}) 
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,{}) 
+ASN1_CLASSFIELD_TYPE(classfield_of,{})       
+ASN1_CLASSFIELD_TYPE(classfield_osf,{
+  m_os<<"\t\tasn1::ObjectSetEntry\t*"<<fieldname<<";\n";   
+})     
+
+  std::ostream &m_os;
+  generate_header &m_Gen;
+};
+
+/** 
+ * Helper functions
+ *
+ */ 
+void cghpph_classdef::generate()
+{
+  asn1::node::iterator it = m_classdef.begin();
+  asn1::node *n           = m_classdef.identifier();
+  asn1::classdef *type    = &m_classdef;
+  asn1::node *params      = NULL;
+  std::string structName;
+  std::string scope("");
+  
+  m_os<<"// cghpph_classdef helper launched "<<std::endl;
+  if (! should_generate())
+  {
+    m_os<<"// Don't generare class "<<n->identifier()<<std::endl;
+    return;
+  } 
+  assert(m_classdef.type_id()() == asn1::type::ASN1_CLASSDEF); 
+  structName = n->cpp_name();
+
+  /**
+   *
+   */
+  m_Gen.gen_object_class_missing(m_os,type);
+  //
+  //
+  gen_interface();
+  
+  gen_objectset();
+  
+  if (std::string("ERROR").compare(n->cpp_name()) == 0) 
+  {
+  m_os<<"#ifdef ERROR\n";
+  m_os<<"#undef ERROR\n";
+  m_os<<"#endif\n";
+  }
+  //
+  //
+  gen_template();
+}
+
+/**
+ * Helper to travers class fields in template ...
+ */ 
+class cghcdtplt : public node_visitor<cghcdtplt>
+{
+  protected:
+    std::ostream &m_os;
+    generate_header &m_gen;
+    std::string fieldname;
+    std::fstream &m_log;
+  public:
+    cghcdtplt(std::ostream &_os,generate_header &h)
+      : m_os(_os),m_gen(h),m_log(h.logger())
+    {}
+
+    // used by foreach
+    void operator ()(asn1::node *n)
+    {
+      fieldname = n->cpp_name();
+      fieldname[0] = '_';
+      m_os<<"\t// "<<n->cpp_name()<<" type_id="<<n->type_id()();
+      visit(n);
+    }
+#define ASN1_CLASSFIELD_TYPE(cls,code) \
+    void visit_##cls(asn1::cls *f) code 
+
+ASN1_CLASSFIELD_TYPE(classfield_tf,{
+
+  m_os<<"\n\t//getter \n";
+  m_os<<"\tint get"<<fieldname<<"("<<fieldname<<" &v)\n\t{\n";
+  m_os<<"\t\tv = m"<<fieldname<<";\n";
+  if ( f->flags().is_optional() ) 
+  {
+    m_os<<"\t\treturn m.present"<<fieldname<<";\n";
+  } else
+  {
+    m_os<<"\t\treturn 1;\n";
+  }
+  m_os<<"\t};\n";
+  // Fast Access
+  m_os<<"\t"<<fieldname<<"\t&get"<<fieldname<<"()\n\t{\n";
+  m_os<<"\t\treturn m"<<fieldname<<";\n";
+  m_os<<"\t};\n";
+
+    // Setter
+  m_os<<"\t//setter \n";
+  m_os<<"\tvoid set"<<fieldname<<"(const "<<fieldname<<" &v)\n\t{\n";
+  m_os<<"\t\tm"<<fieldname<<"= v;\n";
+  if ( f->flags().is_optional() ) 
+  {
+    m_os<<"\t\tmemset(&m,0x00,sizeof(struct _present)); \n";
+    m_os<<"\t\tm.present"<<fieldname<<"= 1;\n";
+  }
+  m_os<<"\t};\n\n";
+    // New decode function
+  m_os<<"\tint decode"<<fieldname<<"(asn1::context &ctx)\n\t{"<<std::endl;
+  if (m_gen.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\""<<f->cpp_name()<<"::decode"<<fieldname;
+    m_os<<"(ctx &c) \");"<<std::endl;
+  }
+  if ( f->flags().is_optional() ) 
+    m_os<<"\t\tm.present"<<fieldname<<"= 1;\n";
+  m_os<<"\t\treturn m"<<fieldname<<".decode(ctx);"<<std::endl;
+  m_os<<"\t};\n";
+    // encode
+  m_os<<"\tvoid encode"<<fieldname<<"(asn1::context &ctx)\n\t{"<<std::endl;
+  if (m_gen.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\""<<f->cpp_name();
+    m_os<<"::decode"<<fieldname<<"(ctx &c) \");"<<std::endl;
+  }
+  if ( f->flags().is_optional() ) 
+    m_os<<"\t\tif (m.present"<<fieldname<<")\n";
+  m_os<<"\t\t\tm"<<fieldname<<".encode(ctx);"<<std::endl;
+  m_os<<"\t};\n";
+})
+
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,{
+  m_os<<std::endl;
+  return ;
+})   
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,{
+  m_os<<std::endl;
+})
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,{
+  m_os<<std::endl;
+})
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,{
+  m_os<<std::endl;
+})
+ASN1_CLASSFIELD_TYPE(classfield_of,{
+  m_os<<std::endl;
+})
+ASN1_CLASSFIELD_TYPE(classfield_osf,{
+  m_os<<std::endl;
+})
+
+
+  protected:
+};
+
+void cghpph_classdef::gen_template()
+{
+  asn1::node::iterator it = m_classdef.begin();
+  asn1::node *n           = m_classdef.identifier();
+  asn1::classdef *type    = &m_classdef;
+  asn1::node *params      = NULL;
+  std::string structName;
+  std::string scope("");
+  
+  if (! should_generate())
+  {
+    m_os<<"// Don't generare class "<<n->identifier()<<std::endl;
+    return;
+  } 
+
+  structName = n->cpp_name();
+
+  m_Gen.gen_object_class_tplt(m_os,type);
+  m_os<<"struct "<<n->cpp_name()<<" : public I"<<n->cpp_name()<<"\n{\n"<<std::endl;;
+  m_os<<"\tenum {uuid = _uuid};"<<std::endl;
+  //typedef  asn1::intrusive_ptr<Object> ptr;
+  m_os<<"\ttypedef asn1::intrusive_ptr<"<<n->cpp_name();
+  m_Gen.gen_object_class_tplt_params(m_os,type);
+  m_os<<" > ptr;\n";
+  m_os<<"\ttypedef "<<n->cpp_name();
+  m_Gen.gen_object_class_tplt_params(m_os,type);
+  m_os<<"  otype;\n";
+  m_os<<"\ttypedef "<<n->cpp_name();
+  m_Gen.gen_object_class_tplt_params(m_os,type);
+  m_os<<"  & otype_reference;\n";
+  // constructors
+  m_os<<"\t"<<n->cpp_name()<<"()\n\t{\n\t\t/*never called */\n";
+  m_os<<"\t};\n";
+  // Missing copy constructor
+  //m_os<<"\t"<<n->cpp_name()<<"";
+  m_os<<"\t"<<n->cpp_name()<<"(const "<<n->cpp_name()<<"";
+  m_Gen.gen_object_class_tplt_params(m_os,type);
+  m_os<<" &o);"<<std::endl;
+  // Destructor
+  m_os<<"\t~"<<n->cpp_name()<<"()\n\t{};\n";
+  
+  //m_os<<"\tvirtual I"<<n->cpp_name()<<" *Create()\n\t{\n";
+  m_os<<"\tstatic otype *Create()\n\t{\n";
+  if (m_Gen.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\"Create ";
+    m_os<<n->cpp_name()<<" %s\",typeid(this).name());\n";
+  }
+  m_os<<"\t\totype *o = new otype";
+  m_os<<"();\n";
+  if (has_optional())
+    m_os<<"\t\tmemset(&o->m,0x00,sizeof(struct _present)) ;\n";
+  m_os<<"\t\treturn o;\n\t};\n";
+  
+  m_os<<"\totype_reference";
+  m_os<<"\toperator =(asn1::Object &_c)\n\t{\n";
+
+  if (m_Gen.with_source_debug())
+  {
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\" "<<n->cpp_name()<<" operator %s = %s\"\n";
+    m_os<<"\t\t\t\t\t,typeid(this).name()\n";
+    m_os<<"\t\t\t\t\t,typeid(_c).name());\n";
+  }
+  m_os<<"\t\treturn *this;\n";
+  m_os<<"\t};\n";
+
+  m_os<<"\tvirtual otype *clone() const\n\t{\n";
+  if (m_Gen.with_source_debug())
+    m_os<<"\t\tASN1_BER_LOG_DEBUG(\"Clone "<<n->cpp_name()<<"\");\n";
+  m_os<<"\t\treturn new otype(*this);\n\t}\n";
+  // generate optionnals
+  gen_printf();
+  // 
+  cghcdtplt cga(m_os,m_Gen);
+  for_each( m_classdef.begin()
+          , m_classdef.end()
+          , cga);
+
+  m_os<<"\tprotected:\n";
+
+  for_each( m_classdef.begin()
+          , m_classdef.end()
+          , gen_iattr(m_os,m_Gen,true));         
+  m_os<<"};\n"<<std::endl;
+
+}
+
+//
+void cghpph_classdef::gen_printf()
+{
+  std::string          structName;
+  asn1::node::iterator it;
+  asn1::classdef       *type   = &m_classdef;
+  asn1::node           *ident  = m_classdef.identifier();
+  asn1::constructed    *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  it = type->begin();
+  
+  structName = ident->cpp_name();
+  if (m_Gen.with_source_comment())
+    m_os<<"\t// display function\n"; 
+  m_os<<"\tvirtual void printf(std::ostream &os) const\n\t{\n";
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::node *ltype = (*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_TF:   /* Type Field                   */
+        if ( (ltype->flags().m_flags & asn1::node::marker_type::FL_OPTIONAL) ) 
+        {
+          m_os<<"\t\tif (m.present"<<fieldname<<")"<<std::endl;
+        } 
+        m_os<<"\t\t\tos<<\""<<ltype->cpp_name();
+        m_os<<" : \"<<m"<<fieldname<<"<<std::endl;\n";
+        break;
+     default:
+     ;
+    }  
+  
+  }  
+  m_os<<"\t};\n\n";
+}
+
+// generate codec part
+void cghpph_classdef::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_classdef::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_classdef;
+  //
+  m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  //
+  if (m_classdef.tagged()) {
+        if ( m_Gen.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+        {
+          m_os<<scope<<"\tvirtual void encode_preamble_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual void encode_epilogue_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual int decode_preamble_ber(asn1::streams::ber &ctx);"<<std::endl;
+          m_os<<scope<<"\tvirtual int decode_epilogue_ber(asn1::streams::ber &ctx);"<<std::endl;
+        }
+  }
+}
+
+//
+void cghpph_classdef::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_classdef::generate_jer()
+{
+}
+
+//
+void cghpph_classdef::generate_xer()
+{
+}
+
+
+/**
+ *
+ */ 
+void cghpph_classdef::gen_objectset()
+{
+  asn1::node           *ident     = m_classdef.identifier();  
+  asn1::classdef       *type      = &m_classdef; 
+  asn1::node::iterator it         = (type)->begin();
+  std::string          structName = ident->cpp_name();
+
+  m_os<<"\n//\n// Objectset struct\n//\n";
+  m_os<<"struct "<<structName<<"Set\n";
+  m_os<<"{\n";
+  m_os<<"\t"<<structName<<"Set *m_next;\n";
+  m_os<<"\tI"<<structName<<"   *m_object;\n";
+  m_os<<"};\n";
+}
+
+
+
+/**
+ * Helper to travers class fields in template ...
+ */ 
+class cghcditf : public node_visitor<cghcditf>
+{
+  protected:
+    std::ostream    &m_os;
+    std::string     fieldname;
+    generate_header &m_gen;
+  public:
+    cghcditf(std::ostream &_os,generate_header &h)
+      : m_os(_os),m_gen(h)
+    {}
+    // used by foreach
+    void operator ()(asn1::node *n)
+    {
+      std::string fieldname = n->cpp_name();
+      fieldname[0] = '_';
+      visit(n);
+    }
+#define ASN1_CLASSFIELD_TYPE(cls,code) \
+    void visit_##cls(asn1::cls *f) code 
+
+ASN1_CLASSFIELD_TYPE(classfield_tf,{
+  fieldname = f->cpp_name();
+  fieldname[0] = '_';
+  m_os<<"\t// "<<f->cpp_name()<<" type_id="<<f->type_id()();
+  m_os<<" type "<<f->cpp_name()<<std::endl;
+  // new encode / decode
+  m_os<<"\tvirtual void encode"<<fieldname<<"(asn1::context &ctx)\n\t{\n";
+  if (m_gen.with_source_debug())
+    m_os<<"\t\tstd::cout<<\"encode_"<<fieldname<<"\"<<std::endl;\n";
+  m_os<<"\t};\n";
+
+  m_os<<"\tvirtual int decode"<<fieldname<<"(asn1::context &ctx)\n\t{\n";
+  if (m_gen.with_source_debug())
+  {
+    m_os<<"\t\tstd::cout<<\"decode_"<<fieldname;
+    m_os<<"\"<<std::endl;\n";
+  }
+  m_os<<"\t\treturn 0;\n\t};\n\n";
+})
+ASN1_CLASSFIELD_TYPE(classfield_ftvf,{
+  fieldname = f->cpp_name();
+  fieldname[0] = '_';
+  asn1::typenode *ftvf_type = f->get_type();  
+  std::string strtype;
+  m_gen.type2cppstring(ftvf_type,strtype);
+  m_os<<std::endl;
+  m_os<<"\tbool "<<fieldname.substr(1)<<"Equals(";
+  m_os<<strtype<<" &_v)\n\t{\n";
+    m_os<<"\t\treturn _v == "<<fieldname<<";\n"; 
+    m_os<<"\t};\n";
+    // Add getter
+    m_os<<std::endl;
+    m_os<<"\t"<<strtype<<" &get_"<<fieldname.substr(1)<<"(";
+    m_os<<")\n\t{\n";
+    m_os<<"\t\treturn "<<fieldname<<";\n"; 
+    m_os<<"\t};\n";
+})   
+ASN1_CLASSFIELD_TYPE(classfield_vtvf,{})   
+ASN1_CLASSFIELD_TYPE(classfield_ftvsf,{
+  fieldname = f->cpp_name();
+  fieldname[0] = '_';
+  m_os<<std::endl;
+  m_os<<"\tSet<"<<f->get_type()->cpp_name()<<"> &get";
+  m_os<<fieldname;
+  m_os<<"()\n\t{\n";
+  m_os<<"\t\treturn "<<fieldname;
+  m_os<<";\n\t};\n\n";
+}) 
+ASN1_CLASSFIELD_TYPE(classfield_vtvsf,{}) 
+ASN1_CLASSFIELD_TYPE(classfield_of,{})       
+ASN1_CLASSFIELD_TYPE(classfield_osf,{})     
+
+
+protected:
+};
+
+
+/**
+*
+*/ 
+void cghpph_classdef::gen_interface()
+{
+asn1::node           *ident     = m_classdef.identifier();  
+asn1::classdef       *type      = &m_classdef; 
+asn1::node::iterator it         = (type)->begin();
+std::string          structName = ident->cpp_name();
+
+m_os<<"\n//\n// Interface I"<<structName;
+m_os<<"\n//\n";
+m_os<<"class I"<<structName<<" : public asn1::Object\n{\n"<<std::endl;;
+
+// constructors
+m_os<<"\tpublic:\n";
+m_os<<"\ttypedef asn1::intrusive_ptr<I"<<structName<<"> ptr;\n";
+m_os<<"\tI"<<structName<<"() {};\n";
+m_os<<"\t~I"<<structName<<"() {};\n\n";
+//m_os<<"\tvirtual I"<<structName<<" *Create() =0;\n";
+m_os<<"\tvirtual I"<<structName<<" *clone() const = 0;\n";
+m_os<<"\n";
+gen_optional();
+m_os<<"\tvirtual size_t get_data_length() const { return 0 ; };";
+m_os<<"\tvirtual size_t get_length() const { return 0 ; };";
+m_os<<"\tvirtual const asn1::tag &tag() const\n\t{\n";
+m_os<<"\t\tstatic asn1::tag t = asn1::tag(0,0);\n";
+m_os<<"\t\treturn t;\n\t};\n"<<std::endl;
+// generate optionnals
+
+
+  cghcditf  iav(m_os,m_Gen);
+  for_each( m_classdef.begin()
+          , m_classdef.end()
+          , iav);
+  // Add protected members
+  m_os<<"\tprotected:\n";
+  for_each( m_classdef.begin()
+          , m_classdef.end()
+          , gen_iattr(m_os,m_Gen));      
+  m_os<<"};\n"<<std::endl;
+  m_os<<"\ntypedef asn1::intrusive_ptr<I"<<structName<<">";
+  m_os<<" I"<<structName<<"_ptr;\n\n";
+}
+
+/**
+ *
+ */ 
+bool cghpph_classdef::should_generate() 
+{
+  asn1::node::iterator it         = m_classdef.begin();
+  bool should = false;
+
+  for ( ; it != m_classdef.end()
+        ; ++it)
+  {
+    asn1::node *field = (*it);
+    if (field->type_id()() == asn1::type::ASN1_CLASSFIELD_TF)
+    {
+      should = true;
+      break;
+    }    
+  } 
+  return should;
+}
+
+
+/**
+ *
+ */ 
+bool cghpph_classdef::has_optional()
+{
+  return m_classdef.opt_size() > 0;
+}
+
+/**
+ *
+ */ 
+void cghpph_classdef::gen_optional()
+{
+  asn1::node             *ident     = m_classdef.identifier();  
+  asn1::classdef         *type      = &m_classdef; 
+  asn1::node::iterator   it         = (type)->begin();
+  bool                   opt        = false;
+  std::list<std::string> l;
+  
+  for ( ; it != type->end(); ++it)
+  {
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    if ( ((*it)->flags().m_flags & asn1::node::marker_type::FL_OPTIONAL) )
+    {
+      l.push_back(fieldname);
+    }
+  }
+
+  if ( l.size() > 0 )
+  {
+    m_os<<"\tstruct _present\n\t{\n";
+    for (std::list<std::string>::const_iterator it = l.begin()
+            ; it != l.end()
+            ; ++it)
+    {
+      m_os<<"\t\tunsigned present"<<(*it)<<" : 1;\n";
+    }
+    m_os<<"\t} m;\n";
+  }
+}
+
+/**
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/libgen/cpp/cghpph_classdef.h b/libgen/cpp/cghpph_classdef.h
new file mode 100644 (file)
index 0000000..67b37f3
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef CGHPPH_CLASSDEF_H
+#define CGHPPH_CLASSDEF_H
+
+
+/**
+ *
+ */
+class cghpph_classdef : public generator_helper
+{
+  protected:
+    cghpph_classdef(const  cghpph_classdef &s) : generator_helper(s.m_os)
+                                               , m_log(s.m_log) 
+                                               , m_Gen(s.m_Gen) 
+                                               , m_classdef(s.m_classdef) {}  
+  public:
+    cghpph_classdef(generate_header &g,std::ostream &os,asn1::classdef &s) ;
+    ~cghpph_classdef();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_printf();
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+    void gen_interface();
+    
+    void gen_template();
+    //
+    // Gen Optional structure
+    void gen_optional();
+    //  Are there optional attributes ?
+    bool has_optional();
+    // Generate structure for ObjectSet of this class type
+    void gen_objectset(); 
+    // Test If need to generate code for this class 
+    // If there are no FT, probably not
+    bool should_generate();   
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::classdef     &m_classdef;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_enumerated.cpp b/libgen/cpp/cghpph_enumerated.cpp
new file mode 100644 (file)
index 0000000..6c5ecf3
--- /dev/null
@@ -0,0 +1,124 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_generator_helper.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_enumerated.h"
+
+#undef GEN_LOG_DEBUG
+#define GEN_LOG_DEBUG
+
+cghpph_enumerated::cghpph_enumerated(generate_header &g,std::ostream &os,asn1::enumerated &s)
+  : cgh_hconstruct(g,os,s) , m_enumerated(s)
+{
+}
+
+cghpph_enumerated::~cghpph_enumerated()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_enumerated::generate()
+{
+  cgh_hconstruct::generate( );
+}
+/**
+ *
+ */
+void cghpph_enumerated::generate_prolog( )
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_enumerated helper launched private "<<m_enumerated.name()<<std::endl;
+  m_os<<"struct "<<m_structName<<" : public asn1::ENUMERATED\n{\n";
+}
+
+/**
+ *
+ */
+void cghpph_enumerated::generate_ctors( )
+{
+  if (m_enumerated.tagged() )
+  {
+        if ( ! m_gencpp.is_tag_explicit(m_enumerated) )
+        {
+          asn1::node::tag_type tg = m_enumerated.tag();
+          m_os<<"\t"<<m_structName<<"(const asn1::tag &t= asn1::tag("<<tg.m_class<<","<<tg.m_value<<")) ;\n";
+        } else
+        {
+          m_os<<"\t"<<m_structName<<"(const asn1::tag &t= asn1::tag(0,10)) ;\n";
+        }
+  } else 
+  {
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t= asn1::tag(0,10)) ;\n";
+  }
+  // copy constructor 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t) ;"<<std::endl;
+  // clone
+  m_os<<"\t"<<m_structName<<"* clone();"<<std::endl;
+}
+
+/**
+ *
+ */
+void cghpph_enumerated::generate_members( )
+{
+  asn1::node::iterator it = m_enumerated.begin();
+  m_os<<"\tenum e"<< m_structName<<"  {\n";
+  for (; it != m_enumerated.end();++it)
+  {
+    asn1::value *num = (*it)->value();
+    if (it != m_enumerated.begin() )
+      m_os<<",\n";
+    m_os<<"\t\t"<<(*it)->cpp_name()<<" ";
+    
+    if ( num != NULL)
+    {
+      m_os<<" = "<<(num)->m_integer;
+    }
+  }
+  m_os<<"\n"<<"\t};\n";
+}
+
+/**
+ *
+ */
+void cghpph_enumerated::generate_operators( )
+{
+  m_os<<"\t"<<m_structName<<"& operator = (unsigned int v ) ; "<<std::endl;
+  m_os<<"\tbool operator ==(const "<<m_structName<<" &v) const ;\n";
+  m_os<<"\tbool operator ==(const e"<<m_structName<<" v) const ;\n";
+  m_os<<"\tbool operator !=(const e"<<m_structName<<" v) const ;\n";
+}
+/**
+ *
+ */
+void cghpph_enumerated::generate_printf( )
+{
+  
+  m_os<<"\tvirtual void printf(std::ostream &os) const;"<<std::endl;
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+  m_os<<" &s"<<");"<<std::endl; 
+}
+
+// generate codec part
+
+//
+void cghpph_enumerated::generate_ber()
+{
+}
+
diff --git a/libgen/cpp/cghpph_enumerated.h b/libgen/cpp/cghpph_enumerated.h
new file mode 100644 (file)
index 0000000..98c8bea
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_ENUMERATED_H
+#define CGHPPH_ENUMERATED_H
+
+
+/**
+ *
+ */
+class cghpph_enumerated : public cgh_hconstruct
+{
+  protected:
+    cghpph_enumerated(const  cghpph_enumerated &s) : cgh_hconstruct(s.m_gencpp,s.m_os,s.m_c)
+                                     , m_enumerated(s.m_enumerated) {}  
+  public:
+    cghpph_enumerated(generate_header &g,std::ostream &os,asn1::enumerated &s) ;
+    ~cghpph_enumerated();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() { };
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() { };
+    //
+    virtual void generate_jer() { };
+    //
+    virtual void generate_xer() { };
+
+  protected:   
+    virtual void generate_prolog( );
+    virtual void generate_ctors( );
+    virtual void generate_members( );
+    virtual void generate_operators( );
+    virtual void generate_printf( );
+  protected:  
+    asn1::enumerated   &m_enumerated;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_import.cpp b/libgen/cpp/cghpph_import.cpp
new file mode 100644 (file)
index 0000000..7f60f4e
--- /dev/null
@@ -0,0 +1,234 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "cghpph_import.h"
+
+
+cghpph_import::cghpph_import(generate_header &g,std::ostream &os,asn1::import &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_import(s)
+  , m_log(g.logger())  
+{
+}
+
+cghpph_import::~cghpph_import()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_import::generate()
+{
+  asn1::node::iterator items,end;
+  
+  m_os<<"// cghpph_import helper launched "<<std::endl;
+  asn1::node::iterator it = m_import.begin();
+
+  items = m_import.begin();
+  end   = m_import.end();
+  // Loop over items and check if OPERATION is imported
+  for (  items  = m_import.begin()
+       ; items != end
+       ; ++items)
+  {
+    //os <<"//#include \""<<(*it)->identifier_cpp_name()<<"/"<<(*items)->cpp_name()<<".h\" /*item "<<(*items)->name()<<"*/\n";
+    if (std::string("OPERATION").compare((*items)->name()) == 0 )
+    {
+      m_os<<"#include \"rtasn1/asn1_rose.h\"\n";
+    }
+  }
+  if (std::string("Remote-Operations-Useful-Definitions")
+     .compare(m_import.identifier()->name()))
+    m_os<<"#include \""<<m_import.identifier()->cpp_name()<<".h\"\n";
+  
+  gen_forward_decl();
+}
+//
+void cghpph_import::gen_printf(const std::string &_scope)
+{
+  std::string          structName;
+  std::string          scope("");
+  asn1::node::iterator lit;
+  asn1::node           *type   = &m_import;
+
+}
+
+// generate codec part
+void cghpph_import::generate_per()
+{
+  std::string scope;
+  //
+}
+
+//
+void cghpph_import::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_import;
+  //
+}
+
+//
+void cghpph_import::generate_oer()
+{
+  //
+  std::string scope;
+}
+
+//
+void cghpph_import::generate_jer()
+{
+}
+
+//
+void cghpph_import::generate_xer()
+{
+}
+
+/**
+ * private structures are generated before the current on.
+ *  outside the scope of the current type.
+ *  This code could be factorized and generator level 
+ */ 
+void cghpph_import::gen_private()
+{
+    asn1::node *type = &m_import; 
+}
+/**
+ *
+ */
+void cghpph_import::gen_forward_decl()
+{
+  asn1::node::iterator items,end;
+  
+  items = m_import.begin();
+  end   = m_import.end();
+  m_os<<"namespace "<<m_import.identifier()->cpp_name()<<" {\n";
+  // Loop over items and check if OPERATION is imported
+  for (  items  = m_import.begin()
+       ; items != end
+       ; ++items)
+  {
+    asn1::node *type = NULL;
+    asn1::typeref *ref = dynamic_cast<asn1::typeref *>(*items); 
+    if (ref)
+    {
+      type = m_Gen.resolver().resolve(*ref);
+      if (type)
+      {
+        switch(type->type_id()())
+        {
+          case asn1::type::ASN1_BIT_STRING :
+          case asn1::type::ASN1_SET :
+          case asn1::type::ASN1_SEQUENCE :
+              if (type->identifier()->parameters())
+              {
+                m_os<<"// type "<<type->type_id()()<<" with param\n";
+              } else
+                m_os<<"class "<<ref->cpp_name()<<";// type "<<type->type_id()()<<"\n";
+            break;
+         case asn1::type::ASN1_OBJECTSET:
+         {
+           asn1::objectset *objs = dynamic_cast<asn1::objectset *>(type);
+           asn1::typeref   *cref = objs->get_classref();
+           m_os<<"// object set "<<objs->name()<<" cref="<<cref->name()<<std::endl;
+           m_os<<"I"<<cref->cpp_name()<<" **"<<objs->name()<<";"<<std::endl;
+         }
+         break;
+         case asn1::type::ASN1_VALUESET:
+         {
+          asn1::objectset *objs = dynamic_cast<asn1::objectset *>(type);
+           asn1::typeref   *cref = objs->get_classref();
+           m_os<<"// WRONG value set "<<objs->name()<<" its objs cref=";
+            m_os<<cref->name()<<std::endl;
+           m_os<<"extern I"<<cref->cpp_name()<<" **"<<objs->name()<<";"<<std::endl;
+
+         }
+         break;
+          case asn1::type::ASN1_REFERENCE :
+            {  
+              asn1::typeref *real_ref = dynamic_cast<asn1::typeref *>(type);
+              if (type->type_node())
+              {
+               std::cerr<<"// IMPORT TODO type "<<type->name()<<" "<<type->type_node()->cpp_name()<<std::endl;
+               //assert(0 && "??? how can that be ?");
+                //m_os<<"class "<<ref->name()<<";";
+                m_os<<"// type "<<type->type_id()()<<"\n";
+              } else if (type->identifier() && type->identifier()->parameters())
+              {
+                m_os<<"// type "<<type->type_id()()<<" with param\n";
+              } else if (real_ref && real_ref->is_objectclass())
+              {
+                m_os<<"// type "<<type->type_id()()<<" object class\n";
+              } else
+                m_os<<"class "<<ref->cpp_name()<<";// type "<<type->type_id()()<<"\n";
+            }
+          break;  
+          case asn1::type::ASN1_INTEGER :
+            if (type->meta_id()() != asn1::meta::TYPE)
+            {
+                break;
+            }
+          case asn1::type::ASN1_CHOICE :
+          case asn1::type::ASN1_OCTET_STRING :
+          case asn1::type::ASN1_ENUMERATED:
+            m_os<<"struct "<<ref->cpp_name()<<";\n";
+          break;  
+          case asn1::type::ASN1_CLASSDEF :
+          {
+            std::string cls = type->identifier()->cpp_name(); 
+            m_os<<"#ifndef TEMPLATE_CLASS_"<<cls<<"\n";  
+            m_os<<"#define TEMPLATE_CLASS_"<<cls<<"\n";  
+            if (std::string("ERROR").compare(type->identifier()->cpp_name()) == 0) 
+            {
+              m_os<<"#ifdef ERROR\n";
+              m_os<<"#undef ERROR\n";
+              m_os<<"#endif\n";
+            }
+            m_os<<"class I"<<type->identifier()->cpp_name()<<";// id="<<type->type_id()()<<"\n";
+            m_os<<"\n";
+#if 0
+           m_Gen.gen_object_class_tplt(m_os,type->identifier());
+           m_os<<"class "<<type->identifier()->cpp_name()<<";\n";
+#endif
+            m_os<<"#endif\n";
+          }
+          break;  
+          default:
+            //m_os<<"class "<<type->identifier_cpp_name()<<";";
+            m_os<<"//default FOUND "<<type->name()<<" id="<<type->type_id()()<<"\n";
+          ;
+        }
+      } else
+      {
+        m_os<<"//NOT FOUND "<<ref->name()<<"\n";
+      }
+    } else
+    {
+        m_os<<"//NOT FOUND not typeref "<<(*items)->name()<<"\n";
+    }
+
+    // Resolve symbol to figure out the kind.   
+    if (std::string("OPERATION").compare((*items)->name()) == 0 )
+    {
+    }
+  }
+  m_os<<"}\n";
+}
diff --git a/libgen/cpp/cghpph_import.h b/libgen/cpp/cghpph_import.h
new file mode 100644 (file)
index 0000000..16409ce
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef CGHPPH_IMPORT_H
+#define CGHPPH_IMPORT_H
+
+
+/**
+ *
+ */
+class cghpph_import : public generator_helper
+{
+  protected:
+    cghpph_import(const  cghpph_import &s) :  generator_helper(s.m_os)
+                                     , m_Gen(s.m_Gen) 
+                                     , m_log(s.m_log) 
+                                     , m_import(s.m_import) {}  
+  public:
+    cghpph_import(generate_header &g,std::ostream &os,asn1::import &s) ;
+    ~cghpph_import();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_private();
+    //
+    void gen_forward_decl();
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::import       &m_import;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_integer.cpp b/libgen/cpp/cghpph_integer.cpp
new file mode 100644 (file)
index 0000000..a74a82a
--- /dev/null
@@ -0,0 +1,145 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_integer.h"
+
+
+cghpph_integer::cghpph_integer(generate_header &g,std::ostream &os,asn1::integer &s)
+  : cgh_hconstruct(g,os,s) , m_integer(s)
+{
+}
+
+cghpph_integer::~cghpph_integer()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_integer::generate()
+{
+  GEN_LOG_DEBUG("INTEGER type %s ident=%s size=%ld\n"
+                    , m_integer.name().c_str()
+                    , m_integer.identifier_name().c_str()
+                    , m_integer.size());
+  cgh_hconstruct::generate();
+}
+/**
+ *
+ */
+void cghpph_integer::generate_prolog( )
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_integer helper launched "<<std::endl;
+  m_os<<"//\n// "<<m_integer.identifier_name()<<"\n//\n";
+      
+  m_os<<"struct "<<m_integer.identifier_cpp_name()<<" : public ";
+  if (m_integer.is_unsigned())
+  {
+    m_os<<"UInt64\n{\n";
+  } else
+    m_os<<"INTEGER\n{\n";
+    
+}
+
+/**
+ *
+ */
+void cghpph_integer::generate_ctors( )
+{
+  m_os<<"\t"<<m_integer.identifier_cpp_name()<<"(const asn1::tag &t = asn1::tag(";
+  if (m_integer.tagged())
+  {
+    m_os<<m_integer.tag().m_class<<","<<m_integer.tag().m_value<<",";
+    if ( m_gencpp.is_tag_explicit(m_integer) )
+    {
+      m_os<<"true";
+    }else
+      m_os<<"false";
+  } else
+  {
+    m_os<<"0,2";
+  }
+  m_os<<")) ;"<<std::endl;
+  
+}
+
+/**
+ *
+ */
+void cghpph_integer::generate_operators( )
+{
+  if (m_integer.is_unsigned())
+  {
+    m_os<<"\tvoid operator =(const unsigned long v) ;\n";
+    m_os<<"\tvoid operator =(const asn1::prim::types::UInt64 &v) ;\n";
+  } else
+  {
+    m_os<<"\tvoid operator =(const long v) ;\n";
+    m_os<<"\tvoid operator =(const asn1::prim::types::Integer &v) ;\n";
+  }
+  
+  m_os<<"\tbool operator ==(const "<<m_integer.identifier_cpp_name()<<" &v) const ;\n";
+}
+
+/**
+ *
+ */
+void cghpph_integer::generate_members( )
+{
+  if (m_integer.size() > 0)
+  {
+    asn1::node::iterator it = m_integer.begin();
+    m_os<<"\tenum e"<<m_integer.identifier_cpp_name()<<" {\n";
+    for (; it != m_integer.end() ; ++it)
+    {
+      asn1::valuetype *tv = dynamic_cast<asn1::valuetype *>(*it);
+      assert (tv != NULL);
+      if (it != m_integer.begin() )
+      {
+        m_os<<"\t\t,";
+      } else 
+        m_os<<"\t\t";
+     
+      m_os<<(*it)->cpp_name()<<" = "<<tv->value_long()<<"\n";
+    }
+    m_os<<"\t};\n"; // end of enum 
+    m_os<<"\tbool operator ==(const e"<<m_integer.identifier_cpp_name()<<" v) const ;\n";
+    m_os<<"\tvoid operator =(const e"<<m_integer.identifier_cpp_name()<<" v)  ;\n";
+  }
+
+
+}
+
+/**
+ *
+ */
+void cghpph_integer::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_integer;
+  //
+  //
+  if ( m_integer.tagged()
+       &&  m_gencpp.is_tag_explicit(m_c))
+  {
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  }
+}
+
diff --git a/libgen/cpp/cghpph_integer.h b/libgen/cpp/cghpph_integer.h
new file mode 100644 (file)
index 0000000..ca7f4d2
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_INTEGER_H__
+#define CGHPPH_INTEGER_H__
+
+
+/**
+ *
+ */
+class cghpph_integer : public cgh_hconstruct
+{
+  protected:
+    cghpph_integer(const  cghpph_integer &s) :  cgh_hconstruct(s.m_gencpp,s.m_os,s.m_c)
+                                     , m_integer(s.m_integer) {}  
+  public:
+    cghpph_integer(generate_header &g,std::ostream &os,asn1::integer &s) ;
+    ~cghpph_integer();
+    
+    // Helper functions
+    virtual void generate() ;
+    //
+    virtual void generate_ber() ;
+    // generate codec part
+    virtual void generate_per()  { };
+    //
+    virtual void generate_oer() { };
+    //
+    virtual void generate_jer() { };
+    //
+    virtual void generate_xer() { };
+  protected:
+    virtual void generate_prolog( );
+    virtual void generate_ctors( );
+    virtual void generate_members( );
+    virtual void generate_operators( );
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:  
+    asn1::integer      &m_integer;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_object.cpp b/libgen/cpp/cghpph_object.cpp
new file mode 100644 (file)
index 0000000..de4bc3a
--- /dev/null
@@ -0,0 +1,229 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "cgh_object.h"
+#include "cghpph_object.h"
+
+#undef GEN_LOG_DEBUG
+#define GEN_LOG_DEBUG
+
+cghpph_object::cghpph_object( generate_header &g
+                            , std::ostream &os
+                            , asn1::object &s
+                            , asn1::classdef &cdef)
+  : m_Gen(g)
+  , cgh_object(g,os,s,cdef)
+  //, m_object(s)
+  //,m_classdef(cdef)
+{
+}
+
+cghpph_object::~cghpph_object()
+{
+}
+
+
+/**
+ * Helper functions
+ *
+ */ 
+void cghpph_object::generate()
+{
+  asn1::node *n      = m_object.identifier();
+  asn1::node *type   = &m_object;
+  asn1::node *params = NULL;
+  std::string structName;
+  
+  //m_os<<"\n//\n// cghpph_object helper launched "<<n->name()<<std::endl;
+  gen_private();
+  // m_os<<"\n// chpph_object helper after missing "<<n->name()<<std::endl;
+  // gen_forward();
+#if 0
+    // c++11 feature forward decl
+    m_os<<"extern template class "<<m_classdef.identifier()->cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">;\n";
+#endif    
+}
+
+/**
+ * Helper functions
+ *
+ */ 
+void cghpph_object::generate_hpp()
+{
+  asn1::node *n      = m_object.identifier();
+  asn1::node *type   = &m_object;
+  asn1::node *params = NULL;
+  std::string structName;
+  
+  m_os<<"\n//\n// cghpph_object helper launched "<<n->name()<<std::endl;
+
+  // Generate template_specialisation
+  if (m_classdef.get_parent() ==  m_Gen.get_module())
+  {
+    // open current namespace    
+    m_os<<"namespace "<<m_Gen.get_module()->cpp_name()<<" {\n"; 
+    m_os<<"template <>\n";
+    m_os<<m_classdef.cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.cpp_name()<<"();\n";
+    m_os<<"}\n"; // Close current namespace   
+  } else
+  {
+    
+    // Open template namespace     
+    m_os<<"namespace "<<m_classdef.get_parent()->cpp_name()<<"\n{\n"; 
+    
+    m_os<<"template <>\n";
+    m_os<<m_classdef.identifier()->cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.identifier()->cpp_name()<<"();\n";
+    // Instanciate copy ctor
+    m_os<<"template <>\n";
+    m_os<<m_classdef.identifier()->cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<">::"<<m_classdef.identifier()->cpp_name()<<"(const ";
+    m_os<<m_classdef.identifier()->cpp_name();
+    m_os<<"<";
+    gen_template_args(true);
+    m_os<<"> &o);\n";
+
+    m_os<<"}\n"; // Close template namespace   
+  }
+
+  // typedef instantiates the template
+  m_os<<"namespace "<<m_Gen.get_module()->cpp_name()<<"\n{\n"; 
+  m_os<<"typedef ";
+  if (m_classdef.get_parent() == m_Gen.get_module() )
+  {
+    m_os<<m_classdef.cpp_name()<<"<"; 
+  } else
+  {
+    asn1::module *cdef_ns = dynamic_cast<asn1::module *>(m_classdef.get_parent());
+    m_os<<cdef_ns->cpp_name();
+    m_os<<"::"<<m_classdef.identifier()->cpp_name()<<"<";  
+  }
+  // To check for CMIP
+  gen_template_args(true);
+  m_os<<"> "<<n->cpp_name()<<";"<<std::endl;
+  m_os<<"}\n"; // Close current namespace   
+
+  //m_os<<"\n//\n// cghpph_object helper end "<<n->name()<<std::endl;
+}
+//
+void cghpph_object::gen_printf(const std::string &scope)
+{
+}
+
+// generate codec part
+void cghpph_object::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_object::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_object;
+  //
+  //
+  if (m_object.tagged())
+  {
+    if ( m_Gen.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_object::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_object::generate_jer()
+{
+}
+
+//
+void cghpph_object::generate_xer()
+{
+}
+
+void cghpph_object::gen_forward()
+{
+  asn1::node::iterator fit = m_classdef.begin(); 
+
+  for ( ; fit != m_classdef.end()
+        ; ++fit)
+  {
+    if ( (*fit)->type_id()() == asn1::type::ASN1_CLASSFIELD_TF )
+    {
+      asn1::node *type = NULL;   
+      if ( (type =  m_object.get_field((*fit)->name()) ) != NULL)
+      {   
+        if (type->get_parent() == m_Gen.get_module())  
+          m_os<<"struct "<<type->cpp_name()<<";"<<std::endl;
+      }
+    }  
+  }  
+}
+
+/**
+ * private structures are generated before the current on.
+ *  outside the scope of the current type.
+ *  This code could be factorized and generator level 
+ */ 
+void cghpph_object::gen_private()
+{
+  asn1::node::iterator fit = m_classdef.begin(); 
+
+  for ( ; fit != m_classdef.end()
+        ; ++fit)
+  {
+    if ( (*fit)->type_id()() == asn1::type::ASN1_CLASSFIELD_TF )
+    {
+      asn1::node *type = NULL;   
+      if ( (type =  m_object.get_field((*fit)->name()) ) != NULL)
+      {
+        asn1::typeref *ref = dynamic_cast<asn1::typeref *>(type);  
+        asn1::node *rtype = NULL;
+        if(ref) 
+        {
+              rtype = m_Gen.resolver().resolve(*ref);
+        } else
+        {
+            std::cerr<<"cghpph_object::gen_private type= ";
+            std::cerr<<type->name()<<" NOT TYPEREF\n";
+        }
+        if (rtype && rtype->get_parent() == m_Gen.get_module())  
+          m_Gen.gen_missing(m_os,rtype->identifier());
+      }
+    }  
+  }  
+}
diff --git a/libgen/cpp/cghpph_object.h b/libgen/cpp/cghpph_object.h
new file mode 100644 (file)
index 0000000..8909716
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef CGHPPH_OBJECT_H
+#define CGHPPH_OBJECT_H
+
+
+/**
+ *
+ */
+class cghpph_object : public cgh_object 
+{
+  protected:
+    cghpph_object(const  cghpph_object &s ) 
+           : cgh_object(s.m_Gencpp,s.m_os,s.m_object,s.m_classdef)
+           , m_Gen(s.m_Gen)
+           //, m_object(s.m_object)
+           //, m_classdef(s.m_classdef)
+    {}  
+  public:
+    cghpph_object(generate_header &g,std::ostream &os,asn1::object &s,asn1::classdef &cdef) ;
+    ~cghpph_object();
+    
+    // Helper functions
+    virtual void generate() ;
+    
+    void generate_hpp() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+    void gen_private();
+  protected:
+    void gen_forward();
+    // Generate template arguments for object
+    //void gen_template_args(bool with_scope=false); 
+  protected:  
+    generate_header      &m_Gen;
+    //asn1::object         &m_object;
+    //asn1::classdef       &m_classdef;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_octetstring.cpp b/libgen/cpp/cghpph_octetstring.cpp
new file mode 100644 (file)
index 0000000..0d56381
--- /dev/null
@@ -0,0 +1,126 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_primitive.h"
+#include "cghpph_octetstring.h"
+
+
+cghpph_octet_string::cghpph_octet_string(generate_header &g,std::ostream &os,asn1::octet_string &s)
+  :  cghpph_primitive(g,os,s) , m_octet_string(s)
+{
+}
+
+cghpph_octet_string::~cghpph_octet_string()
+{
+}
+
+
+/**
+ *
+ */
+void cghpph_octet_string::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+     m_os<<"// cghpph_octet_string helper launched "<<m_octet_string.cpp_name()<<std::endl;
+  
+  m_os<<"struct "<<m_structName<<" : public OCTET_STRING\n{\n";
+  m_os<<"\tpublic:\n";
+}
+/**
+ *
+ */
+void cghpph_octet_string::generate_ctors()
+{
+  if (m_octet_string.tagged())
+  {
+    m_os<<"\t\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(";
+    m_os<<m_octet_string.tag().m_class<<","<<m_octet_string.tag().m_value<<",";
+
+    if ( m_gencpp.is_tag_explicit(m_octet_string))
+    {
+      m_os<<"true)";
+    }else
+      m_os<<"false)";
+    m_os<<");\n";
+  } else
+  {
+    m_os<<"\t\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(0,4));\n";
+  }
+  m_os<<"\t\t~"<<m_structName<<"();\n";
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+}
+/**
+ *
+ */
+void cghpph_octet_string::generate_operators()
+{
+  // Assignment
+  m_os<<"\t"<<m_structName<<" & operator =(const "<<m_structName<<" &t"<<") ;\n";
+  
+  m_os<<"\t"<<m_structName<<" & operator =(const asn1::prim::types::String &t"<<") ;\n";
+  
+}
+
+/**
+ *
+ */
+void cghpph_octet_string::generate_printf()
+{
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const ";
+  m_os<<m_octet_string.identifier_cpp_name()<<" &s);\n";
+}
+
+// generate codec part
+void cghpph_octet_string::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_octet_string::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_octet_string;
+  //
+  //
+  if (m_octet_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_octet_string) )
+    {
+      m_os<<scope<<"\t\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\t\tvirtual int decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_octet_string::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_octet_string::generate_jer()
+{
+}
+
+//
+void cghpph_octet_string::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cghpph_octetstring.h b/libgen/cpp/cghpph_octetstring.h
new file mode 100644 (file)
index 0000000..e164be2
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef CGHPPH_OCTETSTRING_H
+#define CGHPPH_OCTETSTRING_H
+
+
+/**
+ *
+ */
+class cghpph_octet_string : public cghpph_primitive
+{
+  protected:
+    cghpph_octet_string(const  cghpph_octet_string &s) : cghpph_primitive(s.m_gencpp,s.m_os,s.m_octet_string)
+                                     , m_octet_string(s.m_octet_string) {}  
+  public:
+    cghpph_octet_string(generate_header &g,std::ostream &os,asn1::octet_string &s) ;
+    ~cghpph_octet_string();
+    
+    // Helper functions
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    virtual void generate_operators();
+    virtual void generate_printf();
+  protected:
+    asn1::octet_string   &m_octet_string;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_oid.cpp b/libgen/cpp/cghpph_oid.cpp
new file mode 100644 (file)
index 0000000..64d5d48
--- /dev/null
@@ -0,0 +1,140 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_oid.h"
+
+
+cghpph_oid::cghpph_oid(generate_header &g,std::ostream &os,asn1::object_identifier &s)
+  :  cgh_hconstruct(g,os,s)
+  , m_oid(s)
+{
+}
+
+cghpph_oid::~cghpph_oid()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ */ 
+void cghpph_oid::generate()
+{
+  cgh_hconstruct::generate( );
+}
+
+/**
+ *
+ */
+void cghpph_oid::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_oid helper launched "<<std::endl;
+  m_os<<"struct "<<m_structName<<" : public asn1::OBJECT_IDENTIFIER\n{\n";
+}
+
+/**
+ *
+ */
+void cghpph_oid::generate_ctors()
+{
+  m_os<<"\t"<<m_structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_oid.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_oid) )
+    {
+      m_os<<m_oid.tag().m_class<<","<<m_oid.tag().m_value<<",true));\n";
+    } else
+    {
+      m_os<<m_oid.tag().m_class<<","<<m_oid.tag().m_value<<",false));\n";
+    }
+  }else
+    m_os<<"0,"<<m_oid.primitive_tag()<<")) ;\n";
+  
+    
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+  // copy assignment  
+  m_os<<"\t"<<m_structName<<" & operator =(const "<<m_structName<<" &t"<<") ;\n";
+  
+  m_os<<"\t"<<m_structName<<" & operator =(const "<<m_oid.cpp_name()<<" &t"<<") ;\n";
+  
+}
+
+/**
+ *
+ */
+void cghpph_oid::generate_operators()
+{
+  // equal operator
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+//
+void cghpph_oid::generate_printf()
+{
+  std::string          structName;
+  asn1::object_identifier   *type   = &m_oid;
+  asn1::node                *ident  = m_oid.identifier();
+  asn1::node                *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  
+  if (m_oid.is_private())
+  {
+    structName = type->cpp_name();
+  } else
+    structName = ident->cpp_name();
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<") ;\n";
+}
+
+// generate codec part
+void cghpph_oid::generate_per()
+{
+}
+
+//
+void cghpph_oid::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_oid;
+  //
+  if (  m_oid.tagged()
+        && m_gencpp.is_tag_explicit(m_oid) )
+    {
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+}
+
+//
+void cghpph_oid::generate_oer()
+{
+}
+
+//
+void cghpph_oid::generate_jer()
+{
+}
+
+//
+void cghpph_oid::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cghpph_oid.h b/libgen/cpp/cghpph_oid.h
new file mode 100644 (file)
index 0000000..a3dde42
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef CGHPPH_OBJECT_IDENTIFIER_H
+#define CGHPPH_OBJECT_IDENTIFIER_H
+
+
+/**
+ *
+ */
+class cghpph_oid : public cgh_hconstruct
+{
+  protected:
+    cghpph_oid(const  cghpph_oid &s) :  cgh_hconstruct(s.m_gencpp,s.m_os,s.m_oid)
+                                     , m_oid(s.m_oid) {}  
+  public:
+    cghpph_oid(generate_header               &g
+                   ,std::ostream            &os
+                   ,asn1::object_identifier &s) ;
+    ~cghpph_oid();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_prolog();
+    
+    virtual void generate_printf();
+    
+    virtual void generate_ctors();
+    
+    virtual void generate_operators();
+  protected:  
+    asn1::object_identifier   &m_oid;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_primitive.cpp b/libgen/cpp/cghpph_primitive.cpp
new file mode 100644 (file)
index 0000000..c0dabcb
--- /dev/null
@@ -0,0 +1,155 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_primitive.h"
+
+
+cghpph_primitive::cghpph_primitive( generate_header &g
+                           , std::ostream &os
+                           , asn1::primitive &s)
+  : cghpp_helper(g,os)
+  , m_primitive(s)
+  , m_structName("")
+{
+
+  assert(m_primitive.type_id()() >= asn1::type::ASN1_ANY
+        && m_primitive.type_id()() < asn1::type::ASN1_STRING_ObjectDescriptor  ); 
+  if (m_primitive.is_private())
+  {
+    m_structName = s.cpp_name();
+  } else
+    m_structName = s.identifier_cpp_name();
+
+}
+
+cghpph_primitive::~cghpph_primitive()
+{
+}
+
+void cghpph_primitive::generate_prolog()
+{
+  assert(m_primitive.type_id()() >= asn1::type::ASN1_ANY
+        && m_primitive.type_id()() < asn1::type::ASN1_STRING_ObjectDescriptor  ); 
+
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_primitive helper launched "<<std::endl;
+  m_os<<"struct "<<m_structName<<" : public "<<m_primitive.cpp_name()<<"\n{\n";
+}
+
+void cghpph_primitive::generate_ctors()
+{
+  m_os<<"\t"<<m_structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_primitive.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_primitive))
+    {
+      m_os<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value<<",true)) ;\n";
+    } else
+    {
+      m_os<<m_primitive.tag().m_class<<","<<m_primitive.tag().m_value<<",false)) ;\n";
+    }
+  }else
+    m_os<<"0,"<<m_primitive.primitive_tag()<<")) ;\n";
+  
+    
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+  // clone 
+  m_os<<"\tvirtual "<<m_structName<<" *clone() ;\n";
+  
+  //
+}
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_primitive::generate()
+{
+  generate_prolog();
+  generate_descriptor();
+
+  generate_ctors();  
+  //
+  generate_ber();
+
+  generate_operators();
+  
+  generate_printf();
+  m_os<<"};\n";
+  
+}
+/**
+ *
+ */
+void cghpph_primitive::generate_operators()
+{
+  // equal operator
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+
+/**
+ *
+ */
+void cghpph_primitive::generate_printf()
+{
+  asn1::node           *ident  = m_primitive.identifier();
+  asn1::node           *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<") ;\n";
+
+}
+
+// generate codec part
+void cghpph_primitive::generate_per()
+{
+}
+
+//
+void cghpph_primitive::generate_ber()
+{
+  //
+  if (m_primitive.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_primitive))
+    {
+      //
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_primitive::generate_oer()
+{
+}
+
+//
+void cghpph_primitive::generate_jer()
+{
+}
+
+//
+void cghpph_primitive::generate_xer()
+{
+}
diff --git a/libgen/cpp/cghpph_primitive.h b/libgen/cpp/cghpph_primitive.h
new file mode 100644 (file)
index 0000000..2d77059
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_PRIMITIVE_H
+#define CGHPPH_PRIMITIVE_H
+
+
+/**
+ *
+ */
+class cghpph_primitive : public cghpp_helper
+{
+  protected:
+    cghpph_primitive(const  cghpph_primitive &s) :  cghpp_helper(s.m_gencpp,s.m_os)
+                                                , m_structName(s.m_structName) 
+                                                , m_primitive(s.m_primitive) {}  
+  public:
+    cghpph_primitive(generate_header &g,std::ostream &os,asn1::primitive &s) ;
+    ~cghpph_primitive();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    virtual void generate_operators();
+    virtual void generate_printf();
+  protected:  
+    asn1::primitive    &m_primitive;
+    std::string         m_structName;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_real.cpp b/libgen/cpp/cghpph_real.cpp
new file mode 100644 (file)
index 0000000..01c644a
--- /dev/null
@@ -0,0 +1,118 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_primitive.h"
+#include "cghpph_real.h"
+
+
+cghpph_real::cghpph_real(generate_header &g,std::ostream &os,asn1::real &s)
+  : cghpph_primitive(g,os,s)
+  , m_real(s)
+{
+}
+
+cghpph_real::~cghpph_real()
+{
+}
+
+
+/**
+ *
+ */
+void cghpph_real::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_real helper launched "<<std::endl;
+  
+  assert(m_real.type_id()() == asn1::type::ASN1_REAL); 
+  
+  m_os<<"\n//\n// struct "<<m_structName<<"\n//\n";
+  m_os<<"struct "<<m_structName<<" : public "<<m_real.cpp_name()<<"\n{\n";
+}
+/**
+ *
+ */
+void cghpph_real::generate_ctors()
+{
+  // Initial ctor
+  m_os<<"\t"<<m_structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_real.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_real) )
+    {
+      m_os<<m_real.tag().m_class<<","<<m_real.tag().m_value<<",true));\n";
+    } else
+    {
+      m_os<<m_real.tag().m_class<<","<<m_real.tag().m_value<<",false));\n";
+    }
+  }else
+    m_os<<"0,1)) ;\n";
+  
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+    
+}
+/**
+ *
+ */
+void cghpph_real::generate_printf()
+{
+  asn1::node           *ident  = m_real.identifier();
+  asn1::node           *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+  if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<");";
+  m_os<<"\n";
+}
+
+// generate codec part
+void cghpph_real::generate_per()
+{
+}
+
+//
+void cghpph_real::generate_ber()
+{
+  //
+  if (m_real.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_real))
+    {
+      //
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_real::generate_oer()
+{
+  //
+}
+
+//
+void cghpph_real::generate_jer()
+{
+}
+
+//
+void cghpph_real::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cghpph_real.h b/libgen/cpp/cghpph_real.h
new file mode 100644 (file)
index 0000000..ba3cbf8
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_REAL_H
+#define CGHPPH_REAL_H
+
+
+/**
+ *
+ */
+class cghpph_real : public cghpph_primitive
+{
+  protected:
+    cghpph_real(const  cghpph_real &s) :  cghpph_primitive(s)
+                                     , m_real(s.m_real) {}  
+  public:
+    cghpph_real(generate_header &g,std::ostream &os,asn1::real &s) ;
+    ~cghpph_real();
+    
+    // Helper functions
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+
+    // loop over the attributes of SEQUENCE or CHOICE
+    // and check if there are some type of SEQUENCE or CHOICE
+    // launch generation for these types first.
+  protected:
+    void generate_prolog();
+    void generate_printf();
+    void generate_ctors();
+  protected:  
+    asn1::real         &m_real;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_sequence.cpp b/libgen/cpp/cghpph_sequence.cpp
new file mode 100644 (file)
index 0000000..59a8dfa
--- /dev/null
@@ -0,0 +1,337 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_sequence.h"
+
+
+cghpph_sequence::cghpph_sequence(generate_header &g,std::ostream &os,asn1::sequence &s)
+  : cgh_hconstruct(g,os,s)
+  , m_seq(s) 
+{
+}
+
+cghpph_sequence::~cghpph_sequence()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the sequence does not always have an identifier. Examples
+ *    -  SEQUENCE OF SEQUENCE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, SEQUENCE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_sequence::generate()
+{
+  if ( ! m_gencpp.add_symbol(m_structName,&m_seq) )
+  {
+    m_os<<"// Structure already in map, skip\n";
+    return;
+  }
+
+  cgh_hconstruct::generate();
+
+  if (m_gencpp.with_source_comment())
+    m_os<<"/* end cghpph_sequence "<<m_structName<<"*/"<<std::endl;
+
+}
+
+/**
+ *
+ */
+void
+cghpph_sequence::generate_prolog( )
+{
+  asn1::node        *n      = m_seq.identifier();
+  asn1::constructed *params = (n) ? n->parameters() : NULL;
+  
+  if (m_gencpp.with_source_comment())
+  { 
+    m_os<<"\n//\n// cghpph_sequence helper launched ";
+    m_os<<m_structName<<"\n//"<<std::endl;
+  }
+
+  if (   n 
+      && n->parameters()
+      && m_gencpp.is_template(n->parameters()) )
+  {
+    // forward declaration
+    m_os<<"template ";
+    m_gencpp.gen_template_signature(m_os,params);
+    m_os<<" struct "<<m_structName<<" ;\n";
+    m_os<<"template ";
+    m_gencpp.gen_template_signature(m_os,params);
+    m_os<<"\nstd::ostream & operator<<(std::ostream &os,const "<<m_structName;
+    m_gencpp.gen_template_params(m_os,params);
+    m_os<<" &s) ;\n";
+
+    m_os<<"//"<<__FUNCTION__<<" parameterized\n";
+    m_os<<"template<";
+    for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+    {
+        if (p != params->begin())
+          m_os<<",";
+        m_os<<"typename "<<(*p)->cpp_name();
+    }
+    m_os<<"> "<<std::endl;
+  }
+  m_os<<"struct "<<m_structName<<" : public asn1::types::sequence_type\n";
+  m_os<<"{\n";
+}
+
+/**
+ *
+ */
+void
+cghpph_sequence::generate_ctors( )
+{
+  asn1::node        *n      = m_seq.identifier();
+  asn1::constructed *params = (n) ? n->parameters() : NULL;
+
+  // Constructor
+  if (m_seq.tagged() )
+  {
+    if ( ! m_gencpp.is_tag_explicit(m_seq) )
+    {
+      asn1::node::tag_type tg = m_seq.tag();
+      m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag("<<tg.m_class<<","<<tg.m_value<<",true))";
+    } else
+    {
+      asn1::node::tag_type tg = m_seq.tag();
+      m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag("<<tg.m_class<<","<<tg.m_value<<",true))";
+    }
+  } else
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(0,16,true))";
+  
+  m_os<<" ;\n";
+  // Copy constructor 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName;
+  
+  // parameterized constructor
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<" &t) ;\n";
+  // Destructor 
+  //m_os<<scope<<"\t//virtual ~"<<structName<<"();\n";
+  
+  // Clone
+  m_os<<"\tvirtual "<<m_structName;;
+  if (params && m_gencpp.is_template(params))
+  {
+    m_gencpp.gen_template_params(m_os,params);
+  }
+  m_os<<" *clone();\n";
+  
+}
+
+/**
+ *
+ */
+void
+cghpph_sequence::generate_operators( )
+{
+  if (m_gencpp.with_ber())
+  {
+    m_os<<"\tvirtual size_t get_data_length() const;\n";
+  }
+
+  // == operator 
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+
+/**
+ *
+ */
+void
+cghpph_sequence::generate_members( )
+{
+  std::string       scope("");
+  asn1::node        *n      = m_seq.identifier();
+  asn1::constructed *params = (n) ? n->parameters() : NULL;
+  // Attribute Members
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"\t//Member attributes\n";
+  }
+  for ( asn1::node::iterator lit = m_seq.begin()
+      ; lit != m_seq.end() ; lit++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+    m_gencpp.gen_composite_attribute( m_os,scope,*f
+                                 , (n != NULL)?n->parameters():NULL);
+  }
+  
+  m_os<<"\n";
+  // For PARAMETERS ObjectSet CLASSES generates 
+  gen_members( );
+  //
+  gen_optionals();
+}
+
+
+/**
+ * See If there is a way to have a common class
+ * for this 
+ * If I'm private, I also need to get parameters from parent classes example
+ *  ReturnResult {OPERATION:Operations} ::= {
+ *     result ::= sequence {
+ *
+ *     }
+ *  }
+ */ 
+void 
+cghpph_sequence::gen_members()
+{
+  std::set<asn1::node *> parameterset;      
+  asn1::node *ident            = m_seq.identifier();
+  asn1::parameters *params     = dynamic_cast<asn1::parameters *>(ident->parameters());
+  /* Collect all parameters  */
+  asn1::node::node_list lst;
+  m_seq.path2module(lst);
+  for (asn1::node::iterator lit = lst.begin()
+       ; lit != lst.end()
+        ; ++lit)
+  {
+    if ( (*lit)->identifier() && (*lit)->identifier()->parameters())
+    {
+      asn1::parameters *_p = dynamic_cast<asn1::parameters *>( (*lit)->identifier()->parameters()); 
+      parameterset.insert(_p->begin(),_p->end());
+    }
+  }
+  if (params)
+  {
+      parameterset.insert(params->begin(),params->end());
+  }  
+  /**/
+  if ( parameterset.size() >0 )
+  {
+    for (std::set<asn1::node *>::iterator it = parameterset.begin();
+       it != parameterset.end();
+       ++it)
+    {
+      asn1::parameter *p = dynamic_cast<asn1::parameter *>(*it);
+      if (asn1::node *g = p->get_governor())
+      {
+        asn1::typeref *objr = dynamic_cast<asn1::typeref *>(g);      
+        if (objr)
+        {
+          asn1::node *obj     = m_gencpp.resolver().resolve(*objr);
+          asn1::module *m     = dynamic_cast<asn1::module *>(obj->get_parent()); 
+          m_os<<"\t// "<<g->name()<<" "<<p->name()<<std::endl;
+          if (!objr->is_simple())
+          {
+            m_os<<"\t"<<m->cpp_name()<<"::I"<<g->name()<<" **"<<p->name()<<";"<<std::endl;
+          }
+        }else
+        {
+          m_os<<"\t// "<<g->name()<<" "<<p->name()<<std::endl;
+        }
+      }
+    }
+  }
+}
+
+
+//
+void cghpph_sequence::generate_printf( )
+{
+  
+  asn1::node *n      = m_seq.identifier();
+  asn1::node *params = (n ) ? n->parameters() :NULL;
+#if 0 
+  if (n != NULL) 
+  {
+    if (m_seq.is_private())
+    {
+      structName = m_seq.cpp_name();  
+    } else
+      structName = n->cpp_name();  
+    params = n->parameters();
+  } else
+  {
+    // Anonymous structure
+    structName = m_seq.cpp_name();  
+  }
+#endif
+  m_os<<"\tvirtual void printf(std::ostream &os) const;\n";
+
+  m_os<<"\tfriend std::ostream &operator << ";
+  if (params && m_gencpp.is_template(params))
+    m_os<<" <>";
+  m_os<<"(std::ostream &os,const ";
+  m_os<<m_structName;  
+
+  if (n && n->parameters() && m_gencpp.is_template(n->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,n->parameters());
+  }
+  m_os<<" &s"<<")";
+  m_os<<";\n";
+}
+
+
+/**
+ *
+ */
+void cghpph_sequence::generate_ber()
+{
+  std::string scope;   
+  //
+  m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+  m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  //
+  if ( m_seq.tagged() 
+      && m_gencpp.is_tag_explicit(m_seq) )
+  {
+          m_os<<"\tvirtual void encode_preamble_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<"\tvirtual void encode_epilogue_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<"\tvirtual int decode_preamble_ber(asn1::streams::ber &ctx);"<<std::endl;
+          m_os<<"\tvirtual int decode_epilogue_ber(asn1::streams::ber &ctx);"<<std::endl;
+  }
+}
+
+/**
+ *
+ */
+void cghpph_sequence::gen_optionals()
+{
+  static const char *typ[] = {"unsigned char","unsigned short","unsigned int","unsigned long","unsigned long long"};   
+  int i = 0;
+  long count = 0;  
+  int l = m_seq.opt_size();
+  long bits = 1<<(m_seq.opt_size()-1);
+  while ( l > 0)
+  {
+    i++; l  = l / 8;
+  }
+  if (i == 0)
+    return;
+  m_os<<"\n\t//Optional bit mask "<<i<<"\n";
+  m_os<<"\tstd::bitset<"<<m_seq.opt_size()<<">\tbit_mask;\n";
+  m_os<<"\tenum {\n";
+  for ( asn1::sequence::OptionalIterator it = m_seq.opt_begin()
+      ; it != m_seq.opt_end()
+      ; ++it)
+  {
+    m_os<<"\t\t";        
+    if (it != m_seq.opt_begin())
+         m_os<<",";  
+    m_os<<(*it)->cpp_name()<<"_present\t = "<<count<<std::endl;
+    count++;
+  }
+  m_os<<"\t};\n";
+}
diff --git a/libgen/cpp/cghpph_sequence.h b/libgen/cpp/cghpph_sequence.h
new file mode 100644 (file)
index 0000000..78d8f45
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef CGHPPH_SEQUENCE_H
+#define CGHPPH_SEQUENCE_H
+
+
+/**
+ *
+ */
+class cghpph_sequence : public cgh_hconstruct
+{
+  protected:
+    cghpph_sequence(const  cghpph_sequence &s) 
+           : cgh_hconstruct(s.m_gencpp,s.m_os,s.m_c)
+             , m_seq(s.m_seq)
+  {}     
+  public:
+    cghpph_sequence(generate_header &g,std::ostream &os,asn1::sequence &s) ;
+    ~cghpph_sequence();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() {};
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() {};
+    //
+    virtual void generate_jer() {};
+    //
+    virtual void generate_xer() {};
+  protected:
+    virtual void generate_prolog() ;
+    virtual void generate_ctors() ;
+    virtual void generate_operators() ;
+    virtual void generate_members() ;
+    virtual void generate_printf();
+  protected:
+    // Generate bit mask for optional flags
+    void gen_optionals();
+    void gen_members();
+  protected:     
+    asn1::sequence     &m_seq;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_sequenceof.cpp b/libgen/cpp/cghpph_sequenceof.cpp
new file mode 100644 (file)
index 0000000..fb720dd
--- /dev/null
@@ -0,0 +1,163 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "cghpph_sequenceof.h"
+
+
+cghpph_sequenceof::cghpph_sequenceof( generate_header &g
+                           , std::ostream &os
+                           , asn1::sequence_of &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_seqof(s)
+  , m_log(g.logger())  
+{
+}
+
+cghpph_sequenceof::~cghpph_sequenceof()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_sequenceof::generate()
+{
+  asn1::node *ns     = NULL;
+  asn1::node *type   = &m_seqof;
+  asn1::typenode *seqof_type = m_seqof.get_eltype();
+  asn1::node *params = NULL;
+  std::string structName,eltype;
+  std::string scope("");
+  
+  if (m_Gen.with_source_comment())
+    m_os<<"// cghpph_sequenceof helper launched "<<std::endl;
+
+  assert(m_seqof.type_id()() == asn1::type::ASN1_SEQUENCE_OF
+        ); 
+  structName = m_seqof.identifier_cpp_name();
+
+  if (m_Gen.type_in_imports(seqof_type,&ns))
+  {
+    eltype = ns->cpp_name() + "::" + seqof_type->cpp_name();
+  } else
+    eltype = seqof_type->cpp_name();
+  m_os<<"struct "<<structName<<" : public asn1::Seq<"<<eltype<<">\n{\n";
+
+  //
+  // Initial ctor
+  m_os<<"\t"<<structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_seqof.tagged())
+  {
+    if ( m_Gen.tag_mode(&m_seqof) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<m_seqof.tag().m_class<<","<<m_seqof.tag().m_value<<",true)) ;\n";
+    } else
+    {
+      m_os<<m_seqof.tag().m_class<<","<<m_seqof.tag().m_value<<",false)) ;\n";
+    }
+  }else {
+    m_os<<"0,"<<"16)) ;\n";
+  }
+    
+  // copy 
+  m_os<<"\t"<<structName<<"(const "<<structName<<" &t"<<") ;\n";
+  // clone 
+  m_os<<"\tvirtual "<<structName<<" *clone() ;\n";
+  //
+  m_os<<"\tinline "<<structName<<" & operator =(const "<<structName<<" &c)\n";
+  m_os<<"\t{ Seq<"<<eltype<<">::operator =(c); return *this; };\n";
+  generate_ber();
+  // equal operator
+  m_os<<scope<<"\tbool operator ==(const "<<structName<<" &_c);\n";
+  
+  gen_printf();
+  m_os<<"};\n";
+  
+}
+//
+void cghpph_sequenceof::gen_printf()
+{
+  std::string          structName;
+  std::string          scope("");
+  asn1::node           *type   = &m_seqof;
+  asn1::node           *ident  = m_seqof.identifier();
+  asn1::node           *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  
+  if (m_seqof.is_private())
+  {
+    structName = type->cpp_name();
+  } else
+    structName = ident->cpp_name();
+  m_os<<scope<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<structName;
+    if (ident->parameters() && m_Gen.is_template(ident->parameters()))
+  {
+    m_Gen.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<") ;\n";
+
+}
+
+// generate codec part
+void cghpph_sequenceof::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_sequenceof::generate_ber()
+{
+  std::string scope;
+  asn1::node *type   = &m_seqof;
+  //
+  if (m_seqof.tagged())
+  {
+    if ( m_Gen.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      //
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_sequenceof::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_sequenceof::generate_jer()
+{
+}
+
+//
+void cghpph_sequenceof::generate_xer()
+{
+}
diff --git a/libgen/cpp/cghpph_sequenceof.h b/libgen/cpp/cghpph_sequenceof.h
new file mode 100644 (file)
index 0000000..aea2174
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_SEQUENCEOF_H
+#define CGHPPH_SEQUENCEOF_H
+
+
+/**
+ *
+ */
+class cghpph_sequenceof : public generator_helper
+{
+  protected:
+    cghpph_sequenceof(const  cghpph_sequenceof &s) :  generator_helper(s.m_os)
+                                     , m_Gen(s.m_Gen) 
+                                     , m_log(s.m_log) 
+                                     , m_seqof(s.m_seqof) {}  
+  public:
+    cghpph_sequenceof(generate_header &g,std::ostream &os,asn1::sequence_of &s) ;
+
+    ~cghpph_sequenceof();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_printf();
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::sequence_of  &m_seqof;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_set.cpp b/libgen/cpp/cghpph_set.cpp
new file mode 100644 (file)
index 0000000..0b2c297
--- /dev/null
@@ -0,0 +1,134 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cgh_hconstruct.h"
+#include "cghpph_set.h"
+
+
+
+/**
+ *
+ */
+cghpph_set::cghpph_set(generate_header &g,std::ostream &os,asn1::set &s)
+  : cgh_hconstruct(g,os,s)
+  , m_set(s)
+{
+}
+
+cghpph_set::~cghpph_set()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_set::generate()
+{
+  cgh_hconstruct::generate() ;
+}
+
+/**
+ *
+ */
+void cghpph_set::generate_prolog( )
+{
+  if (m_gencpp.with_source_comment() )
+    m_os<<"// cghpph_set helper launched "<<std::endl;
+  m_os<<"struct "<<m_structName<<" : asn1::types::sequence_type\n{\n";
+}
+/**
+ *
+ */
+void cghpph_set::generate_ctors( )
+{
+  // Missing constructors
+  if (m_set.tagged())
+  {
+    asn1::node::tag_type lt = m_set.tag();
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag("<<lt.m_class<<","<<lt.m_value<<",true)) ;"<<std::endl;
+  } else
+    m_os<<"\t"<<m_structName<<"(const asn1::tag &t = asn1::tag(0,17,true)) ;"<<std::endl;
+}
+/**
+ *
+ */
+void cghpph_set::generate_operators( )
+{
+  // equal operator
+  m_os<<"\tbool operator ==("<<m_structName<<" &_c);\n";
+}
+
+/**
+ *
+ */
+void cghpph_set::generate_members( )
+{
+  std::string  scope("");
+  asn1::node  *n      = m_set.identifier();
+  // Loop over the attributes
+  for ( asn1::node::iterator it = m_set.begin()
+      ; it != m_set.end() ; it++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    m_gencpp.gen_composite_attribute(m_os,scope,*f,(n != NULL)?n->parameters():NULL);
+    m_os<<"\n";
+  }
+}
+/**
+ *
+ */
+void cghpph_set::generate_printf( )
+{
+  asn1::node::iterator lit;
+  asn1::node          *ident  = m_set.identifier();
+  asn1::constructed   *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  lit = m_set.begin();
+#if 0 
+  if (m_set.is_private())
+  {
+    structName = type->cpp_name();
+  } else
+    structName = ident->cpp_name();
+#endif
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<" ) ;";
+
+}
+
+// generate codec part
+void cghpph_set::generate_ber()
+{
+  //
+  m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+  m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+  //
+  if ( m_set.tagged()
+      &&  m_gencpp.is_tag_explicit(m_set))
+  {
+          m_os<<"\tvirtual void encode_preamble_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<"\tvirtual void encode_epilogue_ber(asn1::context &ctx);"<<std::endl;
+          m_os<<"\tvirtual int decode_preamble_ber(asn1::streams::ber &ctx);"<<std::endl;
+          m_os<<"\tvirtual int decode_epilogue_ber(asn1::streams::ber &ctx);"<<std::endl;
+  }
+}
diff --git a/libgen/cpp/cghpph_set.h b/libgen/cpp/cghpph_set.h
new file mode 100644 (file)
index 0000000..e7b815d
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef CGHPPH_SET_H
+#define CGHPPH_SET_H
+
+
+/**
+ *
+ */
+class cghpph_set : public cgh_hconstruct
+{
+  protected:
+    cghpph_set(const  cghpph_set &s) :  cgh_hconstruct(s.m_gencpp,s.m_os,s.m_c)
+                                     , m_set(s.m_set) {}
+  public:
+    cghpph_set(generate_header &g,std::ostream &os,asn1::set &s) ;
+    ~cghpph_set();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() { };
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() { };
+    //
+    virtual void generate_jer() { };
+    //
+    virtual void generate_xer() { };
+  protected:
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    virtual void generate_members();
+    virtual void generate_operators();
+    virtual void generate_printf();
+  protected:  
+    asn1::set          &m_set;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_setof.cpp b/libgen/cpp/cghpph_setof.cpp
new file mode 100644 (file)
index 0000000..df19262
--- /dev/null
@@ -0,0 +1,165 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cgcpp_helper.h"
+#include "cghpph_setof.h"
+
+
+cghpph_setof::cghpph_setof( generate_header &g
+                           , std::ostream &os
+                           , asn1::set_of &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_setof(s)
+  , m_log(g.logger())  
+{
+}
+
+cghpph_setof::~cghpph_setof()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_setof::generate()
+{
+  asn1::node *ns     = NULL;
+  asn1::node *type   = &m_setof;
+  asn1::typenode *setof_type = m_setof.get_eltype();
+  asn1::node *params = NULL;
+  std::string structName,eltype;
+  std::string scope("");
+  
+  if (m_Gen.with_source_comment())
+    m_os<<"// cghpph_setof helper launched "<<std::endl;
+
+  assert(m_setof.type_id()() == asn1::type::ASN1_SET_OF
+        ); 
+  structName = m_setof.identifier_cpp_name();
+
+  if (m_Gen.type_in_imports(setof_type,&ns))
+  {
+    eltype = ns->cpp_name() + "::" + setof_type->cpp_name();
+  } else
+    eltype = setof_type->cpp_name();
+  m_os<<"struct "<<structName<<" : public asn1::Set<"<<eltype<<">\n{\n";
+
+  //
+  // Initial ctor
+  m_os<<"\t"<<structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_setof.tagged())
+  {
+    if ( m_Gen.tag_mode(&m_setof) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      m_os<<m_setof.tag().m_class<<","<<m_setof.tag().m_value<<",true)) ;\n";
+    } else
+    {
+      m_os<<m_setof.tag().m_class<<","<<m_setof.tag().m_value<<",false)) ;\n";
+    }
+  }else {
+    m_os<<"1,"<<"17)) ;\n";
+  }
+  /*ctor from one element type */
+  m_os<<"\t"<<structName<<"(const  "<<eltype<<" &T);\n";
+
+    
+  // copy 
+  m_os<<"\t"<<structName<<"(const "<<structName<<" &t"<<") ;\n";
+  // clone 
+  m_os<<"\tvirtual "<<structName<<" *clone() ;\n";
+  //
+  m_os<<"\tinline "<<structName<<" & operator =(const "<<structName<<" &c)\n";
+  m_os<<"\t{ Set<"<<eltype<<">::operator =(c); return *this; };\n";
+  generate_ber();
+  // equal operator
+  m_os<<scope<<"\tbool operator ==(const "<<structName<<" &_c);\n";
+  
+  gen_printf();
+  m_os<<"};\n";
+  
+}
+//
+void cghpph_setof::gen_printf()
+{
+  std::string          structName;
+  std::string          scope("");
+  asn1::node           *type   = &m_setof;
+  asn1::node           *ident  = m_setof.identifier();
+  asn1::node           *params = ident->parameters();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  //assert(m_setof.is_private());
+  if (m_setof.is_private())
+  {
+    structName = type->cpp_name();
+  } else
+    structName = ident->cpp_name();
+  m_os<<scope<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<structName;
+    if (ident->parameters() && m_Gen.is_template(ident->parameters()))
+  {
+    m_Gen.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<") ;\n";
+
+}
+
+// generate codec part
+void cghpph_setof::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_setof::generate_ber()
+{
+  asn1::node *type   = &m_setof;
+  //
+  if (m_setof.tagged())
+  {
+    if ( m_Gen.tag_mode(type) == asn1::node::tag_type::TM_EXPLICIT)
+    {
+      //
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_setof::generate_oer()
+{
+  //
+  std::string scope;
+  m_os<<scope<<"\tvirtual void encode_oer(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_oer(asn1::context &ctx);"<<std::endl;
+}
+
+//
+void cghpph_setof::generate_jer()
+{
+}
+
+//
+void cghpph_setof::generate_xer()
+{
+}
diff --git a/libgen/cpp/cghpph_setof.h b/libgen/cpp/cghpph_setof.h
new file mode 100644 (file)
index 0000000..05214ea
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef CGHPPH_SETOF_H
+#define CGHPPH_SETOF_H
+
+
+/**
+ *
+ */
+class cghpph_setof : public generator_helper
+{
+  protected:
+    cghpph_setof(const  cghpph_setof &s) :  generator_helper(s.m_os)
+                                     , m_Gen(s.m_Gen) 
+                                     , m_log(s.m_log) 
+                                     , m_setof(s.m_setof) {}  
+  public:
+    cghpph_setof(generate_header &g,std::ostream &os,asn1::set_of &s) ;
+
+    ~cghpph_setof();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_printf();
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::set_of       &m_setof;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_string.cpp b/libgen/cpp/cghpph_string.cpp
new file mode 100644 (file)
index 0000000..50a73d8
--- /dev/null
@@ -0,0 +1,143 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_primitive.h"
+#include "cghpph_string.h"
+
+
+cghpph_string::cghpph_string( generate_header &g
+                           , std::ostream &os
+                           , asn1::primitive &s)
+  : cghpph_primitive(g,os,s)
+  , m_string(s)
+{
+}
+
+cghpph_string::~cghpph_string()
+{
+}
+
+
+/**
+ *
+ */
+void cghpph_string::generate_prolog()
+{
+  if (m_gencpp.with_source_comment())
+    m_os<<"// cghpph_string helper launched "<<std::endl;
+
+  assert(m_string.type_id()() >= asn1::type::ASN1_STRING
+        && m_string.type_id()() < asn1::type::ASN1_STRING_ObjectDescriptor  ); 
+
+  m_os<<"struct "<<m_structName<<" : public "<<m_string.cpp_name()<<"\n{\n";
+}
+
+/**
+ *
+ */
+void cghpph_string::generate_ctors()
+{
+  m_os<<"\t"<<m_structName<<"(const  asn1::tag &t = asn1::tag(";
+  if (m_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_string))
+    {
+      m_os<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true)) ;\n";
+    } else
+    {
+      m_os<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",false)) ;\n";
+    }
+  }else
+    m_os<<"0,"<<m_string.primitive_tag()<<")) ;\n";
+  
+  // Two other ctors
+  m_os<<"\t"<<m_structName<<"(const std::string &s);\n";  
+  // copy 
+  m_os<<"\t"<<m_structName<<"(const "<<m_structName<<" &t"<<") ;\n";
+  
+  m_os<<"\t"<<m_structName<<"(const "<<m_string.cpp_name()<<" &c,";
+  m_os<<"const  asn1::tag &t = asn1::tag(";
+  if (m_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_string) )
+    {
+      m_os<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",true)) ;\n";
+    } else
+    {
+      m_os<<m_string.tag().m_class<<","<<m_string.tag().m_value<<",false)) ;\n";
+    }
+  }else
+    m_os<<"0,"<<m_string.primitive_tag()<<")";
+  
+  m_os<<") ;\n";
+  //  = copy assignement 
+  m_os<<"\t"<<m_structName<<" &operator =(const "<<m_string.cpp_name()<<" &c);\n"; 
+  m_os<<"\t"<<m_structName<<" &operator =(const std::string &c);\n"; 
+  m_os<<"\t"<<m_structName<<" &operator =(const char *c);\n"; 
+  // clone
+  m_os<<"\tvirtual "<<m_structName<<" *clone();\n"; 
+  
+}
+
+/**
+ *
+ */
+void cghpph_string::generate_printf()
+{
+  asn1::node           *ident  = m_string.identifier();
+  /*
+   * Try to handler sequence of sequence 
+   */
+  
+  m_os<<"\tfriend std::ostream &operator <<(std::ostream &os,const "<<m_structName;
+    if (ident->parameters() && m_gencpp.is_template(ident->parameters()))
+  {
+    m_gencpp.gen_template_params(m_os,ident->parameters());
+  }
+  m_os<<" &s"<<") ;\n";
+
+}
+
+// generate codec part
+void cghpph_string::generate_per()
+{
+}
+
+//
+void cghpph_string::generate_ber()
+{
+  if (m_string.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(m_string) )
+    {
+      //
+      m_os<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+}
+
+//
+void cghpph_string::generate_oer()
+{
+}
+
+//
+void cghpph_string::generate_jer()
+{
+}
+
+//
+void cghpph_string::generate_xer()
+{
+}
+
diff --git a/libgen/cpp/cghpph_string.h b/libgen/cpp/cghpph_string.h
new file mode 100644 (file)
index 0000000..e748d50
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef CGHPPH_STRING_H
+#define CGHPPH_STRING_H
+
+
+/**
+ *
+ */
+class cghpph_string : public cghpph_primitive
+{
+  protected:
+    cghpph_string(const  cghpph_string &s) :  cghpph_primitive(s.m_gencpp,s.m_os,s.m_string)
+                                     , m_string(s.m_string) {}  
+  public:
+    cghpph_string(generate_header &g,std::ostream &os,asn1::primitive &s) ;
+    ~cghpph_string();
+    
+    // Helper functions
+
+    virtual void generate_prolog();
+    virtual void generate_ctors();
+    //virtual void generate_operators() {};
+    virtual void generate_printf();
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:  
+    asn1::primitive    &m_string;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_typeref.cpp b/libgen/cpp/cghpph_typeref.cpp
new file mode 100644 (file)
index 0000000..9141746
--- /dev/null
@@ -0,0 +1,332 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "asn1_gen_codec_cpp.h"
+#include "cghpp_helper.h"
+#include "cghpph_typeref.h"
+
+
+cghpph_typeref::cghpph_typeref(generate_header &g,std::ostream &os,asn1::typeref &s)
+  :  cghpp_helper(g,os) , m_typeref(s)
+{
+}
+
+cghpph_typeref::~cghpph_typeref()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_typeref::generate()
+{
+  asn1::node *n      = m_typeref.identifier();
+  asn1::node *type   = &m_typeref;
+  asn1::node *params = NULL;
+  std::string structName;
+  
+  assert( n!= NULL); 
+  if (m_gencpp.with_source_comment())
+  {
+    m_os<<"// cghpph_typeref helper launched ";
+    m_os<<n->name()<<std::endl;
+  }
+  if (m_typeref.is_simple())
+  {
+    if (m_gencpp.with_source_comment())
+      m_os<<"// cghpph_typeref simple "<<std::endl;
+    //generate_simple();
+    cghpp_helper::generate();
+  } else if (m_typeref.is_objectclass())
+  {
+    m_os<<"// cghpph_typeref object class"<<std::endl;
+    generate_objectclass();
+  } else 
+  {
+    assert(0);  
+  }
+}
+
+/**
+ *
+ */
+void cghpph_typeref::generate_prolog( )
+{
+  std::string refName;
+  asn1::node *ns;
+
+  if (m_gencpp.type_in_imports(&m_typeref,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+m_typeref.cpp_name();
+  } else
+  {
+    refName   = m_typeref.cpp_name();
+  }
+  m_os<<"//\nclass "<<m_typeref.identifier_cpp_name()<<" : public ";
+  m_os<<refName<<"\n{\n";
+  m_os<<"  public:\n";
+}
+
+/**
+ *
+ */
+void cghpph_typeref::generate_ctors( )
+{
+  gen_simple_ctors();
+}
+
+/**
+ *
+ */
+void cghpph_typeref::generate_operators( )
+{
+  m_os<<"\n";
+  m_os<<"\tbool operator==("<<m_typeref.identifier_cpp_name()<<" &o);\n";
+  m_os<<"\n";
+
+  generate_simple();
+}
+//
+//
+//
+void cghpph_typeref::generate_simple()
+{
+  asn1::node *ns        = NULL;
+  asn1::node *n         = m_typeref.identifier();
+  asn1::typeref *type   = &m_typeref;
+  std::string type_name = type->cpp_name();     
+  std::string refName   = type->cpp_name();     
+       
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();
+  } else
+  {
+    refName   = type->cpp_name();
+  }
+
+  //generate_ber();
+  // If its the simple
+  if ( !type->tagged())
+  {
+     // Process untagged elements
+     asn1::node *params = type->parameters();
+     if (m_gencpp.type_in_imports(type,&ns) ) 
+     {
+       // imported case
+       if (type->meta_id()() == asn1::meta::OBJECTCLASS)
+       {
+         m_os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+       } else if (std::string("OPERATON").compare(type->cpp_name())==0)
+       {
+         m_os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+       } else
+       {
+         //m_os<<"\t"<<ns->cpp_name()<<"::";
+         //m_os<<type->cpp_name()<<" ";
+       }
+     } else if (std::string("TYPE_IDENTIFIER").compare(type->cpp_name())==0)
+     {
+        m_os<<" /* def"<<type->cpp_name()<<"*/INTEGER ";
+      
+     } else 
+     {
+        // internal case 
+         if (m_gencpp.with_source_comment())
+         { 
+           m_os<<" /* def no import, has constraints "<<type->has_constraints();
+           m_os<<" */ ";
+         }
+     }
+  }
+}
+//
+//
+//
+void
+cghpph_typeref::gen_simple_ctors()
+{
+  asn1::node *ns        = NULL;
+  asn1::node *n         = m_typeref.identifier();
+  asn1::typeref *type   = &m_typeref;
+  std::string type_name = n->cpp_name();     
+  std::string refName   = type->cpp_name();     
+  std::list<asn1::node *> refs;
+  
+  m_gencpp.reference_chaine(type,refs);
+       
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();     
+  } 
+  if (type->tagged())
+  {
+    /**
+     * When tagged explicit, may be build object with tag
+     *  from referenced type which needs to be used to
+     *  decode what follows
+     */ 
+    m_os<<"\t"<<type_name<<"(const asn1::tag &_t";
+    m_os<<" = asn1::tag(";
+    m_os<<type->tag().m_class<<","<<type->tag().m_value<<")";
+    m_os<<" ) ;"<<std::endl;
+  } else
+  {
+    m_os<<"\t"<<type_name<<"( ) ;"<<std::endl;
+    m_os<<"\t"<<type_name<<"( const asn1::tag &t) ;"<<std::endl;
+  }
+
+  m_os<<"\t"<<type_name<<"(const "<<type_name<<"&_c) ;"<<std::endl;
+  // Check Type of Initial type
+#if 1
+  if ( refs.size()>0 && 
+       refs.back()->type_id()() == asn1::type::ASN1_CHOICE)
+  {
+    m_os<<"\t"<<type_name<<"(unsigned int i, const asn1::tag &t) ;"<<std::endl;
+  }
+#endif
+  // Add an operator
+  m_os<<"\t"<<type_name<<" &operator =(const "<<refName<<" &_v);\n"; 
+}
+
+/**
+ *
+ * In order to resolve object class references we need 
+ * the resolver.  The resolver should be able to return 
+ * the appropriate object class. Except for TYPE-IDENTIFIER which is
+ * built  in.
+ */
+void 
+cghpph_typeref::generate_objectclass()
+{
+  asn1::node *n       = m_typeref.identifier();
+  asn1::typeref *type = &m_typeref;
+  asn1::objectclass_reference &_ref  = m_typeref.get_objectclass();
+
+  /* TYPE-IDENTIFIER&TYPE*/
+  if (m_typeref.is_type_identifier())
+  {
+    if (type->has_constraints())
+    {
+      // Try to find the constraint type value  
+      m_os<<"//\ntypedef "<<type->cpp_name()<<" "<<n->cpp_name()<<";";
+      m_os<<"\n"<<std::endl;
+    } else
+    {
+       // Without constraint it should be a template
+      m_os<<"//\nERROR TI Shall be template"<<type->cpp_name()<<n->cpp_name()<<" ";
+      m_os<<"\n"<<std::endl;
+    }
+  } else 
+  {
+    // Use the resolver to figure out what to do.
+    m_os<<"//cghpph_typeref::generate_objectclass TODO ";
+    m_os<<n->cpp_name()<<" ::= ";
+    m_os<<type->cpp_name();
+    m_os<<" Ref="<<_ref.name();
+    if (n->parameters())
+    {
+      m_os<<" TYPE with parameters don't generate code ";;  
+    }
+    if (m_typeref.act_parameters())
+    {
+      m_os<<" REF WITH PARAMETERS !!!";  
+    }
+    m_os<<"\n"<<std::endl;
+    asn1::node *real_type = 
+      m_gencpp.resolver().resolve(m_typeref);
+    if (real_type)
+    {
+      m_os<<"// FOUND REAL TYPE "<<real_type->cpp_name()<<std::endl;  
+      m_os<<"typedef I"<<type->cpp_name()<<" I"<<n->cpp_name()<<";";
+      m_os<<"\n"<<std::endl;
+    }
+  }
+}
+//
+void cghpph_typeref::gen_printf(const std::string &scope)
+{
+}
+
+// generate codec part
+void cghpph_typeref::generate_per()
+{
+  std::string scope;
+  //
+  m_os<<scope<<"\tvirtual void encode_per(asn1::context &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode_per(asn1::context &ctx);"<<std::endl;
+}
+
+/**
+ *
+ * TODO I think signature of the functions should be asn1::streams::ber &ctx and not
+ *   asn1::context    
+ */ 
+void cghpph_typeref::generate_ber()
+{
+  std::string scope;
+  asn1::node *ns        = NULL;
+  asn1::typeref *type   = &m_typeref;
+  std::string type_name = m_typeref.identifier()->cpp_name();     
+  std::string refName   = type->cpp_name();     
+  std::list<asn1::node *> refs;
+  
+  m_gencpp.reference_chaine(type,refs);
+       
+  if (m_gencpp.type_in_imports(type,&ns) ) 
+  {
+    refName   = ns->cpp_name()+"::"+type->cpp_name();     
+  } 
+  //
+  //
+  if (m_typeref.tagged())
+  {
+    if ( m_gencpp.is_tag_explicit(*type) )
+    {
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int decode(asn1::context &ctx);"<<std::endl;
+    } else 
+    {
+      m_os<<scope<<"\tvirtual void encode(asn1::context &ctx);"<<std::endl;
+      m_os<<scope<<"\tvirtual int  decode(asn1::context &ctx);"<<std::endl;
+    }
+  }
+  // What do I define if there is no tag ?
+}
+
+//
+void cghpph_typeref::generate_oer()
+{
+  //
+  std::string scope;
+  //m_os<<scope<<"\tvirtual void encode_oer(asn1::codecs::oer &ctx);"<<std::endl;
+  //m_os<<scope<<"\tvirtual int  decode_oer(asn1::codecs::oer &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual void encode(asn1::codecs::oer &ctx);"<<std::endl;
+  m_os<<scope<<"\tvirtual int  decode(asn1::codecs::oer &ctx);"<<std::endl;
+}
+
+//
+void cghpph_typeref::generate_jer()
+{
+}
+
+//
+void cghpph_typeref::generate_xer()
+{
+}
+
+
diff --git a/libgen/cpp/cghpph_typeref.h b/libgen/cpp/cghpph_typeref.h
new file mode 100644 (file)
index 0000000..c5602d5
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef CGHPPH_TYPEREF_H
+#define CGHPPH_TYPEREF_H
+
+
+/**
+ *
+ */
+class cghpph_typeref : public cghpp_helper
+{
+  protected:
+    cghpph_typeref(const  cghpph_typeref &s) :  cghpp_helper(s.m_gencpp,s.m_os)
+                                     , m_typeref(s.m_typeref) {}  
+  public:
+    cghpph_typeref(generate_header &g,std::ostream &os,asn1::typeref &s) ;
+    ~cghpph_typeref();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    void gen_printf(const std::string &scope);
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    virtual void generate_prolog() ;
+    virtual void generate_ctors() ;
+    virtual void generate_operators() ;
+  protected:
+    // Internal generation functions 
+    void generate_simple() ;
+    void gen_simple_ctors() ;
+    void generate_external_type() {} ;
+    void generate_external_value() {} ;
+    // This method will be used to deal with
+    // TYPE-IDENTIFIER and OBJECT CLASS 
+    void generate_objectclass() ;
+    void gen_objectclass_ctors() {} ;
+  protected:  
+    asn1::typeref        &m_typeref;
+};
+
+#endif
diff --git a/libgen/cpp/cghpph_value.cpp b/libgen/cpp/cghpph_value.cpp
new file mode 100644 (file)
index 0000000..b8c51c4
--- /dev/null
@@ -0,0 +1,77 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <assert.h>
+#include <string>
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "asn1_generator_helper.h"
+#include "cgcpp_helper.h"
+#include "cghpph_value.h"
+
+
+cghpph_value::cghpph_value( generate_header &g
+                    , std::ostream &os
+                    , asn1::value &s)
+  : m_Gen(g)
+  , generator_helper(os)
+  , m_value(s)
+  , m_log(g.logger())
+{
+}
+
+cghpph_value::~cghpph_value()
+{
+}
+
+
+/** Helper functions
+ *
+ *  It seems that the choice does not always have an identifier. Examples
+ *    -  SEQUENCE OF CHOICE {}
+ *    -  Test ::= CHOICE {  toto INTEGER, CHOICE { } }
+ *    these sequences are anonymous definitions ...  
+ */ 
+void cghpph_value::generate()
+{
+  asn1::node *n      = m_value.identifier();
+  asn1::node *type   = &m_value;
+  asn1::node *params = NULL;
+  std::string structName;
+  std::string scope("");
+  
+  if (m_Gen.with_source_comment())
+    m_os<<"// cghpph_value helper launched "<<std::endl;
+
+}
+//
+void cghpph_value::gen_printf()
+{
+}
+
+// generate codec part
+void cghpph_value::generate_per()
+{
+}
+
+//
+void cghpph_value::generate_ber()
+{
+}
+
+//
+void cghpph_value::generate_oer()
+{
+}
+
+//
+void cghpph_value::generate_jer()
+{
+}
+
+//
+void cghpph_value::generate_xer()
+{
+}
diff --git a/libgen/cpp/cghpph_value.h b/libgen/cpp/cghpph_value.h
new file mode 100644 (file)
index 0000000..29f9bec
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef CGHPPH_VALUE_H
+#define CGHPPH_VALUE_H
+
+
+/**
+ *
+ */
+class cghpph_value : public generator_helper
+{
+  protected:
+    cghpph_value(const  cghpph_value &s) :  generator_helper(s.m_os)
+                                     , m_Gen(s.m_Gen) 
+                                     , m_log(s.m_log) 
+                                     , m_value(s.m_value) {}  
+  public:
+    cghpph_value(generate_header &g,std::ostream &os,asn1::value &s) ;
+    ~cghpph_value();
+    
+    // Helper functions
+    virtual void generate() ;
+
+    // generate codec part
+    virtual void generate_per() ;
+    //
+    virtual void generate_ber() ;
+    //
+    virtual void generate_oer() ;
+    //
+    virtual void generate_jer() ;
+    //
+    virtual void generate_xer() ;
+  protected:
+    void gen_printf();
+  protected:  
+    std::fstream       &m_log;    
+    generate_header    &m_Gen;
+    asn1::value        &m_value;
+};
+
+#endif
diff --git a/libgen/js/asn1_gen_js.cpp b/libgen/js/asn1_gen_js.cpp
new file mode 100644 (file)
index 0000000..b1fa524
--- /dev/null
@@ -0,0 +1,1049 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <cassert>
+#include "asn1_generator.h"
+#include "asn1_gen_js.h"
+#include "asn1_visitor.h"
+
+/**
+ *  Default Cosntructor
+ */
+generate_js::generate_js(asn1::module *n) : asn1::generator(n) 
+{}
+
+generate_js::generate_js(asn1::module *n,asn1::module::modules_type &m) 
+  : asn1::generator(n,m)
+{
+}
+
+/**
+ * Helper function to look for missing prototypes
+ */
+void  generate_js::gen_missing(std::ostream &os,asn1::node *n)
+{
+  asn1::node::iterator it;
+  //= std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+  switch (n->type_id()())
+  {
+    case asn1::type::ASN1_SEQUENCE_OF:
+    case asn1::type::ASN1_SET_OF:
+      {
+#ifdef DEBUG
+        std::cout<<"Find sequence of or set of:\n";
+#endif
+        asn1::node *type = n->as_typenode()->get_eltype();
+        if  (type !=NULL)
+        {
+          if (asn1::typeref *tref = type->as_typeref()) 
+          {
+            it = std::find_if(m_module->begin(),
+                 m_module->end(),
+                 asn1::find_node(tref->get_reference()->name()));
+          } else
+          it = std::find_if(m_module->begin(),
+                 m_module->end(),
+                 asn1::find_node(type->name()));
+        } else return;
+      
+      } 
+      break;
+    case asn1::type::ASN1_SEQUENCE:
+    case asn1::type::ASN1_CHOICE:
+      {
+        asn1::constructed *cons = n->as_constructed();
+#if 1
+        std::cout<<"generate_js::"<<__FUNCTION__<<" Find choice or sequence :\n";
+        asn1::node::iterator lit = cons->begin();
+        for (; lit != cons->end() ; lit++)
+        {
+          asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+          if (asn1::typenode *tn = f->get_type()) {
+                gen_missing(os,tn);
+          }
+        }
+#endif
+      }
+        return;
+        break;
+    case asn1::type::ASN1_NULL:
+        return;
+    case asn1::type::ASN1_REFERENCE:
+    {
+      asn1::typeref *tref = n->as_typeref();
+      // Try to check references
+      if (n->parameters() != NULL)
+      {
+        asn1::constructed *params = n->parameters();
+        std::cout<<"generate_js::"<<__FUNCTION__<<" Have parameters\n";
+        for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+        {
+          std::cout<<"generate_js::"<<__FUNCTION__<<" Parameter:"<<(*p)->name()<<"\n";
+          it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node((*p)->name()));
+                
+          if (it != m_module->end())
+                  gen_missing(os,(*it));
+        }
+      }
+       //
+      if (tref->get_reference())
+      {
+        if (std::string("TYPE-IDENTIFIER::&Type").compare(tref->get_reference()->name()) == 0)
+        {
+                 asn1::constraint::iterator c = tref->constraint_begin();
+                 if ((*c)->type() == asn1::constraint::EL_TYPE)
+                 {
+                    asn1::node *ctype = (*c)->value();
+                    it = std::find_if(m_module->begin(),
+                                    m_module->end(),
+                                    asn1::find_node(ctype->name()));
+                 }
+              } else {
+                 it = std::find_if(m_module->begin(),
+                                   m_module->end(),
+                                  asn1::find_node(tref->get_reference()->name()));
+              }
+
+       } else 
+       {
+              it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+
+       }
+    }
+    break;    
+    default:
+       it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+  }
+// Found a element to be generated  
+  if ( it != m_module->end())
+  {
+    asn1::assignment *ltype = (*it)->as_assignment();
+    if ( (ltype->is_generated() != true))
+    {
+      if (ltype->get_color() == asn1::node::CL_GREEN) 
+      {
+        ltype->set_generated(true);
+        std::cout<<" gen minssing:"<<ltype->name()<<std::endl;
+        switch(ltype->get_type()->type_id()())
+        {
+          case asn1::type::ASN1_REFERENCE:
+            gen_typeref(os,ltype->get_type()->as_typeref());
+          break;
+          default:
+            gen_typedef(os,ltype->get_type());
+        }
+        ltype->set_color(asn1::node::CL_RED);
+      } else if (ltype->get_color() == asn1::node::CL_ORANGE) 
+      {
+        if (ltype->get_type()->type_id()() == asn1::type::ASN1_SEQUENCE ||
+            ltype->get_type()->type_id()() == asn1::type::ASN1_CHOICE
+        ) 
+        os<<"struct "<<ltype->cpp_name()<<";"<<std::endl;
+        ltype->set_generated(true);        
+      }else {
+        ltype->set_generated(true);
+      }
+    } 
+  }
+}
+/**
+ *
+ *
+ */
+void  generate_js::gen_const(std::ostream &os,asn1::node *type)
+{
+  switch(type->type_id()())
+  {
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    {
+      os<<"struct "<<type->identifier_cpp_name();
+      os<<" : public OBJECT_IDENTIFIER {";
+      //gen_oid_value(os,type->identifier());
+      os<<std::endl;
+    }
+    break;
+    case asn1::type::ASN1_VALUESET:
+    {
+    }
+    break;
+    case asn1::type::ASN1_INTEGER:
+    {
+      os<<"  #define "<<type->identifier_cpp_name();
+      os<<"\t "<<type->cpp_name()<<"";
+    }
+    break;
+    default:
+      std::cout<<" DEFAULT"; std::cout.flush();
+      os<<"  const "<<type->identifier_cpp_name()<<"\t\t= "<<type->cpp_name()<<";";
+        ;
+  }
+  os<<std::endl;
+
+}
+
+/**
+ *
+ *
+ */
+void 
+generate_js::gen_enumerated_printf( std::ostream &os,asn1::enumerated &n 
+                                       , const std::string &name)
+{
+  std::string indent("");
+  asn1::node::iterator it = n.begin();
+  os<<indent<<"\tprintf : function() ";
+  os<<"{\n";
+
+  for (; it != n.end(); it++)
+  {
+    if (asn1::valuetype *vt =  dynamic_cast<asn1::valuetype *>(*it))
+    {
+      os<<"\telse if (this.m_value == this.e"<<name<<"."<<(*it)->cpp_name()<<")\n";
+      os<<"\t\tError(\""<<(*it)->cpp_name()<<"\");\n";
+    } else
+    {
+      os<<"\tif (this.m_value === this.e"<<name<<"."<<(*it)->cpp_name()<<")\n";
+      os<<"\t\tError(\""<<(*it)->cpp_name()<<"\");\n";    
+    }
+  
+  }  
+  os<<"\tError(\"(\"+this.m_value+\")\");\n";
+ // os<<"\t\treturn os;\n";
+  os<<"\t}\n";
+}
+
+/**
+ *
+ *
+ */
+void generate_js::gen_enumerated( std::ostream &os,asn1::enumerated &_enum 
+                                , const std::string &name)
+{
+  asn1::enumerated *enumtype = &_enum;
+  assert(enumtype != NULL);
+  std::string indent("");
+  asn1::node::iterator it = enumtype->begin();
+  
+  os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<name<<"\",AEBW.Asn1, { ";
+  //os<<indent<<"struct "<<name<<" {\n";
+  os<<indent<<"\tconstructor : "<<"function () {this.m_value = ";
+  os<<(*it)->cpp_name()<<" ;},\n";
+  os<<indent<<"\tencode_ber  : function(ctx,Stream) ,\n";
+  os<<indent<<"\te"<<name<<":  {\n";
+  for (; it != _enum.end(); it++)
+  {
+    if (it != _enum.begin() )
+      os<<",\n";
+    os<<indent<<"\t\t"<<(*it)->cpp_name()<<" : ";
+    
+  }
+  os<<"\n"<<indent<<"\t},\n";
+  gen_enumerated_printf(os,_enum,name);
+  os<<indent<<"\n});\n";
+}
+
+//
+// gen_typeref
+//
+void generate_js::gen_typeref(std::ostream &os,asn1::typeref *type)
+{
+  std::string type_name;
+  
+  if (type ) 
+  {
+    std::cout<<"generate_js::"<<__FUNCTION__<<" "<<type->identifier_name();
+    std::cout<<" id="<<type->type_id()()<<" ";
+    
+    if (type != NULL) 
+    {
+      std::cout<<" typenode is  "<<type->name()<<" ";
+    } else 
+    {
+      std::cout<<" typenode is NULL ERROR";
+      std::cerr<<"generate_js::"<<__FUNCTION__<<" type is null\n";
+      exit(0);
+    }
+    if (type->parameters() != NULL){
+      std::cout<<" parameterized ";
+    }
+    std::cout<<std::endl;
+  }
+  if (type->get_reference()) {
+    type_name = type->cpp_name();
+  } else {
+    type_name = type->cpp_name();
+  }
+  if (type->type_id()() != asn1::type::ASN1_REFERENCE)
+  {
+    std::cout<<__FUNCTION__<<"ERROR "<<type->cpp_name()<<" type="<<type->type_id()();
+    exit(0);
+  }
+
+
+  gen_missing(os,type);
+  asn1::node *ns = NULL;
+  os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<type->identifier_cpp_name()<<"\",";
+  os<<m_module->cpp_name()<<"."<<type_name<<",null);\n";
+}
+
+
+//
+//
+//
+void generate_js::gen_typedef(std::ostream &os,asn1::typenode *type)
+{
+  if (type ) 
+  {
+    std::cout<<"gen_typedef : "<<type->identifier_name();
+    std::cout<<" id="<<type->type_id()()<<" ";
+    if (type != NULL) 
+    {
+      std::cout<<" typenode is  "<<type->name()<<" ";
+    } else 
+    {
+      std::cout<<" typenode is NULL ";
+    }
+    std::cout<<std::endl;
+    os<<"\n";
+  }
+
+  if (type != NULL)
+    switch (type->type_id()())
+    {
+      case asn1::type::ASN1_REFERENCE:
+      {
+        std::cout<<"__FUNCTION__"<<" ERROR "<<type->cpp_name()<<std::endl;
+        exit(0);
+
+      }
+      break;
+      case asn1::type::ASN1_INTEGER:
+        {
+          if (type->tagged() )
+          {
+           os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<type->cpp_name()<<"\",AEBW.Asn1.Integer,null);\n ";
+
+          } else {
+           os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<type->identifier_cpp_name()<<"";
+           os<<"\",AEBW.Asn1.Integer,null);\n";
+          }
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          asn1::sequence *seqtype = dynamic_cast<asn1::sequence *>(type);
+          std::string scope("");
+          asn1::node::iterator lit = seqtype->begin();
+          for (; lit != seqtype->end() ; ++lit)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( f->get_type() != NULL) {
+                  gen_missing(os,f->get_type());
+            }
+          }
+          gen_seq(os,scope,seqtype);
+          os<<"\n";
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE_OF:
+        {
+          asn1::node *ns = NULL;
+          asn1::typenode *sty =type->get_eltype();
+          gen_missing(os,sty);
+          if (type_in_imports(sty,&ns) )
+          {
+            os<<"AEBW.declare(\""<<m_module->cpp_name();
+            os<<"."<<type->identifier_cpp_name()<<"\",AEBW.Asn1.SequenceOf /*";
+            os<<"\t"<<ns->cpp_name()<<".";
+            os<<sty->cpp_name()<<"*/,null) ";
+          } else {
+            switch (sty->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+              {
+                std::string scope("\t");
+
+                sty->name(type->identifier_cpp_name()+"_type");
+                gen_seq(os,scope,sty->as_sequence());
+              }
+              break;
+              default:
+                if (asn1::typeref *tref = sty->as_typeref())
+                {
+                  os<<"AEBW.declare(\""<<m_module->cpp_name();
+                  os<<"."<<type->identifier_cpp_name();
+                  os<<"\",AEBW.Asn1.SequenceOf/*";
+                  os<<tref->get_reference()->cpp_name()<<"*/,null); ";
+                } else
+                {
+                  os<<"AEBW.declare(\""<<m_module->cpp_name();
+                  os<<"."<<type->identifier_cpp_name();
+                  os<<"\",AEBW.Asn1.SequenceOf /*"<<sty->cpp_name();
+                  os<<"*/,null); ";
+                }
+            }
+          }
+        }
+        break;
+      case asn1::type::ASN1_SET:
+        {
+          asn1::set *settype = dynamic_cast<asn1::set *>(type);
+          asn1::node::iterator lit = settype->begin();
+          for (; lit != settype->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( f->get_type() != NULL) {
+                  gen_missing(os,f->get_type());
+            }
+          }
+          gen_set(os,settype->identifier());
+          os<<";\n";
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SET_OF:
+        {
+          asn1::typenode *subtype =type->get_eltype();
+          gen_missing(os,subtype);
+          if (asn1::typeref *tref = subtype->as_typeref())
+                {
+                  os<<"typedef SET_OF<"<<tref->get_reference()->name()<<"> ";
+          } else
+                {
+                  os<<"typedef SET_OF<"<<subtype->cpp_name()<<"> ";
+                  }
+        }
+        break;
+      case asn1::type::ASN1_CHOICE:
+        {
+          asn1::choice *ch = dynamic_cast<asn1::choice *>(type);
+          asn1::node::iterator lit = ch->begin();
+          for (; lit != ch->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( f->get_type() != NULL) {
+              gen_missing(os,f->get_type());
+            }
+          }
+          gen_choice(os,*ch);
+          os<<";\n";
+          return;
+        }
+        break;
+      case asn1::type::ASN1_ENUMERATED:
+        {
+           //os<<"typedef ";
+            gen_enumerated( os
+                          , *type->as_enumerated()
+                          , type->identifier_cpp_name());
+        }
+        break;
+      ;
+      case asn1::type::ASN1_BIT_STRING:
+      {
+        std::cerr<<__FUNCTION__<<" BIT_STRING TODO"<<std::endl;
+        return ;
+      }
+      break;
+      default:
+       gen_missing(os,type);
+       asn1::node *ns = NULL;
+       os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<type->identifier_cpp_name()<<"";
+       //os<<"typedef ";
+       if (type_in_imports(type,&ns) ) {
+         os<<"\","<<ns->cpp_name()<<"."<<type->cpp_name()<<",null);\n";
+        } else {
+         os<<"\","<<type->cpp_name()<<",null/* default case*/);\n";
+        }
+       return;
+      ;
+    };
+
+  
+}
+
+/**
+ *
+ */
+void generate_js::gen_seq_printf(std::ostream &os,std::string &scope,asn1::sequence *type,bool priv)
+{
+  os<<scope<<"\tprintf : function() {\n";
+  os<<scope<<"\t}\n";
+
+}
+/**
+ *
+ */
+void generate_js::gen_seq( std::ostream &os
+                         , std::string &scope
+                         , asn1::sequence *type,bool priv)
+{
+  asn1::node *n = type->identifier();
+  asn1::node::iterator lit = type->begin();
+  asn1::constructed  *params = n->parameters();
+  m_Stack.push_back(n->cpp_name());
+  assert(type != NULL);
+
+  // default constructor 
+  // I should probaly push optionnal attributes and OBEJECTS in a stack and add a initializer here.
+  std::vector<asn1::node *> opt_attrs;
+  for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*lit);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL)
+    {
+      asn1::typeref *tref = attr_type->as_typeref();
+      if ( tref &&  tref->is_complex())
+      {
+          asn1::reference *r = tref->get_reference();
+          std::string lr = r->back().m_identifier;
+          opt_attrs.push_back((*it));
+      }
+    }
+  }
+  os<<scope<<"AEBW.declare(\""<<m_module->cpp_name()<<".";
+  os<<n->cpp_name()<<"\",AEBW.Asn1.Sequence, {\n";
+  // Constructor
+  os<<scope<<"\tconstructor : function "<<"()";
+  os<<" {\n";
+  if (opt_attrs.size() == 1)
+  {
+    os<<"\t\t"<<opt_attrs[0]->cpp_name()<<": \"\"";
+  } else if (opt_attrs.size() > 1)
+  {
+  }
+  
+  os<<"\t},\n";
+  // Copy constructor 
+  os<<scope<<"\tencode_ber : function(ctx,s";
+  os<<") {},\n";
+
+  for (; lit != type->end() ; lit++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*lit);
+    asn1::typenode *attr_type = f->get_type();
+    if (! f->is_extensible())
+      gen_composite_attribute(os,scope,f,n->parameters());
+  }
+  
+  gen_seq_printf(os,scope,type,priv);
+  // What is scope for here ?
+  os<<scope<<"});\n ";
+  m_Stack.pop_back();
+}
+
+
+//
+//
+//
+void generate_js::gen_template_params(std::ostream &os,asn1::node *_params)
+{
+  asn1::constructed *params = dynamic_cast<asn1::constructed *>(_params);
+  asn1::node::node_list nl;
+
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+ os<<"> ";
+}    
+//
+//
+//
+void generate_js::gen_template_signature(std::ostream &os,asn1::node *_params)
+{
+  asn1::constructed *params = dynamic_cast<asn1::constructed *>(_params);
+  asn1::node::node_list nl;
+
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" typename "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" typename "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+ os<<"> ";
+}    
+
+/**
+ *
+ *
+ */
+void generate_js::gen_choice_printf(std::ostream &os,asn1::choice *type)
+{
+  asn1::node *n= type->identifier();
+  os<<"\tprintf : function() {";
+  os<<"\n\t},\n";
+}
+
+/**
+ *
+ *
+ */
+void generate_js::gen_choice(std::ostream &os,asn1::choice &_type)
+{
+  std::string scope(""); 
+  asn1::choice *type = &_type;
+  asn1::node *n= type->identifier();
+  assert(type != NULL);
+  m_Stack.push_back(n->cpp_name());
+  std::cout<<"generate_js::gen_choice"<<std::endl;
+  
+  os<<"AEBW.declare(\""<<m_module->cpp_name()<<"."<<n->cpp_name()<<"\",AEBW.Asn1.Choice,{\n";
+  os<<"\tconstructor : function() {\n";
+  os<<"\t\tthis.kind_ = 0;},\n";
+  os<<"\tencode_ber : function(ctx,";
+  // Parameter stuff here
+  if (n->parameters() && is_template(n->parameters()))
+  {
+    gen_template_params(os,n->parameters());
+  }
+  os<<" Stream"<<") {\n";
+  os<<"\t},\n";
+  gen_choice_printf(os,type);
+  // == operator 
+  //
+  asn1::node::iterator it;
+  it = type->begin();
+  for (; it != (type)->end() ; it++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+    if (! f->is_extensible())
+      gen_composite_attribute(os,scope,f,n->parameters());
+
+  }
+  // Now add an enum tu identifie type
+  os<<"\tenums : { ";
+  asn1::node::iterator lit;
+  lit = type->begin();
+  int count = 0;
+  for (; lit != (type)->end() ; lit++)
+  {
+    os<<" typeof_"<<(*lit)->cpp_name()<<": "<<count++<<" , ";
+  }
+
+  os<<"typeof_end : "<<count<<"}"<<std::endl;
+
+  os<<"}); ";
+  m_Stack.pop_back();
+}
+
+void 
+generate_js::gen_composite_attribute_ref( std::ostream &os
+                                        , std::string &scope
+                                        , asn1::typeref *attribute
+                                        , asn1::node *_params)
+{
+  asn1::constructed *params = dynamic_cast<asn1::constructed *>(_params);
+  asn1::reference *ref = attribute->get_reference();
+  
+  if (ref->size() > 1) 
+  {
+    // find the object and folow the links ....
+    std::string rname = ref->back().m_identifier;
+    os<<"\tasn1::Object * /* GCAT "<<rname<<"*/ ";
+  } else {
+    // easy case
+    asn1::node::iterator refm = std::find_if(m_module->begin(),
+                m_module->end(),
+                asn1::find_node(ref->name()));
+    if (refm != m_module->end())
+    {
+      // Here I have the type definition. I should add
+        os<<"\t"<<ref->cpp_name();
+        if (attribute->parameters()!= NULL)
+        {
+          os<<"<";
+          for (asn1::node::iterator it = attribute->parameters()->begin(); 
+              it != attribute->parameters()->end(); ++it)
+          {
+            if (it != attribute->parameters()->begin())
+              os<<",";
+            os<<(*it)->cpp_name();
+          }
+          os<<">";
+        }
+        os<<" /*NR c="<<(*refm)->get_color()<<"*/ ";
+    } else 
+    {
+       asn1::node *ns = NULL;
+       if (type_in_imports(ref->name(),&ns) ) {
+         asn1::reference::component_const_iterator compit = ref->begin();
+         // Check first element of reference
+         if ( (*compit).type == asn1::reference::component::CAPITALS)
+         {
+           os<<"\t/* GCAT */"<<ns->cpp_name()<<"::"<<ref->name()<<" ";
+         } else
+         os<<"\t"<<ns->cpp_name()<<"::"<<ref->cpp_name()<<" /*NR 2*/ ";
+         // check if attribute has parameters
+         if (attribute->parameters() != NULL)
+         {
+           os<<"<";
+           for (asn1::node::iterator it = attribute->parameters()->begin(); it != attribute->parameters()->end(); ++it)
+           {
+             asn1::node *ns1 = NULL;
+             if (it != attribute->parameters()->begin())
+               os<<",";
+             // check namespace
+             if (type_in_imports((*it)->name(),&ns1) ) {
+               os<<ns1->cpp_name()<<"::"<<(*it)->cpp_name();
+             } else
+               os<<(*it)->cpp_name();
+           }
+           os<<">";
+
+         }
+       } else if (params) // reference in parameters of definition
+       {
+         bool found = false;
+         for (asn1::node::iterator it = params->begin()
+             ; it != params->end(); ++it )
+         {
+            if (ref->name().compare((*it)->name())== 0)
+            {
+               os<<"\t"<<(*it)->cpp_name();
+               found = true;
+            }
+            if (!found)
+             os<<" ERRORNOTPARAMS ";
+
+         }
+
+       } else
+       {
+         os<<" ERROR ";
+       }
+    }
+    
+  }
+}
+
+void 
+generate_js::gen_composite_attribute( std::ostream &os
+                                    , std::string &scope
+                                    , asn1::field *attribute
+                                    , asn1::node *params)
+{
+  asn1::typenode *attr_type = attribute->get_type();
+  assert(attr_type != NULL);
+  if (attr_type != NULL)
+  {
+    switch (attr_type->type_id()())
+    {
+      case asn1::type::ASN1_ENUMERATED:
+        {
+          gen_enumerated( os
+                        , *attr_type->as_enumerated()
+                        , attribute->cpp_name()+"_t");
+          os <<attribute->cpp_name()<<";"<<std::endl;
+        } 
+        break;
+      case asn1::type::ASN1_SET:
+        {
+          gen_set(os,attribute);
+          os<<"\t\t"<<attribute->cpp_name()<<";\n";
+        }
+        break;
+      case asn1::type::ASN1_CHOICE:
+        {
+          attr_type->name(attribute->cpp_name()+"_t");
+          //gen_choice(os,attr_type);
+          os<<"\t\t"<<attribute->cpp_name()<<": \"\",\n";
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          std::string scope("\t");
+          attribute->get_type()->name(attribute->cpp_name()+"_t");
+          
+          os<<"\t\t"<<(attribute)->cpp_name()<<" : \"\",\n";
+        }
+        break;
+      case asn1::type::ASN1_SELECTION:
+        {
+          os<<"\t\tINTEGER "<<(attribute)->cpp_name();
+          os<<"; // SELECTION TO be done\n";
+        }
+        break;
+      case asn1::type::ASN1_SET_OF:
+      case asn1::type::ASN1_SEQUENCE_OF:
+        {
+          asn1::typenode *type    = attribute->get_type();
+          asn1::typenode *subtype = type->get_eltype();
+          
+          switch (subtype->type_id()())
+          {
+            case asn1::type::ASN1_SEQUENCE:
+              subtype->name((attribute)->cpp_name()+std::string("_type"));
+              gen_seq(os,scope,subtype->as_sequence(),true);
+              os<<";\n\t"<<type->name();
+              os<<"<"<<std::string( (attribute)->cpp_name()+"_type");
+              os<<">\t"<<(attribute)->cpp_name()<<";\n";
+              break;
+            default:
+              asn1::node *ns;
+              if (type_in_imports(subtype,&ns) )
+              {
+                os<<"  "<<type->name()<<"<"<<ns->cpp_name();
+                os<<"::"<<subtype->cpp_name();
+                os<<">\t"<<(attribute)->cpp_name()<<";\n";
+              } else
+              {
+                if (asn1::typeref *tref = subtype->as_typeref()) 
+                {
+                  os<<"  "<<type->name()<<"<";
+                  os<<(tref->get_reference())->cpp_name();
+                  os<<">\t"<<(attribute)->cpp_name()<<";\n";
+                } else
+                os<<"  "<<type->name()<<"<"<<subtype->cpp_name()<<">\t"<<attribute->cpp_name()<<";\n";
+              }
+          }
+        }
+        break;
+      case asn1::type::ASN1_REFERENCE:
+        
+      {
+        os<<"\t"<<(attribute)->cpp_name()<<": \"\",";
+        os<<std::endl;
+        }
+        break;
+      default:
+        {
+          asn1::node *ns = NULL;
+          os<<"\t"<<(attribute)->cpp_name()<<": \"\",";
+        os<<"\n";
+        }
+    }
+  }
+}
+
+
+/**
+ *
+ */
+void generate_js::gen_set_printf(std::ostream &os,std::string &scope,asn1::node *n,bool priv)
+{
+  /*
+   * Try to handler sequence of sequence 
+   */
+
+}
+
+
+/**
+ *
+ */
+void generate_js::gen_set(std::ostream &os,asn1::node *n)
+{
+  std::string scope("");
+}
+
+
+void generate_js::gen_object_class_opt(std::ostream &os,asn1::node *n)
+{
+}
+
+/**
+ *
+ *
+ */
+void generate_js::gen_object_class_missing(std::ostream &os,asn1::node *n)
+{
+}
+
+
+/**
+ *
+ *
+ */
+void generate_js::gen_object_class_interface(std::ostream &os,asn1::node *n)
+{
+}
+
+
+void generate_js::gen_object_class_attributes(std::ostream &os,asn1::node *n)
+{
+}
+
+
+void 
+generate_js::gen_object_class_printf(std::ostream &os,asn1::node *n)
+{
+}
+/**
+ *
+ *
+ */
+void generate_js::gen_object_class(std::ostream &os,asn1::node *n)
+{
+}
+/**
+ *
+ *
+ */
+void generate_js::gen_object(std::ostream &os,asn1::node *n)
+{
+  os.flush();
+}
+
+/**
+ *
+ *
+ */
+void generate_js::gen_object_object_type(std::ostream &os,asn1::node *n)
+{
+}
+
+
+
+/**
+ *
+ *
+ */
+void generate_js::gen_object_error(std::ostream &os,asn1::node *n)
+{
+  std::cerr<<__FUNCTION__<<" To rewrite"<<std::endl;
+}
+
+
+void generate_js::gen_object_operation(std::ostream &os,asn1::node *n) 
+{
+  std::cerr<<__FUNCTION__<<" To rewrite"<<std::endl;
+}
+
+/**
+ *
+ *
+ */
+void generate_js::gen_object_operation_package(std::ostream &os,asn1::node *n) 
+{
+}
+
+void generate_js::gen_object_connection(std::ostream &os,asn1::node *n) 
+{
+}
+
+
+class do_assignment : public assignment_visitor<do_assignment>
+{
+  protected:
+    generate_js &m_js;
+    std::ostream &m_os;
+  public:
+    do_assignment(generate_js &_js,std::ostream &os) 
+      : m_os(os),m_js(_js)  {};
+
+    void visit_type(asn1::type_assignment *type)
+    {
+      m_js.gen_typedef(m_os,type->get_type());
+    }
+    void visit_value(asn1::value_assignment *type)
+    {
+      m_js.gen_const(m_os ,type->get_type());
+    }
+#if 0
+    void visit_valueset(asn1::valueset_assignment *type)
+    {
+    }
+    void visit_objectclass(asn1::objectclass_assignment *type)
+    {
+    }
+#endif
+    void visit_object(asn1::object_assignment *type)
+    {
+      m_js.gen_object(m_os,type->get_type());
+    }
+    void visit_typeref(asn1::typeref_assignment *type)
+    {
+      m_js.gen_typeref(m_os,type->get_type()->as_typeref());
+    }
+    void visit_assignment(asn1::assignment *type)
+    {
+      std::cout<<__FUNCTION__<<" Unhandled assignment "<<type->name()<<std::endl;
+      m_os<<"//"<<__FUNCTION__<<" Unhandled assignment "<<type->name()<<std::endl;
+    }
+};
+
+/**
+ *
+ */
+void generate_js::gen_module(std::ostream &os,asn1::module *_module)
+{
+  asn1::import_list *imports = _module->imports();
+  // Add include for external dependencies
+  
+  os<<"if ( !  "<<_module->cpp_name()<<")\n {\n"<<std::endl;
+  _module->sort_childs();
+  
+  for ( asn1::node::iterator it = _module->begin()
+      ; it != _module->end() ; it++)
+  {
+    asn1::assignment *type = (*it)->as_assignment();
+    std::cout<<"generate_js::"<<__FUNCTION__<<" process "<<type->name();
+    std::cout.flush();
+    if (type->get_type() != NULL)
+    {
+     if ( type->is_generated())
+     {
+       std::cout<<" ALREADY GENERATED "<<std::endl; 
+       continue;
+     }
+     do_assignment doa(*this,os);
+     if (type)
+     {
+       doa.visit(type);
+     } else
+       std::cout<<__FUNCTION__<<" Type "<<type->name()<<" is NULL"<<std::endl;
+     os<<std::endl;
+     type->set_color(asn1::node::CL_RED);
+    } else 
+    {
+         std::cout<<" no type "<<type->name();
+         os<<"// "<<__FUNCTION__<<" no type "<<type->name();
+    }
+    os<<std::endl; 
+    std::cout<<std::endl; 
+  }
+  os<<"}"<<std::endl;
+}
+
+/**
+* vim:et:sw=2:ts=2
+*/
diff --git a/libgen/js/asn1_gen_js.h b/libgen/js/asn1_gen_js.h
new file mode 100644 (file)
index 0000000..1be9a52
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef GEN_HEADER_JS_H__
+#define GEN_HEADER_JS_H__
+#include <iostream>
+#include <algorithm>
+
+
+/**
+ *
+ */
+class generate_js : public asn1::generator
+{
+  public:
+
+    generate_js(asn1::module *n); 
+    
+    generate_js(asn1::module *n,asn1::module::modules_type &m); 
+   
+
+    void gen_missing(std::ostream &os,asn1::node *n) ;
+
+    /**
+     *
+     *
+     */
+    void gen_const(std::ostream &os,asn1::node *n);
+    
+    void gen_enumerated_printf( std::ostream &os
+                              , asn1::enumerated &n
+                              , const std::string &name);
+    void gen_enumerated(std::ostream &os,asn1::enumerated &n ,const std::string &name);
+       //
+    //
+    //
+    void gen_typedef(std::ostream &os,asn1::typenode *n);
+    void gen_typeref(std::ostream &os,asn1::typeref *n);
+    
+    void gen_seq_printf( std::ostream &os
+                       , std::string &scope
+                       , asn1::sequence *type,bool priv =false);
+    /**
+     *
+     */
+    void gen_seq( std::ostream &os,std::string &scope
+                , asn1::sequence *n,bool priv = false);
+    
+    void gen_choice_printf(std::ostream &os,asn1::choice *n);
+    
+    void gen_choice(std::ostream &os,asn1::choice &choice);
+    
+    void gen_composite_attribute( std::ostream &os
+                                , std::string &scope
+                                , asn1::field *attribute,asn1::node *params = NULL);
+    void gen_composite_attribute_ref( std::ostream &os
+                                    , std::string &scope
+                                    , asn1::typeref *attribute
+                                    , asn1::node *params = NULL);
+    void gen_template_params(std::ostream &os,asn1::node *params);
+    void gen_template_signature(std::ostream &os,asn1::node *params);
+    
+    /**
+     *
+     */
+    void gen_set(std::ostream &os,asn1::node *n);
+    void gen_set_printf(std::ostream &os,std::string &scope,asn1::node *n,bool priv =false);
+  
+    /*
+     * Ros generation Code
+     */
+    void gen_object_class(std::ostream &os,asn1::node *n); 
+    void gen_object_class_interface(std::ostream &os,asn1::node *n);
+    void gen_object_class_missing(std::ostream &os,asn1::node *n);
+    void gen_object_class_opt(std::ostream &os,asn1::node *n); 
+    void gen_object_class_attributes(std::ostream &os,asn1::node *n); 
+  
+    void gen_object_class_printf(std::ostream &os, asn1::node *n);
+    void gen_object(std::ostream &os,asn1::node *n); 
+    void gen_object_object_type(std::ostream &os,asn1::node *n); 
+    void gen_object_error(std::ostream &os,asn1::node *n); 
+    void gen_object_operation(std::ostream &os,asn1::node *n); 
+    void gen_object_operation_package(std::ostream &os,asn1::node *n); 
+    void gen_object_connection(std::ostream &os,asn1::node *n); 
+    /**
+     *
+     */
+    void gen_module(std::ostream &os,asn1::module *n);
+  protected:
+    std::vector<std::string>  m_Stack;
+};
+/**
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libgen/lds/asn1_gen_lds.cpp b/libgen/lds/asn1_gen_lds.cpp
new file mode 100644 (file)
index 0000000..bb67a5e
--- /dev/null
@@ -0,0 +1,347 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <list>
+#include <assert.h>
+
+#include "asn1_generator.h"
+#include "asn1_gen_lds.h"
+#include "adt/asn1_visitor.h"
+
+
+
+
+/**
+ * Default constructor to be used
+ */
+generate_lds::generate_lds(asn1::module *n,asn1::module::modules_type &m)
+  : generator(n,m)
+{
+}
+
+
+/**
+*
+*
+*/
+void
+generate_lds::gen_const(std::ostream &os,asn1::node *n)
+{
+}
+
+
+/**
+ *
+ */ 
+void
+generate_lds::gen_enumerated( std::ostream &os
+       , asn1::enumerated  &_enum
+       )
+{
+}
+
+
+class dolds_typedef : public node_visitor<dolds_typedef>
+{
+  protected:
+    generate_lds       &m_gen;
+    std::ostream       &m_os;
+    std::fstream       &m_log;
+
+  public:
+    dolds_typedef(std::ostream &_os,generate_lds &_gen)
+      : m_os(_os) , m_gen(_gen)
+      , m_log(_gen.logger())
+    {
+    }
+#define DO_TYPEDEF(Tp,Code) \
+    void visit_##Tp(asn1::Tp *type) \
+    Code
+
+    void visit_primitive(asn1::primitive *type)
+    {
+      m_os<<"string "<<type->identifier_name()<<";"<<std::endl;
+    }
+DO_TYPEDEF(boolean,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_boolean  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"boolean "<<type->identifier_name()<<";"<<std::endl;
+    })
+DO_TYPEDEF(integer,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_integer  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"integer "<<type->identifier_name()<<";"<<std::endl;
+    })
+DO_TYPEDEF(choice,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_choice  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"value type "<<type->identifier_name()<<" { choice"<<std::endl;
+      for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+      {
+        asn1::field *f = dynamic_cast<asn1::field *>(*it);
+        asn1::typenode *attr_type = f->get_type();
+        if (attr_type != NULL)
+        {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            m_os<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            m_os<<"\t"<<f->cpp_name()<<"\t"<<attr_type->cpp_name()<<";\n";
+          }
+        }
+      }
+      m_os<<" };"<<std::endl;
+    })
+
+DO_TYPEDEF(sequence,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_sequence  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"value type "<<type->identifier_name()<<" { struct"<<std::endl;
+      for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+      {
+        asn1::field *f = dynamic_cast<asn1::field *>(*it);
+        asn1::typenode *attr_type = f->get_type();
+        if (attr_type != NULL)
+        {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            m_os<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            m_os<<"\t"<<f->cpp_name()<<"\t"<<attr_type->cpp_name()<<";\n";
+          }
+        }
+      }
+      m_os<<" };"<<std::endl;
+    })
+DO_TYPEDEF(set,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_set  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"value type "<<type->identifier_name()<<" { struct"<<std::endl;
+      for (asn1::node::iterator it = type->begin(); it != type->end() ; it++)
+      {
+        asn1::field *f = dynamic_cast<asn1::field *>(*it);
+        asn1::typenode *attr_type = f->get_type();
+        if (attr_type != NULL)
+        {
+          if (attr_type->type_id()() == asn1::type::ASN1_EXTENSIBLE)
+          {
+            m_os<<"\t// Extensible marker"<<std::endl;
+          } else
+          {
+            m_os<<"\t"<<f->cpp_name()<<"\t"<<attr_type->cpp_name()<<";\n";
+          }
+        }
+      }
+      m_os<<" };"<<std::endl;
+    })
+DO_TYPEDEF(sequence_of,{
+      // Try to create an include file
+      asn1::typenode *seqof_type = type->get_eltype();
+      GEN_LOG_DEBUG( "visit_sequence_of  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"value type "<<type->identifier_name()<<" inherits ";
+      m_os<<"Array <"<<","<<seqof_type->cpp_name()<<">;"<<std::endl;
+    })
+DO_TYPEDEF(octet_string,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_octet_string  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"octet_string "<<type->identifier_name()<<";"<<std::endl;
+    })
+DO_TYPEDEF(bit_string,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_bit_string  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"bitstring "<<type->identifier_name()<<";"<<std::endl;
+    })
+DO_TYPEDEF(enumerated,{
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_enumerated  %s  \n"
+                    , type->identifier_name().c_str());
+      m_os<<"enumerated "<<type->identifier_name()<<";"<<std::endl;
+    })
+};
+
+/**
+ * I think I should provide a visitor class for that 
+ * function as well. For each type I have to decide what 
+ * to generate.
+ */ 
+void
+generate_lds::gen_typedef(std::ostream &os,asn1::typenode *type)
+{
+  dolds_typedef dolds(os,*this);
+  os<<"\n/*\n * "<<type->identifier_name()<<"\n */\n";
+  dolds.visit(type);
+}
+
+
+/**
+ *
+ */ 
+void
+generate_lds::gen_typeref( std::ostream &os
+                         , asn1::typeref &type)
+{
+  os<<"\n/*\n * "<<type.identifier_name()<<"\n * TODO\n */\n";
+  os<<"syntype "<<type.identifier_name()<<" = "<<type.cpp_name()<<" endsyntype "<<type.identifier_name()<<";\n";
+}
+
+
+/**
+*
+*/
+void
+generate_lds::gen_seq( std::ostream &os
+       , asn1::sequence &n)
+{
+}
+
+
+/**
+ *
+ */ 
+void
+generate_lds::gen_choice( std::ostream &os
+          , asn1::choice &choice)
+{
+}
+
+
+/**
+*
+*/
+void
+generate_lds::gen_set(std::ostream &os,asn1::set &n)
+{
+}
+
+
+/*
+* Ros generation Code
+*/
+void
+generate_lds::gen_object_class(std::ostream &os,asn1::classdef &n)
+{
+}
+
+/**
+ *
+ */ 
+void
+generate_lds::gen_object(std::ostream &os,asn1::object &n)
+{
+}
+/**
+* gen_module, main entry point. loops through imports and
+* then through assignments.
+*
+
+*/
+class dolds_assignment : public assignment_visitor<dolds_assignment>
+{
+  public:
+    dolds_assignment(std::ostream &_os,generate_lds &_gen)
+      : m_os(_os) , m_gen(_gen)
+      , m_log(_gen.logger())
+    {
+    }
+    // Main processing function per assignment
+    void operator ()(asn1::node *n)
+    {
+      asn1::typenode *type = n->as_assignment()->get_type();
+      std::string     path = n->cpp_name()+".cpp";
+      GEN_LOG_DEBUG( "Process  item=%s meta=%d\n"
+                 , n->name().c_str()
+                 , n->meta_id()());
+      if ( ! type)
+        return;
+      
+      if ( n->is_generated())
+      {
+        GEN_LOG_DEBUG("%s already generated\n",n->name().c_str());
+        return;
+      }
+#if 0
+      if (m_gen.with_split_cpp())
+        m_gen.open_assignment_stream(m_sep_os,n->as_assignment());
+#endif
+      visit(n->as_assignment());
+#if 0
+      if (m_sep_os.is_open())
+        m_sep_os.close();
+#endif
+      n->set_color(asn1::node::CL_RED);
+    }
+#define ASSIGNMENT(En,Tp,Parent,Code) \
+    void visit_##Tp(asn1::Tp##_assignment *a) \
+    Code
+ASSIGNMENT(TYPEREF,typeref,assignment,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_Typeref  %s  parameterized: %d\n"
+                    , a->name().c_str(),params);
+      m_gen.gen_typeref(m_os,*a->get_type()->as_typeref());
+    })
+ASSIGNMENT(TYPE,type,assignment,{
+      int params = (a->parameters() != NULL)?1:0;
+      // Try to create an include file
+      GEN_LOG_DEBUG( "visit_Type  %s  parameterized: %d\n"
+                    , a->name().c_str(),params);
+      m_gen.gen_typedef(m_os,a->get_type());
+    })
+ASSIGNMENT(VALUE,value,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+ASSIGNMENT(VALUESET,valueset,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECT,object,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECTCLASS,objectclass,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECTSET,objectset,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECTFIELD,objectfield,assignment,{
+    std::cout<<__FUNCTION__<<" TODO "<<a->name()<<std::endl;
+    })
+
+    void visit_assignment(asn1::assignment *a)
+    {}
+#undef ASSIGNMENT
+
+  protected:
+    generate_lds       &m_gen;
+    std::ostream       &m_os;
+    std::fstream       &m_log;
+};
+
+void
+generate_lds::gen_module(std::ostream &os,asn1::module *_module)
+{
+  asn1::module &_m = *_module;
+  _m.sort_childs();
+  
+  dolds_assignment doa(os,*this);
+  for ( asn1::node::iterator it = _m.begin();
+       it != _m.end() ; it++)
+  {
+    doa.visit((*it)->as_assignment());
+  }
+}
+/*
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/libgen/lds/asn1_gen_lds.h b/libgen/lds/asn1_gen_lds.h
new file mode 100644 (file)
index 0000000..cffa172
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef GEN_HEADER_LDS_H__
+#define GEN_HEADER_LDS_H__
+#include <iostream>
+#include <algorithm>
+
+
+/**
+ * When calling the generator, the structure has already been flatten.
+ * There is no need to recurse over sub types and so on.
+ */
+class generate_lds : public asn1::generator
+{
+  public:
+
+
+    generate_lds(asn1::module *n,asn1::module::modules_type &m);
+
+    /**
+     *
+     */
+    void gen_const(std::ostream &os,asn1::node *n);
+    
+
+    /**
+     *
+     */
+    void gen_typeref( std::ostream &os
+                    , asn1::typeref &n);
+    
+    /**
+     *
+     */
+    void gen_typedef(std::ostream &os,asn1::typenode *n);
+    /**
+     *
+     */
+    void gen_seq( std::ostream &os
+                , asn1::sequence &n);
+    
+    /**
+     *
+     */
+    void gen_choice( std::ostream &os
+                   , asn1::choice &choice);
+    
+    /**
+     *
+     */
+    void gen_set(std::ostream &os,asn1::set &n);
+
+    /**
+     *
+     */
+    void gen_enumerated( std::ostream &os
+                       , asn1::enumerated  &_enum
+                       );
+  
+    /*
+     * Ros generation Code
+     */
+    void gen_object_class(std::ostream &os,asn1::classdef &n);
+  
+    /**
+     *
+     */
+    void gen_object(std::ostream &os,asn1::object &n);
+    /**
+     *
+     */
+    void gen_module(std::ostream &os,asn1::module *_m);
+  protected:
+};
+/**
+ * vim:et:sw=2:ts=2:list
+ */
+#endif
diff --git a/libgen/uml/asn1_gen_uml.cpp b/libgen/uml/asn1_gen_uml.cpp
new file mode 100644 (file)
index 0000000..c73a6ce
--- /dev/null
@@ -0,0 +1,1274 @@
+#include <iostream>
+#include <algorithm>
+#include <map>
+#include <cassert>
+#include "asn1_generator.h"
+#include "asn1_gen_uml.h"
+#include "adt/asn1_visitor.h"
+
+static long g_counter = 0;
+
+/**
+ *  Default Cosntructor
+ */
+generate_uml::generate_uml(asn1::module *n) : asn1::generator(n) 
+{}
+
+generate_uml::generate_uml(asn1::module *n,asn1::module::modules_type &m) 
+  : asn1::generator(n,m)
+{
+}
+
+/**
+ * Helper function to look for missing prototypes
+ */
+void  generate_uml::gen_missing(std::ostream &os,asn1::typenode *n)
+{
+  asn1::node::iterator it;
+  switch (n->type_id()())
+  {
+    case asn1::type::ASN1_SEQUENCE_OF:
+    case asn1::type::ASN1_SET_OF:
+      {
+#ifdef DEBUG
+        std::cout<<"Find sequence of or set of:\n";
+#endif
+        asn1::typenode *type = n->get_eltype();
+        if  (type !=NULL)
+        {
+          if (asn1::typeref *tref = type->as_typeref()) 
+          {
+            it = std::find_if(m_module->begin(),
+                 m_module->end(),
+                 asn1::find_node(tref->get_reference()->name()));
+          } else
+          it = std::find_if(m_module->begin(),
+                 m_module->end(),
+                 asn1::find_node(type->name()));
+        } else return;
+      
+      } 
+      break;
+    case asn1::type::ASN1_SEQUENCE:
+    case asn1::type::ASN1_CHOICE:
+      {
+        asn1::constructed *ct = n->as_constructed();
+        GEN_LOG_DEBUG("choice or sequence %s\n",n->name().c_str());
+        asn1::node::iterator lit = ct->begin();
+        for (; lit != ct->end() ; lit++)
+        {
+          asn1::field *f = dynamic_cast<asn1::field *>(*it);
+          if ( f->get_type() != NULL) {
+                gen_missing(os,f->get_type());
+          }
+        }
+      }
+        return;
+        break;
+    case asn1::type::ASN1_NULL:
+        return;
+    case asn1::type::ASN1_REFERENCE:
+    {
+      asn1::typeref *tref = n->as_typeref();
+       // Try to check references
+       if (tref->parameters() != NULL)
+       {
+         asn1::constructed *params = n->parameters();
+         std::cout<<"generate_uml::"<<__FUNCTION__<<" Have parameters\n";
+//         os<<"//generate_uml::"<<__FUNCTION__<<" "<<n->name()<<" Have parameters\n";
+         for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+         {
+                std::cout<<"generate_uml::"<<__FUNCTION__<<" Parameter:"<<(*p)->name()<<"\n";
+                it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node((*p)->name()));
+                
+                if (it != m_module->end())
+                  gen_missing(os,(*it)->as_typenode());
+         }
+       }
+       //
+       if (tref->get_reference())
+       {
+          if (std::string("TYPE-IDENTIFIER::&Type").compare(tref->get_reference()->name()) == 0)
+          {
+             asn1::constraint::iterator c = tref->constraint_begin();
+             if ((*c)->type() == asn1::constraint::EL_TYPE)
+             {
+                asn1::node *ctype = (*c)->value();
+                it = std::find_if(m_module->begin(),
+                                m_module->end(),
+                                asn1::find_node(ctype->name()));
+             }
+          } else {
+             it = std::find_if(m_module->begin(),
+                               m_module->end(),
+                              asn1::find_node(tref->get_reference()->name()));
+          }
+
+       } else 
+       {
+              it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+
+       }
+    }
+     break;    
+    default:
+       it = std::find_if(m_module->begin(),m_module->end(),asn1::find_node(n->name()));
+  }
+// Found a element to be generated  
+  if ( it != m_module->end())
+  {
+    asn1::assignment *ltype = dynamic_cast<asn1::assignment *>(*it);
+    if ( ltype->is_generated() != true)
+    {
+      if (ltype->get_color() == asn1::node::CL_GREEN) 
+      {
+        ltype->set_generated(true);
+        GEN_LOG_DEBUG("missing %s\n",ltype->name().c_str());
+        switch(ltype->get_type()->type_id()())
+        {
+          case asn1::type::ASN1_REFERENCE:
+            gen_typeref(os,ltype->get_type()->as_typeref());
+          break;
+          default:
+            gen_typedef(os,ltype->get_type()->as_typenode());
+        }
+        (*it)->set_color(asn1::node::CL_RED);
+      } else if (ltype->get_color() == asn1::node::CL_ORANGE) 
+      {
+        if (ltype->get_type()->type_id()() == asn1::type::ASN1_SEQUENCE ||
+            ltype->get_type()->type_id()() == asn1::type::ASN1_CHOICE
+        ) 
+        os<<"struct "<<ltype->cpp_name()<<";"<<std::endl;
+        ltype->set_generated(true);        
+      }else {
+        ltype->set_generated(true);
+      }
+    } 
+  }
+}
+
+/**
+ *
+ *
+ */
+void  generate_uml::gen_const(std::ostream &os,asn1::node *type)
+{
+  switch(type->type_id()())
+  {
+    case asn1::type::ASN1_OBJECT_IDENTIFIER:
+    {
+      os<<"<packagedElement xmi:id=\""<<type->identifier_cpp_name();
+      os<<g_counter<<"\" xmi:type=\"uml:LiteralInteger\"";
+      os<<" name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+      g_counter++;
+    }
+    break;
+    case asn1::type::ASN1_VALUESET:
+    {
+    }
+    break;
+    case asn1::type::ASN1_INTEGER:
+    {
+      os<<"<packagedElement xmi:id=\"Pkg_"<<g_counter;
+      os<<"\" xmi:type=\"uml:LiteralInteger\"";
+      os<<" name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+      g_counter++;
+    }
+    break;
+    default:
+      std::cout<<__FUNCTION__<<" ERROR DEFAULT"<<type->identifier_cpp_name();
+      std::cout<<"\n"; std::cout.flush();
+      ;
+  }
+  os<<std::endl;
+
+}
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_enumerated( std::ostream &os
+                                 , asn1::enumerated &_type 
+                                 , const std::string &name
+                                 , bool nested)
+{
+  asn1::enumerated *enumt = &_type;
+  std::string indent("");
+  asn1::node::iterator it = enumt->begin();
+  std::string balise;
+  if (nested ) {
+    balise = "nestedClassifier";
+  } else 
+    balise = "packagedElement";
+  os<<"<"<<balise<<" xmi:id=\""<<_type.identifier()->uid();
+  os<<"\" xmi:type=\"uml:Class\" name=\""<<name<<"\">";
+  for (; it != enumt->end(); it++)
+  {
+    os<<"<ownedAttribute xmi:id=\""<<(*it)->uid()<<"\" name=\"";
+    os<<(*it)->name()<<"\"/>\n";
+  }
+  os<<indent<<"</"<<balise<<">\n ";
+}
+
+//
+// gen_typeref
+//
+void generate_uml::gen_typeref(std::ostream &os,asn1::typeref *type)
+{
+  std::string type_name;
+  
+  if (type ) 
+  {
+    int par = (type->parameters() == NULL)?0:1;
+    GEN_LOG_DEBUG("type=%s params=%d\n",type->name().c_str(),par);
+    
+    if (type->has_constraints())
+    {
+      asn1::constraint *c = *(type->constraint_begin());
+    }
+  }
+  if (type->get_reference()) {
+    //type_name = type->get_reference()->cpp_name();
+    type_name = type->cpp_name();
+  } else {
+    type_name = type->cpp_name();
+  }
+  if (type->type_id()() != asn1::type::ASN1_REFERENCE)
+  {
+    std::cout<<__FUNCTION__<<"ERROR "<<type->cpp_name()<<" type="<<type->type_id()();
+    exit(0);
+  }
+
+
+     gen_missing(os,type);
+     asn1::node *ns = NULL;
+     //os<<"typedef ";
+     os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\" name=\""<<type->identifier_cpp_name()<<"\"/>\n";
+     g_counter++;
+  if (type->tagged())
+  {
+  } else {
+       // Process untagged elements
+       asn1::constructed *params = type->parameters();
+       if (type_in_imports(type,&ns) ) 
+       {
+         // imported case
+         if (type->meta_id()() == asn1::meta::OBJECTCLASS)
+         {
+           //os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+         } else if (std::string("OPERATON").compare(type->cpp_name())==0)
+         {
+           //os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+         } else
+         {
+           //TODO find reference and add it so we can know 
+           //os<<"\t"<<ns->cpp_name()<<"::";
+           //os<<type->cpp_name()<<" ";
+         }
+       } else if (std::string("TYPE_IDENTIFIER").compare(type->cpp_name())==0) {
+          //os<<" /* def"<<type->cpp_name()<<"*/INTEGER ";
+        
+       } else {
+          // internal case 
+       }
+        // Buuggeeee
+        if (std::string("ROS").compare(type->name()) )
+          if (params && is_template(params))
+          {
+            asn1::node::iterator begin = params->begin();
+            asn1::node::iterator end   = params->end();
+            os<<"<";
+            for (; begin != end ; ++begin) {
+              if (begin != params->begin())
+                os<<",";
+              os<<(*begin)->cpp_name();
+            }
+            os<<">";
+          }
+     
+  }
+
+   // os<<"\t\t"<<type->identifier_cpp_name()<<";\n\n";
+}
+
+
+//
+//
+//
+void generate_uml::gen_typedef(std::ostream &os,asn1::typenode *type)
+{
+  if (type ) 
+  {
+    GEN_LOG_DEBUG("type %s ident=%s\n",type->name().c_str(),type->identifier_name().c_str());
+    
+    if (type->has_constraints())
+    {
+      asn1::constraint *c = *(type->constraint_begin());
+//      if (c)
+//        os <<c->name();
+
+    }
+    if ( type->identifier() && type->identifier()->parameters())
+    {
+//      os<<" parameterized "; 
+    }
+    os<<"\n";
+  }
+
+  if (type != NULL)
+    switch (type->type_id()())
+    {
+      case asn1::type::ASN1_REFERENCE:
+      {
+        std::cout<<"__FUNCTION__"<<" ERROR "<<type->cpp_name()<<std::endl;
+        exit(0);
+       //    os<<"typedef  "<<type->name()<<" ";
+       gen_missing(os,type);
+       asn1::node *ns = NULL;
+       //os<<"typedef ";
+       os<<"AEBW.declare(\""<<type->cpp_name()<<"\",AEBW.Asn1 ";
+       if (type->tag().m_value != -1)
+       {
+       } else {
+         if (type_in_imports(type,&ns) ) {
+           if (type->meta_id()() == asn1::meta::OBJECTCLASS)
+           {
+             os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+           } else if (std::string("OPERATON").compare(type->cpp_name())==0)
+           {
+             os<<"// OBJECT CLASS NOT YET SUPPORTED "<<type->cpp_name()<<" ";
+           } else
+           {
+             os<<"\t"<<ns->cpp_name()<<"::";
+             os<<type->cpp_name()<<" ";
+           }
+          } else
+            os<<" /**/ "<<type->cpp_name()<<" ";
+       
+       }
+
+      }
+      break;
+      case asn1::type::ASN1_INTEGER:
+        {
+          os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+          g_counter++;
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE:
+        {
+          std::string scope("");
+          asn1::sequence *seq = type->as_sequence();
+          asn1::node::iterator lit = seq->begin();
+          for (; lit != seq->end() ; ++lit)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( asn1::typenode *tn = f->get_type() ) {
+                  gen_missing(os,tn);
+            }
+          }
+          gen_seq(os,scope,*seq);
+          os<<"\n";
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SEQUENCE_OF:
+        {
+          asn1::node *ns = NULL;
+          asn1::typenode *subt =type->get_eltype();
+          gen_missing(os,subt);
+          if (type_in_imports(subt,&ns) ) {
+              os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+              g_counter++;
+          } else {
+            switch (subt->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+              {
+                std::string scope("\t");
+
+                subt->name(type->identifier_cpp_name()+"_type");
+                gen_seq(os,scope,*subt->as_sequence());
+                //os<<";\ntypedef SEQUENCE_OF<"<<(*it)->cpp_name()<<"> ";
+                os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+              }
+              break;
+              default:
+                if (asn1::typeref *tref = subt->as_typeref())
+                {
+                 os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+                } else
+                {
+                   os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+                }
+            }
+          }
+        }
+        break;
+      case asn1::type::ASN1_SET:
+        {
+          asn1::set *settype = type->as_set();
+          asn1::node::iterator lit = settype->begin();
+          for (; lit != settype->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( asn1::typenode *tn = f->get_type()) {
+                  gen_missing(os,tn);
+            }
+          }
+          gen_set(os,settype);
+          os<<"\n";
+          return ;
+        }
+        break;
+      case asn1::type::ASN1_SET_OF:
+        {
+          asn1::typenode *it = type->get_eltype();
+          if (it)
+            gen_missing(os,it);
+          if (asn1::typeref *tref = it->as_typeref())
+          {
+            os<<"<packagedElement xmi:id=\""<<g_counter<<"\" xmi:type=\"uml:DataType\"  name=\""<<tref->get_reference()->name()<<"\"/>"<<std::endl;
+            g_counter++;
+          } else
+          {
+            os<<"<packagedElement xmi:id=\""<<g_counter<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->cpp_name()<<"\"/>"<<std::endl;
+            g_counter++;
+          }
+        }
+        break;
+      case asn1::type::ASN1_CHOICE:
+        {
+          asn1::choice *ct = type->as_choice();
+          asn1::node::iterator lit = ct->begin();
+          for (; lit != ct->end() ; lit++)
+          {
+            asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+            if ( asn1::typenode *tn = f->get_type() ) {
+              gen_missing(os,tn);
+            }
+          }
+            gen_choice(os,ct);
+           os<<"\n";
+           return;
+        }
+        break;
+      case asn1::type::ASN1_ENUMERATED:
+        {
+           //os<<"typedef ";
+            gen_enumerated(os,*type->as_enumerated(),type->identifier_cpp_name());
+        }
+        break;
+      ;
+      case asn1::type::ASN1_BIT_STRING:
+      {
+        os<<"<packagedElement xmi:id=\""<<type->identifier()->uid();
+        os<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name();
+        os<<"\"/>"<<std::endl;
+        g_counter++;
+        return ;
+      }
+      break;
+      default:
+       gen_missing(os,type);
+       asn1::node *ns = NULL;
+        os<<"<packagedElement xmi:id=\""<<type->identifier()->uid()<<"\" xmi:type=\"uml:DataType\"  name=\""<<type->identifier_cpp_name()<<"\"/>"<<std::endl;
+       return;
+      ;
+    };
+
+  //os<<"\t\t"<<type->identifier_cpp_name()<<";\n\n";
+  
+}
+
+/**
+ *
+ */
+void generate_uml::gen_seq(std::ostream &os,std::string &scope,asn1::sequence &_type)
+{
+  asn1::sequence * type = &_type;
+  asn1::node     * n    = _type.identifier();
+  asn1::node::iterator lit;
+  asn1::constructed  *params = n->parameters();
+  std::string balise;
+  
+  balise = "packagedElement";
+  /*
+   * Try to handler sequence of sequence 
+   */
+  if ( type != NULL)
+  {
+    lit = type->begin();
+  }
+
+  m_Stack.push_back(n->cpp_name());
+  // default constructor 
+  // I should probaly push optionnal attributes and OBEJECTS in a stack and add a initializer here.
+  std::vector<asn1::node *> opt_attrs;
+  for (asn1::node::iterator it = type->begin()
+      ; it != type->end() ; it++)
+  {
+    asn1::field    *f         = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *attr_type = f->get_type();
+    if (attr_type != NULL)
+    {
+      asn1::typeref *tref = attr_type->as_typeref();
+      if (tref && tref->get_reference() && tref->is_complex())
+      {
+          asn1::reference *r = tref->get_reference();
+          std::string lr = r->back().m_identifier;
+          opt_attrs.push_back((*it));
+      }
+    }
+  }
+  os<<"<"<<balise<<" xmi:id=\""<<n->uid();
+  os<<"\" xmi:type=\"uml:Class\"  name=\""<<n->cpp_name()<<"\"> \n";
+  // Constructor
+  // Copy constructor 
+
+  for (; lit != type->end() ; lit++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*lit);
+    gen_composite_attribute(os,scope,f,n->parameters());
+  }
+  
+  os<<"</"<<balise<<">\n";
+  m_Stack.pop_back();
+}
+
+
+//
+//
+//
+void generate_uml::gen_template_params(std::ostream &os,asn1::node *_params)
+{
+  asn1::constructed *params = _params->as_constructed();
+  asn1::node::node_list nl;
+
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+ os<<"> ";
+}    
+//
+//
+//
+void generate_uml::gen_template_signature(std::ostream &os
+              ,asn1::node *_params)
+{
+  asn1::constructed *params = _params->as_constructed();
+  asn1::node::node_list nl;
+
+  os<<"<";
+  for(asn1::node::iterator p = params->begin(); p != params->end() ;++p)
+  {
+    if (nl.size()>0)
+    {
+      asn1::node::iterator it = std::find_if(nl.begin(),nl.end(),asn1::find_node((*p)->name()));
+      if (it != nl.end() )
+      {
+        //
+      } else {
+       if (p != params->begin()) os<<",";
+       os<<" typename "<<(*p)->cpp_name();
+       nl.push_back(*p);       
+      }
+    } else {
+      if (p != params->begin()) os<<",";
+      os<<" typename "<<(*p)->cpp_name();
+      nl.push_back(*p);
+    }
+  }
+ os<<"> ";
+}    
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_choice(std::ostream &os,asn1::choice *n,bool nested)
+{
+  std::string scope(""); 
+  asn1::constructed *type = n->as_constructed();
+  asn1::node::iterator it;
+  std::string balise;
+  if (nested) {
+    balise = "nestedClassifier";
+  } else {
+    balise = "packagedElement";
+  }
+  if (type == NULL)
+  {
+    type = n->as_constructed();
+  }
+  m_Stack.push_back(n->cpp_name());
+  GEN_LOG_DEBUG("node=%s nested=%d\n",n->name().c_str(),nested);
+  it = type->begin();
+  // Handle parameter stuff
+  if (n->parameters() && is_template(n->parameters()))
+  {
+    asn1::node::node_list nl;
+    asn1::constructed  *params = n->parameters();
+ //   os<<"//"<<__FUNCTION__<<" parameterized\n";
+    // Forward declaration for ostream function
+    os<<"template ";
+    gen_template_signature(os,params);
+    os<<" struct "<<n->cpp_name()<<" /* : public asn1::type */ ;\n";
+    os<<"template ";
+    gen_template_signature(os,params);
+    os<<"\nstd::ostream & operator<<(std::ostream &os,const "<<n->cpp_name();
+    gen_template_params(os,params);
+    os<<" &s) ;\n";
+   
+    // Real declation
+    os<<"template ";
+    gen_template_signature(os,params);
+  }
+
+  //os<<"struct "<<n->cpp_name()<<" /* : public asn1::type */ {\n";
+  // os<<"  int\t\t"<<"kind_;"<<std::endl;
+  os<<"<"<<balise<<" xmi:id=\""<<n->uid();
+  os<<"\" xmi:type=\"uml:Class\"  name=\""<<n->cpp_name()<<"\">"<<std::endl;
+  for (; it != type->end() ; it++)
+  {
+    asn1::field *f = dynamic_cast<asn1::field *>(*it);
+    gen_composite_attribute(os,scope,f,n->parameters());
+  }
+  // Now add an enum tu identifie type
+
+  os<<"</"<<balise<<">";
+  m_Stack.pop_back();
+}
+
+void 
+generate_uml::gen_composite_attribute_ref(std::ostream &os
+            , std::string &scope
+            , asn1::typeref *attribute
+            , asn1::node *_params)
+{
+  asn1::constructed *params = _params->as_constructed();
+  asn1::reference *ref = attribute->get_reference();
+  
+  if (ref->size() > 1) 
+  {
+    // find the object and folow the links ....
+    std::string rname = ref->back().m_identifier;
+//    os<<"\tasn1::Object * /* GCAT "<<rname<<"*/ ";
+  } else {
+    // easy case
+    asn1::node::iterator refm = std::find_if(m_module->begin(),
+                m_module->end(),
+                asn1::find_node(ref->name()));
+    if (refm != m_module->end())
+    {
+      // Here I have the type definition. I should add
+        //os<<"\t"<<ref->cpp_name();
+        os<<" type=\""<<(*refm)->uid()<<"\"";
+        
+    } else 
+    {
+       asn1::node *ns = NULL;
+       if (type_in_imports(ref->name(),&ns) ) {
+         asn1::node *target = NULL;
+         get_type_in_module(ns->name(),ref->name(),&target);
+         asn1::reference::component_const_iterator compit = ref->begin();
+         // Check first element of reference
+         if (target) {
+           os<<" type=\""<<target->uid()<<"\"";
+         }
+         // check if attribute has parameters
+         if (attribute->parameters() != NULL)
+         {
+           os<<"<";
+           for ( asn1::node::iterator it = attribute->parameters()->begin()
+               ; it != attribute->parameters()->end()
+               ; ++it)
+           {
+             asn1::node *ns1 = NULL;
+             if (it != attribute->parameters()->begin())
+               os<<",";
+             // check namespace
+             if (type_in_imports((*it)->name(),&ns1) ) {
+               os<<ns1->cpp_name()<<"::"<<(*it)->cpp_name();
+             } else
+               os<<(*it)->cpp_name();
+           }
+           os<<">";
+
+         }
+       } else if (params) // reference in parameters of definition
+       {
+         bool found = false;
+         for ( asn1::node::iterator it = params->begin()
+             ; it != params->end(); ++it)
+         {
+            if (ref->name().compare((*it)->name())== 0)
+            {
+               os<<"\t"<<(*it)->cpp_name();
+               found = true;
+            }
+         }
+
+       } else
+       {
+       //  os<<" ERROR ";
+       }
+    }
+    
+  }
+}
+
+  
+
+void 
+generate_uml::gen_composite_attribute( std::ostream &os
+                                     , std::string &scope
+                                     , asn1::field *attribute
+                                     , asn1::node *params)
+{
+    asn1::typenode *attr_type = attribute->get_type();
+    if (attr_type != NULL)
+    {
+      switch (attr_type->type_id()())
+      {
+        case asn1::type::ASN1_ENUMERATED:
+          {
+              gen_enumerated( os
+                            , *attr_type->as_enumerated()
+                            , attribute->cpp_name()+"_t"
+                            , true);
+              os<<"<ownedAttribute xmi:id=\"p_"<<attr_type->uid();
+              os<<"\" type=\""<<attr_type->identifier()->uid();
+              os<<"\"  name=\""<<attribute->cpp_name();
+              os<<"\" visibility=\"public\"/>";
+          } 
+          break;
+        case asn1::type::ASN1_SET:
+          {
+              os<<"<ownedAttribute xmi:id=\"set_"<<g_counter;
+              os<<"\" type=\"\"  name=\""<<attribute->cpp_name();
+              os<<"\" visibility=\"public\"/>";
+              g_counter++;
+          }
+          break;
+        case asn1::type::ASN1_CHOICE:
+          {
+              attr_type->name(attribute->cpp_name()+"_t");
+              gen_choice(os,attr_type->as_choice(),true);
+              os<<"<ownedAttribute xmi:id=\"choice_"<<attribute->uid();
+              os<<"\" type=\""<<attr_type->uid()<<"\"  name=\"";
+              os<<attribute->cpp_name()<<"\" visibility=\"public\"/>";
+          }
+          break;
+        case asn1::type::ASN1_SEQUENCE:
+          {
+              std::string scope("\t");
+              attribute->get_type()->name(attribute->cpp_name()+"_t");
+              assert(0);
+                   gen_seq(os,scope,*attribute->get_type()->as_sequence());
+              //os<<"\t\t"<<(attribute)->cpp_name()<<" : \"\",\n";
+              os<<"<ownedAttribute xmi:id=\""<<attribute->uid();
+              os<<"\" type=\""<<attribute->get_type()->uid();
+              os<<"\" name=\""<<attribute->cpp_name();
+              os<<"\" visibility=\"public\"/>";
+              g_counter++;
+          }
+          break;
+        case asn1::type::ASN1_SELECTION:
+          {
+          }
+          break;
+        case asn1::type::ASN1_SET_OF:
+        case asn1::type::ASN1_SEQUENCE_OF:
+          {
+            //std::string scope("");
+            asn1::typenode *type    = attribute->get_type();
+            asn1::typenode *subtype = type->get_eltype();
+            switch (subtype->type_id()())
+            {
+              case asn1::type::ASN1_SEQUENCE:
+                subtype->name((attribute)->cpp_name()+std::string("_type"));
+                gen_seq(os,scope,*subtype->as_sequence());
+                os<<"\n";
+                os<<"<ownedAttribute xmi:id=\"seq_"<<g_counter;
+                os<<"\" visibility=\"public\"";
+                os<<" name=\""<<(attribute)->cpp_name()<<"\"/>\n";
+                g_counter++;
+                break;
+              default:
+                asn1::node *ns;
+                if (type_in_imports(subtype,&ns) ) {
+                  os<<"<ownedAttribute xmi:id=seq1_\""<<g_counter<<"\" visibility=\"public\""<<" name=\""<<(attribute)->cpp_name()<<"\"/>\n";
+                  g_counter++;
+                } else
+                {
+                  asn1::node *tn;
+                  if (get_type_in_module(m_module->name(),subtype->name(),&tn)) {
+                  os<<"<ownedAttribute xmi:id=\""<<g_counter<<"\" type=\""<<tn->uid()<<"\" visibility=\"public\""<<" name=\""<<(attribute)->cpp_name()<<"\">\n";
+                  os<<"<upperValue xmi:type=\"uml:LiteralUnlimitedNatural\" xmi:id=\"_i1AV"<<g_counter<<"\" value=\"*\"/>\n";
+                  os<<"<lowerValue xmi:type=\"uml:LiteralInteger\" xmi:id=\"_i0_uoDsvEeOCl"<<g_counter<<"\"/>\n";
+                  os<<"</ownedAttribute>";
+                  } else
+                  os<<"<ownedAttribute xmi:id=\""<<g_counter<<"\" visibility=\"public\""<<" name=\""<<(attribute)->cpp_name()<<"\"/>\n";
+                  g_counter++;
+                }
+            }
+          }
+          break;
+        case asn1::type::ASN1_REFERENCE:
+          
+        {
+          os<<"<ownedAttribute xmi:id=\""<<g_counter<<"\" ";
+            if (asn1::typeref *ref = attr_type->as_typeref()) {
+              // New way to handle reference
+              gen_composite_attribute_ref(os,scope,ref,params);
+            } else {
+            os<<"type=\"\"";
+          }
+          os<<" name=\""<<attribute->cpp_name()<<"\" visibility=\"public\"/>";
+               g_counter++;
+          os<<std::endl;
+          }
+          break;
+        default:
+          {
+            asn1::node *ns = NULL;
+            os<<"<ownedAttribute  xmi:id=\"def_"<<g_counter;
+            os<<"\" name=\""<<attribute->cpp_name();
+            os<<"\" type=\"\" visibility=\"public\"/>";
+                 g_counter++;
+            os<<"\n";
+          }
+      }
+    }
+}
+
+
+
+/**
+ *
+ */
+void generate_uml::gen_set(std::ostream &os,asn1::set *n)
+{
+  std::string scope("");
+  asn1::constructed *tp = n->as_constructed();
+  asn1::node::iterator it = tp->begin();
+  
+  os<<"<packagedElement xmi:id=\""<<g_counter;
+  os<<"\" xmi:type=\"uml:class\" name=\""<<n->cpp_name()<<"\" >\n";
+  g_counter++;
+  for (; it != tp->end() ; it++)
+  {
+    asn1::field    *f    = dynamic_cast<asn1::field *>(*it);
+    asn1::typenode *type = f->get_type();
+    if (type != NULL)
+    {
+      
+      switch (type->type_id()())
+      {
+        case asn1::type::ASN1_SEQUENCE_OF:
+        case asn1::type::ASN1_SET_OF:
+          {
+            os<<"<ownedAttribute xmi:id=\"setororseqof"<<g_counter<<"\" type=\"\" name=\""<<f->cpp_name()<<"\" visibility=\"public\"/>";
+            g_counter++;
+          }
+          break;
+        default:
+          os<<"<ownedAttribute xmi:id=\"npsetof"<<g_counter<<"\" type=\"\" name=\""<<f->cpp_name()<<"\" visibility=\"public\"/>";
+            g_counter++;
+          os<<"\n";
+      }
+    }
+  }
+  os<<"</packagedElement>\n";
+  
+}
+
+
+
+void generate_uml::gen_object_class_opt(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+  bool opt = false;
+  std::list<std::string> l;
+  for ( ; it != type->end(); ++it)
+  {
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    if ( ((*it)->flags().m_flags & asn1::node::marker_type::FL_OPTIONAL) ) {
+      l.push_back(fieldname);
+    }
+  }
+  if (l.size()>0) {
+    os<<"\tstruct _present { \n";
+    for (std::list<std::string>::const_iterator it = l.begin(); it != l.end(); ++it)
+    {
+      if (1) {
+        os<<"\t\t";
+          os<<"unsigned  present"<<(*it)<<" : 1;\n";
+      }else {
+          os<<"\t\tunsigned present"<<(*it)<<" : 1\n";
+      }
+    }
+    os<<"\t} m;\n";
+  }
+}
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_object_class_missing(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+  
+  // cosntructors
+
+  // generate optionnals
+
+  // public methods 
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::field *ltype = dynamic_cast<asn1::field *>(*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_FTVF:    /* Fixed Type Value Field       */
+        os<<std::endl;
+        // call missing here
+        gen_missing(os,ltype->get_type());
+        break;
+      case asn1::type::ASN1_CLASSFIELD_TF:      /* Type Field                   */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVF:    /* Variable Type Value Field    */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_FTVSF:   /* Fixed Type Value Set Field   */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVSF:   /* Variable Type Value Set Field*/
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OF:      /* Object Field                 */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OSF:     /* Object Set Field             */
+        os<<std::endl;
+        break;
+      break;
+      default:
+        os<<std::endl;
+    };
+  }
+}
+
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_object_class_interface(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+  
+  os<<"<packagedElement xmi:id=\""<<n->uid()<<"\" xmi:type=\"uml:Interface\" name=\"I"<<n->cpp_name()<<"\">\n";
+
+  // public methods 
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::node *ltype = (*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_FTVF:    /* Fixed Type Value Field       */
+        os<<"<ownedOperation xmi:id=\"ape_"<<ltype->uid()<<"\" name=\""<<fieldname.substr(1)<<"Equals\"/>\n";
+        break;
+      case asn1::type::ASN1_CLASSFIELD_TF:      /* Type Field                   */
+        os<<"<ownedOperation xmi:id=\"op_"<<ltype->uid()<<"\" name=\"codec"<<fieldname<<"\"/>\n";
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVF:    /* Variable Type Value Field    */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_FTVSF:   /* Fixed Type Value Set Field   */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVSF:   /* Variable Type Value Set Field*/
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OF:      /* Object Field                 */
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OSF:     /* Object Set Field             */
+        os<<std::endl;
+        break;
+      break;
+      default:
+        os<<std::endl;
+    };
+  }
+  os<<"</packagedElement>"<<std::endl;
+}
+
+
+void generate_uml::gen_object_class_attributes(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::classfield *ltype = dynamic_cast<asn1::classfield *>(*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    os<<"\t//"<<(*it)->cpp_name()<<" type_id="<<(*it)->type_id()();
+    //<<std::endl;
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_FTVF:    /* Fixed Type Value Field       */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_TF:      /* Type Field                   */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVF:    /* Variable Type Value Field    */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_FTVSF:   /* Fixed Type Value Set Field   */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_VTVSF:   /* Variable Type Value Set Field*/
+        os<<std::endl;
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OF:      /* Object Field                 */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_OSF:     /* Object Set Field             */
+        break;
+      break;
+      default:
+        os<<std::endl;
+    };
+  }
+
+}
+
+
+void 
+generate_uml::gen_object_class_printf(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+  
+  for ( ; it != type->end(); ++it)
+  {
+    asn1::node *ltype = (*it);
+    std::string fieldname = (*it)->cpp_name();
+    fieldname[0] = '_';
+    
+    switch(ltype->type_id()())
+    {
+      case asn1::type::ASN1_CLASSFIELD_FTVF:    /* Fixed Type Value Field       */
+        break;
+      case asn1::type::ASN1_CLASSFIELD_TF:      /* Type Field                   */
+        if ( (ltype->flags().m_flags & asn1::node::marker_type::FL_OPTIONAL) ) 
+       {
+         os<<"\t  if (m.present"<<fieldname<<")"<<std::endl;
+       } 
+        os<<"\t\tos<<\""<<ltype->cpp_name();
+        os<<"\t"<<" : \"<<m"<<fieldname<<"<<std::endl;\n";
+        break;
+     default:
+     ;
+    }  
+  
+  }  
+  os<<"\t};\n";
+}
+/**
+ *
+ *
+ */
+void generate_uml::gen_object_class(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  
+  gen_object_class_missing(os,n);
+  gen_object_class_interface(os,n);
+  
+  // generate optionnals
+  gen_object_class_printf(os,n);
+  gen_object_class_opt(os,n);
+
+  // public methods 
+  gen_object_class_attributes(os,n);
+}
+/**
+ *
+ *
+ */
+void generate_uml::gen_object(std::ostream &os,asn1::assignment *n)
+{
+  asn1::constructed *type = n->get_type()->as_constructed();
+  asn1::node::iterator it = type->begin();
+//  os<<"// generate_uml::"<<__FUNCTION__<<" "<<n->name()<<"\n";
+  os.flush();
+  if (!type->name().compare("OPERATION"))
+  {
+    gen_object_operation(os,n);
+  } else 
+  if (!type->name().compare("ERROR"))
+  {
+    gen_object_error(os,n);
+  } else if (!type->name().compare("OBJECT-TYPE"))
+  {
+  }
+}
+
+
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_object_error(std::ostream &os,asn1::node *n)
+{
+}
+
+
+void generate_uml::gen_object_operation(std::ostream &os,asn1::node *n) 
+{
+}
+
+/**
+ *
+ *
+ */
+void generate_uml::gen_object_operation_package(std::ostream &os,asn1::node *n) 
+{
+}
+void generate_uml::gen_object_connection(std::ostream &os,asn1::node *n) 
+{
+}
+
+
+class douml_assignment : public assignment_visitor<douml_assignment>
+{
+  public:
+    douml_assignment(std::ostream &_os,generate_uml &_gen)
+      : m_os(_os) , m_gen(_gen)
+    {
+    }
+#define ASSIGNMENT(En,Tp,Parent,Code) \
+    void visit_##Tp(asn1::Tp##_assignment *a) \
+    Code
+ASSIGNMENT(TYPEREF,typeref,assignment,{
+    m_gen.gen_typeref(m_os,a->get_type()->as_typeref());
+    })
+ASSIGNMENT(TYPE,type,assignment,{
+    m_gen.gen_typedef(m_os,a->get_type());
+    })
+ASSIGNMENT(VALUE,value,assignment,{
+    m_gen.gen_const(m_os,a->get_type());
+    })
+ASSIGNMENT(VALUESET,valueset,assignment,{
+    std::cout<<__FUNCTION__<<" TODO"<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECT,object,assignment,{
+    m_gen.gen_object(m_os,a);
+    })
+ASSIGNMENT(OBJECTCLASS,objectclass,assignment,{
+    m_gen.gen_object_class(m_os,a);
+    })
+ASSIGNMENT(OBJECTSET,objectset,assignment,{
+    std::cout<<__FUNCTION__<<" TODO"<<a->name()<<std::endl;
+    })
+ASSIGNMENT(OBJECTFIELD,objectfield,assignment,{
+    std::cout<<__FUNCTION__<<" TODO"<<a->name()<<std::endl;
+    })
+
+    void visit_assignment(asn1::assignment *a)
+    {}
+#undef ASSIGNMENT
+
+  protected:
+    generate_uml &m_gen;
+    std::ostream &m_os;
+};
+
+/**
+ *
+ */
+void generate_uml::gen_module(std::ostream &os,asn1::module *n)
+{
+  asn1::import_list *imports = n->imports();
+  std::fstream umlos;
+  std::string umlname = std::string(n->name()+".uml");
+  umlos.open(umlname.c_str(),std::fstream::out);
+  umlos<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<std::endl;
+  umlos<<"<xmi:XMI xmi:version=\"2.1\" ";
+  umlos<<"xmlns:xmi=\"http://schema.omg.org/spec/XMI/2.1\"";
+  umlos<<" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
+  umlos<<" xmlns:Cpp=\"http:///schemas/Cpp/www.ebersold.fr/modeling/cpp/0\" ";
+  umlos<<" xmlns:uml=\"http://www.eclipse.org/uml2/3.0.0/UML\"";
+  umlos<<" xsi:schemaLocation=\"http:///schemas/Cpp/www.ebersold.fr/modeling/cpp/0 \">";
+  umlos<<"<uml:Package xmi:id=\"pkg_"<<n->cpp_name()<<g_counter;
+  umlos<<"\" name=\""<<n->cpp_name()<<"\">"<<std::endl;
+
+  g_counter++;
+  n->sort_childs();
+  asn1::node::iterator it = n->begin();
+  
+  for (; it != n->end() ; it++)
+  {
+    asn1::assignment *a = dynamic_cast<asn1::assignment *>(*it);
+    GEN_LOG_DEBUG("Process item %s\n",a->name().c_str());
+    if (a->get_type() != NULL)
+    {
+     if ( a->is_generated())
+     {
+       GEN_LOG_DEBUG("item %s already generated\n",a->name().c_str());
+       continue;
+     }
+     douml_assignment douml(umlos,*this);
+     douml.visit(a);
+     os<<std::endl;
+     (*it)->set_color(asn1::node::CL_RED);
+    } else 
+    {
+        GEN_LOG_WARN("item %s of undefined type \n",(*it)->name().c_str());
+    }
+    os<<std::endl; 
+
+  }
+  umlos<<"</uml:Package>";
+  umlos<<"</xmi:XMI>";
+  umlos.close();
+}
+
+/**
+* vim:et:sw=2:ts=2
+*/
diff --git a/libgen/uml/asn1_gen_uml.h b/libgen/uml/asn1_gen_uml.h
new file mode 100644 (file)
index 0000000..991e5ed
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef GEN_HEADER_UML_H__
+#define GEN_HEADER_UML_H__
+#include <iostream>
+#include <algorithm>
+
+
+/**
+ *
+ */
+class generate_uml : public asn1::generator
+{
+  public:
+
+    generate_uml(asn1::module *n); 
+    
+    generate_uml(asn1::module *n,asn1::module::modules_type &m); 
+    
+    virtual ~generate_uml() {} ; 
+   
+
+    void gen_missing(std::ostream &os,asn1::typenode *n) ;
+
+    /**
+     *
+     *
+     */
+    void gen_const(std::ostream &os,asn1::node *n);
+    
+    void gen_enumerated( std::ostream &os
+                       , asn1::enumerated &n 
+                       , const std::string &name
+                       , bool nested = false);
+    //
+    //
+    //
+    void gen_typedef(std::ostream &os,asn1::typenode *n);
+    void gen_typeref(std::ostream &os,asn1::typeref *n);
+    
+    /**
+     *
+     */
+    void gen_seq( std::ostream &os
+                , std::string &scope
+                , asn1::sequence &n
+                );
+    
+    void gen_choice( std::ostream &os
+                   , asn1::choice *n
+                   , bool nested=false);
+    
+    void gen_composite_attribute( std::ostream &os
+                                , std::string  &scope
+                                , asn1::field  *attribute
+                                , asn1::node   *params = NULL);
+
+    void gen_composite_attribute_ref( std::ostream &os
+                                    , std::string &scope
+                                    , asn1::typeref *attribute
+                                    , asn1::node *params = NULL);
+
+    void gen_template_params(std::ostream &os,asn1::node *params);
+
+    void gen_template_signature(std::ostream &os,asn1::node *params);
+    
+    /**
+     *
+     */
+    void gen_set( std::ostream &os
+                , asn1::set *n);
+
+    /*
+     * Ros generation Code
+     */
+    void gen_object_class(std::ostream &os,asn1::assignment *n); 
+    void gen_object_class_interface(std::ostream &os,asn1::assignment *n);
+    void gen_object_class_missing(std::ostream &os,asn1::assignment *n);
+    void gen_object_class_opt(std::ostream &os,asn1::assignment *n); 
+    void gen_object_class_attributes(std::ostream &os,asn1::assignment *n); 
+  
+    void gen_object_class_printf(std::ostream &os, asn1::assignment *n);
+    void gen_object(std::ostream &os,asn1::assignment *n); 
+    void gen_object_error(std::ostream &os,asn1::node *n); 
+    void gen_object_operation(std::ostream &os,asn1::node *n); 
+    void gen_object_operation_package(std::ostream &os,asn1::node *n); 
+    void gen_object_connection(std::ostream &os,asn1::node *n); 
+    /**
+     *
+     */
+    void gen_module(std::ostream &os,asn1::module *n);
+  protected:
+    std::vector<std::string>  m_Stack;
+};
+/**
+ * vim:et:sw=2:ts=2
+ */
+#endif
diff --git a/libparser/CMakeLists.txt b/libparser/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b2c9902
--- /dev/null
@@ -0,0 +1,60 @@
+PROJECT(libasn1parser)
+
+IF(CMAKE_CROSSCOMPILING)
+    SET(IMPORT_EXECUTABLES "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point to the
+    export file from native build")
+    INCLUDE(${IMPORT_EXECUTABLES})
+ENDIF(CMAKE_CROSSCOMPILING)
+
+
+# Only for Linux not MAC
+IF(APPLE)
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG ")
+ELSEIF(WIN32)
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG ")
+ELSE(APPLE)
+  SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -std=c++0x")
+  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
+ENDIF(APPLE)
+
+INCLUDE(${rules_SOURCE_DIR}/flex.cmake)
+
+
+LEXGEN(asn1.l lasn1.cpp)
+BISONGEN(asn1.y pasn1.cpp cpp)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libgen)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../adt)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${aebutils_SOURCE_DIR})
+
+IF (NOT CMAKE_CROSSCOMPILING)
+ADD_LIBRARY(libasn1p 
+    lasn1.cpp
+    pasn1.cpp
+    asn1_parser.cpp
+    )
+TARGET_LINK_LIBRARIES(libasn1p asn1adt)
+
+  MESSAGE("Export Executables to ${CMAKE_BINARY_DIR}")
+  EXPORT(TARGETS libasn1p asn1adt FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake
+      NAMESPACE native-)
+ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+#IF(CMAKE_CROSSCOMPILING)
+#    SET(asn1p_EXE native-asn1p)
+#    GET_TARGET_PROPERTY(test ${asn1p_EXE} IMPORTED_LOCATION_DEBUG)
+#    SET(asn1p_EXE ${test})
+#ELSE(CMAKE_CROSSCOMPILING)
+#    SET(asn1p_EXE ${CMAKE_CURRENT_BINARY_DIR}/asn1p)
+#ENDIF(CMAKE_CROSSCOMPILING)
+
+
+# Install Stuff
+#IF (NOT CMAKE_CROSSCOMPILING)
+#INSTALL(TARGETS asn1p
+#      DESTINATION bin/)
+#ENDIF(NOT CMAKE_CROSSCOMPILING)
+
+
diff --git a/libparser/asn1.l b/libparser/asn1.l
new file mode 100644 (file)
index 0000000..c5067d1
--- /dev/null
@@ -0,0 +1,393 @@
+%{
+#include <cstdio>
+#include <stdio.h>
+#include <errno.h>
+
+//#include "lasn1.hpp"
+#include "asn1_node.h"
+#include "asn1_constraint.h"
+#include "asn1_module.h"
+
+/*
+%option never-interactive
+*/
+#if 0
+#undef  YYSTYPE
+typedef  union
+{
+  asn1::node        *node;
+  asn1::constraint  *constraint;
+  asn1::module      *module;
+} YYSTYPE;
+#define YYSTYPE_IS_DECLARED 1
+//#define YYSTYPE asn1::node 
+#define YYPARSER_PARAM yylval
+#define YYLEX_PARAM yylval
+#define YY_DECL int _asn1_lex(asn1::node *yylval)
+  asn1::node                 *node;
+  asn1::constraint           *constraint;
+  asn1::module               *module;
+  asn1::reference            *reference;
+  asn1::reference::component *ref_comp;
+  asn1::value                *value;
+  asn1::node::tag_type        tag;
+  asn1::node::marker_type    *marker;
+} YYSTYPE;
+#else 
+typedef  union
+{
+  asn1::node                 *node;
+  asn1::constraint           *constraint;
+  asn1::module               *module;
+  asn1::reference            *reference;
+  asn1::reference::component *ref_comp;
+} YYSTYPE;
+#define YYSTYPE_IS_DECLARED 1
+#define YY_DECL int _asn1_lex(YYSTYPE *yylval)
+#endif 
+
+#include "pasn1.hpp"
+
+long
+asn1_atoi(const char *ptr);
+
+void _asn1_error(const char *s) {
+  printf("Failed line: %d %s  <%s>\n",yylineno,s,yytext);
+#if 1
+  exit(1);
+#endif
+};
+
+#define TOK(x) {return x;}
+#define REF_TF        { yylval->reference = new asn1::typefield_reference(yytext);return T_TYPEFIELDREFERENCE;}
+#define REF_VF        { yylval->reference = new asn1::valuefield_reference(yytext);return T_VALUEFIELDREFERENCE;}
+#define NODE_TOK(x)   { yylval->node = new asn1::node(yytext);return x;}
+
+#define NUM_TOK(x)    { asn1::valuetype *vt = new asn1::valuetype(std::string(yytext),NULL);\
+                        (yylval)->node = vt; \
+                        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER); \
+                        v->m_integer = asn1_atoi(yytext);\
+                        vt->value(v); \
+                        vt->value_long(asn1_atoi(yytext)); \
+                        return x;\
+                      }
+
+#define NUMV_TOK(x,val)   { asn1::valuetype *vt = new asn1::valuetype(std::string(yytext),NULL);\
+                        (yylval)->node = vt; \
+                        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER); \
+                        v->m_integer = val;\
+                        (yylval)->node->value(v); \
+                        (yylval)->node->value_long(val); \
+                        return x;\
+                      }
+#define DOUBLE_TOK(x) { *yylval = new asn1::valuetype(std::string(yytext),NULL);return x;}
+%}
+
+%option prefix="_asn1_"
+%option stack
+%option yylineno
+/*
+%option noyywrap stack
+%option debug
+*/
+%pointer
+
+%x dash_comment
+%x idash_comment
+%x cpp_comment
+%x quote
+%x opaque
+%x encoding_control
+%x with_syntax
+%x object
+
+/* */
+Digits          [0-9]+
+NDigits         -{Digits}
+
+Real            [-+]?[0-9]+[.]?([eE][-+]?)?[0-9]+
+
+
+
+Char            ([^\n\t\"\'\\])
+Char_Literal    "'"({Char}|\")"'"
+String_Literal  \"({Char}|"'")*\"
+HString         '[0-9A-F \r\r\v\f\n]+'H
+BString         '[01 \t\r\v\f\n]+'B
+Identifier      [a-z][a-zA-Z0-9]*([-][a-zA-Z0-9]+)*
+CapitalReference    [A-Z][A-Z0-9]*([-][A-Z0-9]+)*
+TypeReference       [A-Z][A-Za-z0-9]*([-][A-Za-z0-9]+)*
+
+TypeFieldReference  &{TypeReference}
+ValueFieldReference &{Identifier}
+
+nl  [\r\n\v\f]
+
+wsp [\t\r\v\f\n ]
+
+%%
+
+-{3,}/[\r\n] /* Comment */
+
+<INITIAL,with_syntax>-- yy_push_state(dash_comment);
+<INITIAL,object>-- yy_push_state(dash_comment);
+
+<dash_comment>{ /* Very special to treat rules for dash_comment rules */
+    {nl}    yy_pop_state();
+    --      yy_pop_state();
+    -       /* single dash */
+    [^\r\v\f\n-]+ /* do nothing */
+}
+
+<INITIAL,cpp_comment>"/*" yy_push_state(cpp_comment);
+
+<cpp_comment>{
+    [^*/<]  /* skip */
+    "*/"    yy_pop_state();
+    .       /* skip */
+}
+
+"::="           TOK(T_ASSIGN)
+
+{BString}       TOK(T_bstring)
+{Digits}        NUM_TOK(T_NUM)
+{NDigits}       NUM_TOK(T_NUM)
+
+ABSENT          TOK(T_ABSENT)
+ABSTRACT        TOK(T_ABSTRACT)
+ABSTRACT-SYNTAX TOK(T_ABSTRACT_SYNTAX)
+ALL             TOK(T_ALL)
+ANY             TOK(T_ANY)
+APPLICATION     TOK(T_APPLICATION)
+AUTOMATIC       TOK(T_AUTOMATIC)
+BEGIN           TOK(T_BEGIN)
+BIT             TOK(T_BIT)
+
+BMPString       TOK(T_BMPString)
+BOOLEAN         TOK(T_BOOLEAN)
+BY              TOK(T_BY)
+CHARACTER       TOK(T_CHARACTER)
+CHOICE          TOK(T_CHOICE)
+CLASS           TOK(T_CLASS)
+COMPONENT       TOK(T_COMPONENT)
+COMPONENTS      TOK(T_COMPONENTS)
+CONTAINING      TOK(T_CONTAINING)
+CONSTRAINED     TOK(T_CONSTRAINED)
+DATE            TOK(T_DATE)
+DATE-TIME       TOK(T_DATE_TIME)
+DEFAULT         TOK(T_DEFAULT)
+DEFINED         TOK(T_DEFINED) /* Not reserved word in ASN1 may be old parser (ANY DEFINED BY) */
+
+DEFINITIONS     TOK(T_DEFINITIONS)
+DURATION        TOK(T_DURATION)
+EMBEDDED
+ENCODED             TOK(T_ENCODED)
+ENCODING-CONTROL    TOK(T_ENCODING_CONTROL)
+END                 TOK(T_END)
+ENUMERATED          TOK(T_ENUMERATED)
+EXCEPT              TOK(T_EXCEPT)
+EXPLICIT            TOK(T_EXPLICIT)
+EXPORTS             TOK(T_EXPORTS)
+EXTENSIBILITY       TOK(T_EXTENSIBILITY)
+EXTERNAL            TOK(T_EXTERNAL)
+FALSE               TOK(T_ASN1_FALSE)
+FROM                TOK(T_FROM)
+GeneralizedTime     TOK(T_GeneralizedTime)
+GeneralString       TOK(T_GeneralizedString)
+GraphicString       TOK(T_GraphicString)
+{HString}           TOK(T_hstring)
+IA5String           TOK(T_IA5String)
+IDENTIFIER          TOK(T_STR_IDENTIFIER)
+IMPLICIT            TOK(T_IMPLICIT)
+IMPLIED             TOK(T_IMPLIED)
+IMPORTS             TOK(T_IMPORTS)
+INCLUDES            TOK(T_INCLUDES)
+INSTANCE            TOK(T_INSTANCE)
+INSTRUCTIONS        TOK(T_INSTRUCTIONS)
+INTEGER             TOK(T_INTEGER)
+INTERSECTION        TOK(T_INTERSECTION)
+ISO64String         TOK(T_ISO646String)
+MAX                 TOK(T_MAX)
+MIN                 TOK(T_MIN)
+MINUS-INFINITY      TOK(T_MINUS_INFINITY)
+NOT-A-NUMBER        TOK(T_NOT_A_NUMBER)
+NULL                TOK(T_NULL)
+NumericString       TOK(T_NumericString)
+ObjectDescriptor    TOK(T_ObjectDescriptorString)
+OBJECT              TOK(T_OBJECT)
+OCTET               TOK(T_OCTET)
+OF                  TOK(T_OF)
+OID-IRI             TOK(T_OID_IRI)
+OPTIONAL            TOK(T_OPTIONAL)
+PATTERN             TOK(T_PATTERN)
+PDV
+PLUS-INFINITY
+PRESENT             TOK(T_PRESENT)
+PrintableString     TOK(T_PrintableString)
+PRIVATE
+REAL                TOK(T_REAL)
+RELATIVE-OID        TOK(T_RELATIVE_OID)
+RELATIVE-OID-IRI    TOK(T_RELATIVE_OID_IRI)
+SEQUENCE            TOK(T_SEQUENCE)
+SET                 TOK(T_SET)
+SETTINGS            TOK(T_SETTINGS)
+SIZE                TOK(T_SIZE)
+STRING              TOK(T_STRING)
+SYNTAX              TOK(T_SYNTAX)
+T61String           TOK(T_T61String)
+TAGS                TOK(T_TAGS)
+TeletexString       TOK(T_TeletexString)
+TIME                TOK(T_TIME)
+TIME-OF-DAY         TOK(T_TIME_OF_DAY)
+TRUE                TOK(T_ASN1_TRUE)
+UNION               TOK(T_UNION)
+UNIQUE              TOK(T_UNIQUE)
+UNIVERSAL           TOK(T_UNIVERSAL)
+UniversalString     TOK(T_UniversalString)
+
+UTCTime             TOK(T_UTCTime)
+UTF8String          TOK(T_UTF8String)
+
+VideotextString     TOK(T_VideotextString)
+VisibleString       TOK(T_VisibleString)
+WITH                TOK(T_WITH)
+
+
+
+
+{Identifier}           NODE_TOK(T_IDENTIFIER)
+{String_Literal}       NODE_TOK(T_IDENTIFIER)
+{CapitalReference}     NODE_TOK(T_CAPITALREFERENCE)
+{TypeReference}        NODE_TOK(T_TYPEREFERENCE)
+{TypeFieldReference}   REF_TF
+{ValueFieldReference}  REF_VF
+
+[{][\t\r\v\f\n ]*[0-7][,][\t\r\v\f\n ]*[0-9]+[\t\r\v\f\n ]*[}] {
+  TOK(T_Tuple)
+}
+
+
+[{][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[,][\t\r\v\f\n ]*[0-9]+[\t\r\v\f\n ]*[}]  {
+    TOK(T_Quadruple)
+  }
+
+
+"<"             TOK(T_LT)
+"@"             TOK(T_AT)
+"!"             TOK(T_EXCLAMATION)
+"["             TOK(T_LBRACKET)
+"]"             TOK(T_RBRACKET)
+"{"             TOK(T_LBRACET)
+"}"             TOK(T_RBRACET)
+")"             TOK(T_RPARENTHESES)
+"("             TOK(T_LPARENTHESES)
+"."            TOK(T_POINT)
+".."            TOK(T_TWOPOINT)
+"..."           TOK(T_THREEPOINT)
+","             TOK(T_COMMA)
+";"             TOK(T_SIMILICON)
+":"             TOK(T_COLON)
+"|"             TOK(T_UNION)
+"^"             TOK(T_EXCEPT)
+"_"             TOK(T_USCORE)
+{wsp}+  /* ignore whitespace*/
+
+<with_syntax>{
+   {CapitalReference} NODE_TOK(T_CAPITALREFERENCE)
+   {TypeFieldReference}  REF_TF
+   {ValueFieldReference} REF_VF
+   ","  TOK(T_COMMA)
+   "}"  TOK(T_RBRACET)
+   "["             TOK(T_LBRACKET)
+   "]"             TOK(T_RBRACKET)
+   {wsp}+  /* ignore whitespace*/
+}
+
+<object>{
+       INTEGER             TOK(T_INTEGER)
+       {Identifier}            NODE_TOK(T_IDENTIFIER)
+       {String_Literal}        NODE_TOK(T_IDENTIFIER)
+       {CapitalReference}      NODE_TOK(T_CAPITALREFERENCE)
+       {TypeReference}         NODE_TOK(T_TYPEREFERENCE)
+       {TypeFieldReference}    REF_TF
+       {ValueFieldReference}   REF_VF
+       "{"             TOK(T_LOBJBRACET)
+       "}"             TOK(T_RBRACET)
+       "<"             TOK(T_LT)
+       "@"             TOK(T_AT)
+       "!"             TOK(T_EXCLAMATION)
+       "["             TOK(T_LBRACKET)
+       "]"             TOK(T_RBRACKET)
+       ")"             TOK(T_RPARENTHESES)
+       "("             TOK(T_LPARENTHESES)
+       "."             TOK(T_POINT)
+       ".."            TOK(T_TWOPOINT)
+       "..."           TOK(T_THREEPOINT)
+       ","             TOK(T_COMMA)
+       ";"             TOK(T_SIMILICON)
+       ":"             TOK(T_COLON)
+       "|"             TOK(T_UNION)
+       "^"             TOK(T_EXCEPT)
+       {wsp}+  /* ignore whitespace*/
+
+}
+
+
+<encoding_control>{
+
+    . /**/
+    END unput('D'); unput('N'); unput('E'); yy_pop_state();
+  }
+
+%%
+#if 0
+itu-t                 NUMV_TOK(T_NUM,0)
+iso                   NUMV_TOK(T_NUM,1)
+joint-iso-itu-t       NUMV_TOK(T_NUM,2)
+joint-iso-ccitt       NUMV_TOK(T_NUM,2)
+#endif
+void enable_with_syntax()
+{
+    yy_push_state(with_syntax);
+}
+void disable_with_syntax()
+{
+    yy_pop_state();
+}
+
+void enable_encoding_control()
+{
+    yy_push_state(encoding_control);
+}
+
+void enable_object()
+{
+    yy_push_state(object);
+}
+void disable_object()
+{
+    yy_pop_state();
+}
+
+
+
+long
+asn1_atoi(const char *ptr)
+{
+    long ret;
+    return atol(ptr);
+}
+
+double
+asn1_atod(const char *ptr)
+{
+    double ret;
+    errno = 0;
+    ret = strtod(ptr,0);
+    if (errno)
+    {
+        std::cerr<<" Value out range : "<<ptr<<std::endl;
+    }
+
+    return ret;
+}
diff --git a/libparser/asn1.y b/libparser/asn1.y
new file mode 100644 (file)
index 0000000..f102f2c
--- /dev/null
@@ -0,0 +1,3330 @@
+%{\r
+\r
+#include <sstream>\r
+#include <fstream>\r
+#include <cstdio>\r
+#include <assert.h>\r
+#include <stdio.h>\r
+#include <sys/stat.h>\r
+#include <sys/types.h>\r
+#ifndef _WIN32\r
+#include <unistd.h>\r
+#endif\r
+#include "asn1_node.h"\r
+#include "asn1_constraint.h"\r
+#include "asn1_reference.h"\r
+#include "asn1_value.h"\r
+#include "asn1_parser.h"\r
+\r
+typedef  union\r
+{\r
+  asn1::node                 *node;\r
+  asn1::constraint           *constraint;\r
+  asn1::module               *module;\r
+  asn1::reference            *reference;\r
+  asn1::reference::component *ref_comp;\r
+  asn1::value                *value;\r
+  asn1::node::tag_type        tag;\r
+  asn1::node::marker_type    *marker;\r
+  asn1::syntax_parser::fragment    *fragment;\r
+  asn1::classfield           *classfield;\r
+  asn1::parameter            *parameter;\r
+  asn1::assignment           *assignment;\r
+} YYSTYPE;\r
+#define YYSTYPE_IS_DECLARED 1\r
+\r
+#if defined(__MINGW32__)\r
+#  define SIZE_T_SPECIFIER "%Iu"\r
+#elif defined(__GNUC__) || defined(__APPLE__)\r
+#  define SIZE_T_SPECIFIER "%zu"\r
+#else\r
+#  define SIZE_T_SPECIFIER "%ld"\r
+#endif\r
+extern  void _asn1_error( const char *s);\r
+extern  int _asn1_lex(YYSTYPE *yylval);\r
+extern void enable_with_syntax(void);\r
+extern void enable_encoding_control(void);\r
+extern void disable_with_syntax(void);\r
+extern void enable_object(void);\r
+extern void disable_object(void);\r
+//#include "lasn1.cpp"\r
+\r
+static\r
+asn1::parser *gParser = asn1::parser::instance();\r
+\r
+#if defined(__GNUC__) && defined(DEBUG)\r
+#define ASN_LOG_DEBUG(fmt,args...) do {\\r
+  char _lbuf[256]; \\r
+  if ( gLog.is_open()) { \\r
+    gLog<<"DEBUG "; \\r
+    sprintf(_lbuf,fmt,##args); gLog<<_lbuf; \\r
+    sprintf(_lbuf," (asn1.y : %d)\n",__LINE__); gLog<<_lbuf; \\r
+  } else if (gParser->debug_console() ) { \\r
+  fprintf(stderr,"asn1_parser (DEBUG): "); \\r
+  fprintf(stderr,fmt,##args);\\r
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\\r
+  } \\r
+} while (0)\r
+\r
+#define ASN_LOG_WARNING(fmt,args...) do {\\r
+  char _lbuf[256]; \\r
+  if (gLog.is_open()) { \\r
+    gLog<<"WARN "; \\r
+    sprintf(_lbuf,fmt,##args); gLog<<_lbuf; \\r
+    sprintf(_lbuf," (asn1.y : %d)\n",__LINE__); gLog<<_lbuf; \\r
+  }  \\r
+  fprintf(stderr,"asn1_parser (WARNI): "); \\r
+  fprintf(stderr,fmt,##args);\\r
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\\r
+} while (0)\r
+\r
+#define ASN_LOG_ERROR(fmt,args...) do {\\r
+  char _lbuf[256]; \\r
+  if ( gLog.is_open()) { \\r
+    gLog<<"ERROR "; \\r
+    sprintf(_lbuf,fmt,##args); gLog<<_lbuf; \\r
+    sprintf(_lbuf," (asn1.y : %d)\n",__LINE__); gLog<<_lbuf; \\r
+  }  \\r
+  fprintf(stderr,"asn1_parser (ERROR): "); \\r
+  fprintf(stderr,fmt,##args);\\r
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\\r
+} while (0)\r
+\r
+static std::fstream gLog;\r
+\r
+void open_log(const std::string &fn)\r
+{\r
+  struct stat st;\r
+  // Check if gLog directory exists\r
+  if (stat("log",&st) == -1 ) {\r
+#ifdef WIN32\r
+      mkdir("log");\r
+#else\r
+      mkdir("log",0777);\r
+#endif\r
+  }\r
+  // \r
+  std::string _logname("log/"); _logname.append(fn); _logname.append(".parser.log");\r
+  if ( gLog.is_open())\r
+  {\r
+    std::cerr<<"open_log "<<fn<<" already open ?"<<std::endl;\r
+  } else  \r
+  {\r
+    gLog.open(_logname.c_str(),std::fstream::out | std::fstream::app);\r
+  }\r
+}\r
+\r
+void close_log()\r
+{\r
+  if ( gLog.is_open() ) \r
+    gLog.close();\r
+}\r
+#elif defined(_WIN32)\r
+  static std::fstream gLog;\r
+  void open_log(const std::string &fn) {\r
+  }\r
+  void close_log() {\r
+  }\r
+#define ASN_LOG_DEBUG(fmt,...) \\r
+  do { printf(fmt "\n" , __VA_ARGS__); } while(0)\r
+#define ASN_LOG_ERROR(fmt,...) \\r
+  do { printf(fmt "\n" , __VA_ARGS__); } while(0)\r
+#define ASN_LOG_WARNING(fmt,...) \\r
+  do { printf(fmt "\n" , __VA_ARGS__); } while(0)\r
+#else\r
+  static std::fstream gLog;\r
+  void open_log(const std::string &fn) {\r
+  }\r
+  void close_log() {\r
+  }\r
+  static inline void ASN_LOG_DEBUG(const char *fmt,...) {(void)fmt;};\r
+  static inline void ASN_LOG_ERROR(const char *fmt,...) {(void)fmt;};\r
+  static inline void ASN_LOG_WARNING(const char *fmt,...) {(void)fmt;};\r
+#endif\r
+\r
+typedef std::map<std::string,asn1::valuetype *> OidMapType;\r
+typedef OidMapType::iterator OidMapIterator;\r
+typedef OidMapType::const_iterator OidMapConstIterator;\r
+\r
+static  OidMapType oid_map;\r
+\r
+static asn1::module * get_current_module ( void )\r
+{\r
+        asn1::parser *p = asn1::parser::instance();\r
+        return  (asn1::module *) p->module();\r
+}\r
+static asn1::reference * current_ref;\r
+static asn1::classdef *gCurrentClassDef = NULL;\r
+\r
+%}\r
+\r
+%token T_ABSENT\r
+%token T_ABSTRACT\r
+%token T_ABSTRACT_SYNTAX\r
+%token T_ALL\r
+%token T_ANY\r
+%token T_APPLICATION\r
+%token T_ASN1_TRUE\r
+%token T_ASN1_FALSE\r
+%token T_ASSIGN\r
+%token T_AT\r
+%token T_AUTOMATIC\r
+%token T_BEGIN\r
+%token T_BIT\r
+%token T_BOOLEAN\r
+%token T_BY\r
+%token <node>T_CAPITALREFERENCE\r
+%token T_CHARACTER\r
+%token T_CHOICE\r
+%token T_CLASS\r
+%token T_COLON\r
+%token T_COMPONENT\r
+%token T_COMPONENTS\r
+%token T_CONTAINING\r
+%token T_DATE\r
+%token T_DATE_TIME\r
+%token T_CONSTRAINED\r
+%token T_DEFAULT\r
+%token T_DEFINITIONS\r
+%token T_DURATION\r
+%token T_ENCODED\r
+%token T_ENCODING_CONTROL\r
+%token T_END\r
+%token T_EXPLICIT\r
+%token T_EXCEPT\r
+%token T_EXCLAMATION\r
+%token T_EXPORTS\r
+%token T_EXTENSIBILITY\r
+%token T_EXTERNAL\r
+%token <node>T_IDENTIFIER\r
+%token T_IMPLICIT\r
+%token T_IMPLIED\r
+%token T_INCLUDES\r
+%token T_INSTANCE\r
+%token T_INSTRUCTIONS\r
+%token <node>T_INTEGER\r
+%token T_INTERSECTION\r
+%token T_LT\r
+%token T_MAX\r
+%token T_MIN\r
+%token T_MINUS_INFINITY\r
+%token T_NOT_A_NUMBER\r
+%token T_NULL\r
+%token <node>T_NUM\r
+%token T_OCTET\r
+%token T_OPTIONAL\r
+%token T_OF\r
+%token T_OID_IRI\r
+%token T_OBJECT\r
+%token T_Quadruple\r
+%token T_POINT\r
+%token T_PATTERN\r
+%token T_PRESENT\r
+%token T_PRIVATE\r
+%token T_REAL\r
+%token T_RELATIVE_OID\r
+%token T_RELATIVE_OID_IRI\r
+%token T_SIMILICON\r
+%token T_SEQUENCE\r
+%token T_SET\r
+%token T_SETTINGS\r
+%token T_SIZE\r
+%token T_STRING\r
+%token T_SYNTAX\r
+%token T_Tuple\r
+%token T_UNION\r
+%token T_UNIVERSAL\r
+%token T_UNIQUE\r
+%token T_STR_IDENTIFIER\r
+%token <node>T_TYPEREFERENCE\r
+%token <reference>T_TYPEFIELDREFERENCE\r
+%token <reference>T_VALUEFIELDREFERENCE\r
+%token T_DEFINED\r
+%token T_TAGS\r
+%token T_UTCTime\r
+%token T_GeneralizedTime\r
+%token T_GeneralizedString\r
+%token T_GraphicString\r
+%token T_BMPString\r
+%token T_IA5String\r
+%token T_ISO646String\r
+%token T_NumericString\r
+%token T_ObjectDescriptorString\r
+%token T_PrintableString\r
+%token T_TeletexString\r
+%token T_TIME\r
+%token T_TIME_OF_DAY\r
+%token T_T61String\r
+%token T_UniversalString\r
+%token T_UTF8String\r
+%token T_VideotextString\r
+%token T_VisibleString\r
+%token T_FROM\r
+%token T_IMPORTS\r
+%token T_ENUMERATED\r
+%token T_PLUS\r
+%token T_MINUS\r
+%token T_LPARENTHESES\r
+%token T_RPARENTHESES\r
+%token T_LBRACET\r
+%token T_LOBJBRACET\r
+%token T_RBRACET\r
+%token T_LBRACKET\r
+%token T_RBRACKET\r
+%token T_COMMA\r
+%token T_TWOPOINT\r
+%token T_THREEPOINT\r
+%token T_WITH\r
+%token T_USCORE\r
+%token T_bstring\r
+%token T_hstring\r
+\r
+%type <tag>         explicit_implicit opt_explicit_implicit\r
+%type <tag>         tag_class\r
+%type <tag>         tag\r
+%type <tag>         tag_type\r
+%type <tag>         opt_tag\r
+\r
+%type <module>      definitions\r
+%type <node>        alternative_type\r
+%type <node>        component_type\r
+%type <node>        component_type_lists\r
+%type <node>        constant_list\r
+%type <node>        constant\r
+%type <node>        opt_component_type_lists\r
+%type <node>        extension_and_exception \r
+%type <node>        exception_spec\r
+%type <constraint>  at_notation_list\r
+%type <constraint>  at_notation_element \r
+%type <constraint>  opt_constraint_def\r
+%type <constraint>  constraint_def\r
+%type <constraint>  contents_constraint\r
+%type <constraint>  general_constraint_def\r
+%type <constraint>  user_defined_constraint\r
+%type <constraint>  subtype_constraint_def\r
+%type <constraint>  set_of_constraints\r
+%type <constraint>  value_range\r
+%type <constraint>  component_relation_constraint\r
+%type <constraint>  constraint_range_spec\r
+%type <constraint>  constraint_subtype_element \r
+%type <constraint>  constraint_spec_subtype_element\r
+%type <constraint>  inner_type_constraint\r
+%type <constraint>  table_constraint\r
+%type <constraint>  simple_table_constraint\r
+%type <constraint>  opt_presence_constraint\r
+%type <node>        component_id_list\r
+\r
+%type <constraint>        contained_subtype  \r
+%type <node>        opt_imports\r
+%type <node>        imports_def\r
+%type <node>        import_item\r
+%type <node>        identifier\r
+%type <node>        opt_identifier\r
+%type <classfield>  oclass_field\r
+%type <node>        pos_neg_identifier\r
+%type <node>        definitions_id\r
+%type <node>        referenced_type\r
+%type <node>        token\r
+%type <module>      type_constant_list \r
+%type <node>        type_constant \r
+%type <node>        type\r
+%type <node>        type_reference\r
+%type <node>        type_declaration\r
+%type <node>        builtin_type\r
+%type <node>        defined_type\r
+%type <node>        type_assign_right\r
+%type <node>        type_assign_right_tag\r
+%type <node>        type_assign_right_tag_default\r
+%type <node>        constant_set_def\r
+%type <node>        object_assignment\r
+%type <node>        type_assignment\r
+%type <reference>        complex_type_reference \r
+%type <ref_comp>        complex_type_reference_amp_list\r
+%type <ref_comp>        complex_type_reference_element\r
+%type <node>        value_assignment\r
+%type <node>        object_set_assignment\r
+%type <reference>        object_class_reference\r
+%type <node>        obj_constant_list\r
+%type <node>        obj_constant\r
+%type <node>        defined_object \r
+%type <module>      definition_module\r
+%type <node>        object_defn\r
+%type <node>        parameterized_value\r
+%type <node>        parameterized_objectset\r
+%type <ref_comp>    primitive_field_reference\r
+%type <reference>   field_name\r
+%type <node>        pos_num\r
+%type <node>        neg_num\r
+%type <node>        pos_neg_num\r
+%type <node>        component_value\r
+%type <node>        component_value_list\r
+%type <node>        value\r
+%type <node>        value_reference\r
+%type <node>        character_string_def \r
+%type <node>        restricted_character_string_def\r
+%type <node>        unrestricted_character_string_def\r
+%type <node>        restricted_character_string_value\r
+%type <node>        defined_value\r
+%type <node>        builtin_value\r
+%type <node>        value_from_object\r
+%type <constraint>  value_set\r
+%type <constraint>  object_set\r
+%type <node>        object\r
+%type <reference>        defined_object_class \r
+%type <node>        set_def\r
+%type <node>        set_value\r
+%type <node>        sequence_def\r
+%type <node>        choice_def \r
+%type <node>        defined_syntax_list\r
+%type <node>        parameter_list \r
+%type <node>        parameter_args \r
+%type <parameter>   parameter_arg\r
+%type <node>        act_parameter_args\r
+%type <node>        act_parameter_arg\r
+%type <node>        default_syntax \r
+%type <node>        defined_syntax\r
+%type <node>        defined_syntax_token\r
+%type <node>        general_string_def\r
+%type <constraint>        element_set_specs\r
+%type <constraint>        element_set_spec\r
+%type <node>        integer_def \r
+%type <node>        real_def \r
+%type <node>        enumerated_def  \r
+%type <node>        boolean_def \r
+%type <node>        time_def \r
+%type <node>        any_def \r
+%type <node>        octet_string_def \r
+%type <node>        object_def\r
+%type <node>        object_class_def \r
+%type <node>        bit_string_def  \r
+%type <node>        bit_element_def\r
+%type <node>        bit_element_list\r
+%type <node>        export_element export_list\r
+%type <constraint>  with_components_list\r
+%type <constraint>  with_components_element\r
+%type <node>        which_list\r
+%type <marker>      default\r
+%type <marker>      opt_default\r
+\r
+%type <fragment>    opt_token syntax_token_list\r
+\r
+%name-prefix="_asn1_"\r
+%pure-parser\r
+\r
+\r
+%%\r
+\r
+definition_files:definitions\r
+  {\r
+    asn1::module *m =  get_current_module ( );\r
+    ASN_LOG_DEBUG("definition_files: got definition" );          \r
+  }\r
+  |   definition_files definitions\r
+  {\r
+    asn1::module *m =  get_current_module ( );\r
+    ASN_LOG_DEBUG("definition_files: got 1 definition" );          \r
+  }\r
+;\r
+\r
+\r
+/**\r
+ * export rules\r
+ */ \r
+opt_exports:\r
+  | exports_def\r
+;\r
+\r
+exports_def:\r
+  T_EXPORTS {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    $<module>$ = get_current_module();\r
+    $<module>$->enter_context(new asn1::exports());\r
+  } export_list T_SIMILICON \r
+  {\r
+    ASN_LOG_DEBUG("exports_def: got exports" );          \r
+    asn1::node *res = $<module>2->leave_context();\r
+    $<node>$ =res;\r
+  }\r
+  | T_EXPORTS T_ALL T_SIMILICON\r
+  {\r
+    ASN_LOG_DEBUG("exports_def: got exports ALL" );\r
+    asn1::exports *exp = new asn1::exports();\r
+    exp->all(true);\r
+    $<node>$ = exp;\r
+  }\r
+  | T_EXPORTS T_SIMILICON\r
+  {\r
+    ASN_LOG_DEBUG("exports_def: got exports nothing" );          \r
+  }\r
+;\r
+\r
+export_list: export_element\r
+  {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    ASN_LOG_DEBUG("export_list: CM %s Got Item: %s"\r
+                 , m->name().c_str()          \r
+                 , $1->name().c_str());          \r
+    m->enter_symbol($1,$1->type_id()());\r
+  }\r
+  | export_list T_COMMA export_element\r
+  {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    ASN_LOG_DEBUG("import_list: CM %s Got Item 1: %s"\r
+                 , m->name().c_str()          \r
+                 , $3->name().c_str());          \r
+    m->enter_symbol($3,$3->type_id()());\r
+  }\r
+;\r
+\r
+export_element: T_TYPEREFERENCE\r
+  {\r
+    ASN_LOG_DEBUG("export_element: got typeref" );          \r
+    $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name())\r
+                   );\r
+    delete $1;               \r
+  }\r
+  | T_TYPEREFERENCE T_LBRACET T_RBRACET\r
+  {\r
+    ASN_LOG_DEBUG("export_element: got typeref {}" );          \r
+    $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name())\r
+                   );\r
+    delete $1;               \r
+  }\r
+  | T_IDENTIFIER\r
+  {\r
+    ASN_LOG_DEBUG("export_element: got identifier" );          \r
+    $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name())\r
+                   );\r
+    delete $1;               \r
+  }\r
+;\r
+\r
+/**\r
+ *\r
+ */\r
+opt_imports: /* Empty*/\r
+    {\r
+        $$ = NULL;\r
+    }\r
+    | imports_def {\r
+        $$ = $1;\r
+    }\r
+;\r
+\r
+imports_def:\r
+    T_IMPORTS \r
+    {\r
+       asn1::parser *p = asn1::parser::instance();\r
+       $<module>$ = get_current_module();\r
+       $<module>$->enter_context(new asn1::import_list());\r
+    } import_set T_SIMILICON\r
+    {\r
+        asn1::node *res = $<module>2->leave_context();\r
+        $$ =res;\r
+    }\r
+    | T_IMPORTS T_FROM T_SIMILICON {\r
+        $$ = NULL;\r
+    }\r
+           ;\r
+\r
+import_set: \r
+  import {\r
+    ASN_LOG_DEBUG("import_set got import");\r
+  }\r
+       | import_set import {\r
+    ASN_LOG_DEBUG("import_set: 1 got import");\r
+  }\r
+;\r
+\r
+import: \r
+    {\r
+       $<module>$ = get_current_module();\r
+       ASN_LOG_DEBUG("import: start Module %s "\r
+                    ,$<module>$->name().c_str()\r
+                    );\r
+       $<module>$->enter_context(new asn1::import("IMPORT"));\r
+    }\r
+    import_list \r
+    {\r
+       $<node>$ = $<module>1->leave_context();\r
+    } T_FROM definitions_id\r
+    {\r
+       \r
+       asn1::module *m = get_current_module();\r
+       ASN_LOG_DEBUG("import: Module %s Got import %s "\r
+                    ,m->name().c_str()\r
+                    ,$<node>5->name().c_str());\r
+       $<node>3->identifier($5);\r
+       $<node>3->name($5->name());\r
+       m->enter_symbol($<node>3,$<node>3->type_id()());\r
+    }\r
+;\r
+\r
+import_list:\r
+  import_item {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    ASN_LOG_DEBUG("import_list: CM %s Got Item: %s"\r
+                 , m->name().c_str()          \r
+                 , $1->name().c_str());          \r
+    m->enter_symbol($1,$1->type_id()());\r
+  }\r
+  | import_list T_COMMA import_item {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    ASN_LOG_DEBUG("import_list: CM %s Got Item 1: %s"\r
+                 , m->name().c_str()          \r
+                 , $3->name().c_str());          \r
+    m->enter_symbol($3,$3->type_id()());\r
+  }\r
+;\r
+\r
+import_item:\r
+    T_TYPEREFERENCE {\r
+      ASN_LOG_DEBUG("import_item: %s typeref",$1->name().c_str());          \r
+      $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name())\r
+                   );\r
+      delete $1;               \r
+    }\r
+    | T_TYPEREFERENCE T_LBRACET T_RBRACET {\r
+      ASN_LOG_DEBUG("import_item: %s parameterized typeref",$1->name().c_str());          \r
+      $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name())\r
+                   );\r
+      delete $1;\r
+    }\r
+    | identifier\r
+    {\r
+      ASN_LOG_DEBUG("import_item: %s identifier what is it? value",$1->name().c_str());          \r
+      $$ = new asn1::typeref($1->name(),\r
+                     new asn1::simple_reference($1->name(),asn1::reference::component::Lowercase)\r
+                   );\r
+      delete $1;\r
+    }\r
+    | T_CAPITALREFERENCE {\r
+      ASN_LOG_DEBUG("import_item: %s CAPITAL what is it?",$1->name().c_str());          \r
+      $$ = new asn1::typeref($1->name(),\r
+                     new asn1::objectclass_reference($1->name())\r
+                   );\r
+      delete $1;\r
+    }\r
+    | T_CAPITALREFERENCE T_LBRACET T_RBRACET {\r
+      ASN_LOG_DEBUG("import_item: %s CAPITAL {} what is it?",$1->name().c_str());          \r
+      $$ = new asn1::typeref($1->name(),\r
+                     new asn1::objectclass_reference($1->name())\r
+                   );\r
+      delete $1 ;\r
+    }\r
+;\r
+/**\r
+ * main  definition entry \r
+ */\r
+definitions: definitions_id \r
+             T_DEFINITIONS opt_explicit_implicit opt_tags_def T_ASSIGN T_BEGIN /* imports_def */\r
+             {\r
+               asn1::parser *p = asn1::parser::instance();\r
+               $<module>$ =  p->module($1->name().c_str());\r
+               $<module>$->tag($3);\r
+#ifdef DEBUG\r
+               if (! gLog.is_open())\r
+                 open_log($1->name());\r
+#endif\r
+                ASN_LOG_DEBUG("definitions: start 1 size=%zu %s def=%s pn=%s"\r
+                             ,$<module>$->size()\r
+                             ,$<module>$->name().c_str()\r
+                             ,$1->name().c_str()\r
+                             ,p->module()->name().c_str()\r
+                              );\r
+             }\r
+             definition_module T_END {\r
+                asn1::parser *p = asn1::parser::instance();\r
+                ASN_LOG_DEBUG("definitions: 1 size=" SIZE_T_SPECIFIER " %s cm=%s"\r
+                             ,$8->size()\r
+                             ,$8->name().c_str()\r
+                             ,p->module()->name().c_str()\r
+                              );\r
+                asn1::module *m =  $8;\r
+                close_log();\r
+             }\r
+;\r
+\r
+definition_module: opt_exports opt_imports \r
+  {\r
+    asn1::import_list *i = dynamic_cast<asn1::import_list *>($2);\r
+    asn1::exports *e = dynamic_cast<asn1::exports *>($2);\r
+    asn1::module *m = get_current_module();\r
+    m->imports(i);\r
+    m->exports(e);\r
+  } type_constant_list\r
+  {\r
+    $$ = $4;\r
+ }\r
+ ;\r
+\r
+opt_tags_def: /* Empty */\r
+  | T_TAGS \r
+  {\r
+    ASN_LOG_DEBUG("opt_tags_def just TAGS");\r
+  }\r
+  | T_TAGS opt_defs \r
+  {\r
+    ASN_LOG_DEBUG("opt_tags_def ");\r
+  }\r
+;\r
+\r
+opt_defs: opt_def\r
+  | opt_defs opt_def\r
+;\r
+\r
+opt_def:  T_EXTENSIBILITY {\r
+    ASN_LOG_DEBUG("opt_def EXTENSIBILITY");\r
+  }\r
+  | T_IMPLIED {\r
+    ASN_LOG_DEBUG("opt_def IMPLIED");\r
+  }\r
+;\r
+\r
+opt_identifier: { $$ = NULL;}\r
+              | identifier \r
+                {\r
+                  $$ = $1;\r
+                }\r
+;\r
+identifier: T_IDENTIFIER\r
+            {$$ = $1;}\r
+;\r
+\r
+pos_num:  T_NUM {\r
+       ASN_LOG_DEBUG("pos_num got Num: %s",$1->name().c_str());\r
+       $$=$1;\r
+       $$->type_id(asn1::type::ASN1_INTEGER);\r
+    }\r
+    | T_PLUS T_NUM {\r
+       $$=$2;\r
+       $$->type_id(asn1::type::ASN1_INTEGER);\r
+    }\r
+           \r
+;\r
+\r
+neg_num: T_MINUS T_NUM {\r
+       $$ = $2;\r
+       $$->type_id(asn1::type::ASN1_INTEGER);\r
+       }\r
+;\r
+\r
+pos_neg_num: pos_num { \r
+       $$ = $1; \r
+       $$->meta_id(asn1::meta::VALUE);\r
+   }\r
+   | neg_num {\r
+       $$ = $1; \r
+       $$->meta_id(asn1::meta::VALUE);\r
+   }\r
+;\r
+\r
+pos_neg_identifier: \r
+    pos_num {\r
+        $$ = $1;\r
+    }\r
+   | neg_num {\r
+        $$ = $1;\r
+    }\r
+   | identifier {\r
+       ASN_LOG_ERROR("pos_neg_identifier: MUST BE TRANSFORMED TO valuetype%s",$1->cpp_name().c_str());\r
+       $$ = $1;\r
+       $$->type_id(asn1::type::ASN1_REFERENCE);\r
+       $$->meta_id(asn1::meta::VALUE);\r
+   }\r
+;\r
+\r
+constant: T_LPARENTHESES pos_neg_num T_RPARENTHESES\r
+          {\r
+            $$ = $2;\r
+          }\r
+        | T_IDENTIFIER T_LPARENTHESES pos_neg_num T_RPARENTHESES\r
+          {\r
+            $$ = $3;\r
+            $$->name($1->name());\r
+            delete $1;\r
+          }\r
+;\r
+\r
+constant_list:\r
+    constant {\r
+        ASN_LOG_DEBUG("constant_list: %s",$1->cpp_name().c_str());\r
+        asn1::module *m= get_current_module();\r
+        m->enter_symbol($1,$1->type_id()());\r
+    }\r
+    | constant_list T_COMMA constant {\r
+        ASN_LOG_DEBUG("constant_list 1:  %s",$3->cpp_name().c_str());\r
+        asn1::module *m= get_current_module();\r
+        m->enter_symbol($3,$3->type_id()());\r
+    }\r
+;\r
+\r
+obj_constant: pos_num {\r
+        ASN_LOG_DEBUG("obj_constant: %s",$1->cpp_name().c_str());\r
+        $$ = $1;\r
+    }\r
+    | T_IDENTIFIER T_LPARENTHESES T_NUM T_RPARENTHESES {\r
+        ASN_LOG_DEBUG("obj_constant 1: %s",$1->cpp_name().c_str());\r
+        $$ = $3;\r
+        oid_map[$<node>1->name()] = dynamic_cast<asn1::valuetype *>($3); \r
+        $$->name($<node>1->name());\r
+        $$->type_id(asn1::type::ASN1_INTEGER);\r
+        delete($1);\r
+    } \r
+/* predefined identifiers \r
+itu-t                 NUMV_TOK(T_NUM,0)\r
+iso                   NUMV_TOK(T_NUM,1)\r
+joint-iso-itu-t       NUMV_TOK(T_NUM,2)\r
+joint-iso-ccitt       NUMV_TOK(T_NUM,2)\r
+*/\r
+    | T_IDENTIFIER {\r
+      OidMapIterator it = oid_map.find($1->name()) ;\r
+      if ( !$1->name().compare("itu-t"))   \r
+      {\r
+        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER);\r
+        asn1::valuetype *vt = new asn1::valuetype($1->name(),v);\r
+        $$->type_id(asn1::type::ASN1_INTEGER);\r
+        vt->value_long(0);\r
+        $$ = vt;\r
+        delete($1);\r
+      } else if ( !$1->name().compare("iso")) \r
+      {\r
+        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER);\r
+        asn1::valuetype *vt = new asn1::valuetype($1->name(),v);\r
+        $$->type_id(asn1::type::ASN1_INTEGER);\r
+        vt->value_long(1);\r
+        $$ = vt;\r
+        delete($1);\r
+      } else if ( !$1->name().compare("joint-iso-itu-t")) \r
+      {\r
+        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER);\r
+        asn1::valuetype *vt = new asn1::valuetype($1->name(),v);\r
+        $$->type_id(asn1::type::ASN1_INTEGER);\r
+        vt->value_long(2);\r
+        $$ = vt;\r
+        delete($1);\r
+      } else if ( !$1->name().compare("joint-iso-ccitt"))\r
+      {\r
+        asn1::value *v = new asn1::value(asn1::value::VT_INTEGER);\r
+        asn1::valuetype *vt = new asn1::valuetype($1->name(),v);\r
+        $$->type_id(asn1::type::ASN1_INTEGER);\r
+        vt->value_long(2);\r
+        $$ = vt;\r
+        delete($1);\r
+      } else if (it != oid_map.end())\r
+      {\r
+        ASN_LOG_DEBUG("obj_constant IDENTIFIER found in map %s",$1->cpp_name().c_str());\r
+        $$ = it->second;\r
+      } else \r
+      { \r
+        ASN_LOG_ERROR("obj_constant IDENTIFIER 3 must be referenced: %s",$1->cpp_name().c_str());\r
+        $$ = $1;\r
+      } \r
+   } \r
+;\r
+\r
+obj_constant_list:\r
+    obj_constant {\r
+        ASN_LOG_DEBUG("obj_constant_list: %s",$1->cpp_name().c_str());\r
+        asn1::module *m = get_current_module();\r
+        m->enter_context(new asn1::object_identifier());\r
+        m->enter_symbol($1,$1->type_id()());\r
+        $$ = $1;\r
+    }\r
+    | obj_constant_list obj_constant {\r
+        ASN_LOG_DEBUG("obj_constant_list: append: $1=%s %s",$1->cpp_name().c_str(),$2->cpp_name().c_str());\r
+        asn1::module *m = get_current_module();\r
+        m->enter_symbol($2,$2->type_id()());\r
+    }\r
+;\r
+\r
+tag_class:\r
+  { \r
+  $$.m_class = asn1::node::tag_type::TC_CONTEXT_SPECIFIC;}\r
+  | T_UNIVERSAL  {\r
+    $$.m_class = asn1::node::tag_type::TC_UNIVERSAL;\r
+  }\r
+  | T_PRIVATE {\r
+    $$.m_class = asn1::node::tag_type::TC_PRIVATE;\r
+  }\r
+  | T_APPLICATION  {\r
+    $$.m_class = asn1::node::tag_type::TC_APPLICATION;\r
+  }\r
+;\r
+\r
+tag_type: \r
+  tag_class T_NUM {\r
+    asn1::node *n = $2;\r
+    asn1::valuetype *vt = dynamic_cast<asn1::valuetype *>(n);\r
+    $$ = $1;\r
+    $$.m_mode  = asn1::node::tag_type::TM_DEFAULT;\r
+    $$.m_value = vt->value_long();\r
+    delete $2;\r
+  }\r
+;\r
+\r
+tag: \r
+  tag_type {\r
+    $$ = $1;\r
+    $$.m_set  = true;\r
+  }\r
+  | T_LBRACKET tag_type T_RBRACKET {\r
+    ASN_LOG_DEBUG("tag: tag_type 1 [%d,%ld] ",$2.m_class,$2.m_value);\r
+    $$ = $2;\r
+    $$.m_set  = true;\r
+  }\r
+  | tag_type explicit_implicit {\r
+    ASN_LOG_DEBUG("tag: tag_type [%d,%ld] explicit_implicit %d",$1.m_class,$1.m_value,$2.m_mode);\r
+    $$ = $1;\r
+    $$.m_mode = $2.m_mode;\r
+    $$.m_set  = true;\r
+  }\r
+  | T_LBRACKET tag_type T_RBRACKET explicit_implicit {\r
+    ASN_LOG_DEBUG("tag: tag_type 1 [%d,%ld] explicit_implicit %d",$2.m_class,$2.m_value,$4.m_mode);\r
+    $$ = $2;\r
+    $$.m_mode = $4.m_mode;\r
+    $$.m_set  = true;\r
+  \r
+  }\r
+;\r
+\r
+opt_tag: \r
+  {\r
+    $$.m_class = asn1::node::tag_type::TC_NOCLASS;\r
+    $$.m_mode  = asn1::node::tag_type::TM_DEFAULT;\r
+    $$.m_value = -1;\r
+    $$.m_set   = false;\r
+  }\r
+  | tag {\r
+           ASN_LOG_DEBUG("opt_tag: tag cls=%d mode=%d val=%ld",$1.m_class,$1.m_mode,$1.m_value);\r
+           $$ = $1;\r
+           $$.m_set   = true;\r
+  }\r
+;\r
+\r
+default: T_DEFAULT value {\r
+    ASN_LOG_DEBUG("default: with value");\r
+    $$ = new asn1::node::marker_type(asn1::node::marker_type::FL_DEFAULT);\r
+    aeb::intrusive_ptr<asn1::value> p($2->value());\r
+    $$->m_value1 = p; \r
+  }\r
+\r
+;\r
+\r
+opt_default: \r
+  { \r
+    ASN_LOG_DEBUG("opt_default:  none");\r
+    $$ = new asn1::node::marker_type();\r
+  }\r
+  | default {\r
+    ASN_LOG_DEBUG("opt_default:  default");\r
+    $$ = $1 ;\r
+  }\r
+  | T_OPTIONAL {\r
+    ASN_LOG_DEBUG("opt_default: optional");\r
+    $$ = new asn1::node::marker_type(asn1::node::marker_type::FL_OPTIONAL);\r
+  }\r
+;\r
+\r
+\r
+integer_def: \r
+  T_INTEGER {\r
+     $$ = new asn1::integer();\r
+     $$->meta_id(asn1::meta::TYPE);\r
+  }\r
+  | T_INTEGER T_LBRACET {\r
+        asn1::module *m= get_current_module();\r
+        m->enter_context(new asn1::integer());\r
+        $<module>$ = m;\r
+  }  constant_list T_RBRACET {\r
+    $$ = $<module>3->leave_context();\r
+    ASN_LOG_DEBUG("integer_def has constant_list");\r
+    $$->meta_id(asn1::meta::TYPE);\r
+ }\r
+;\r
+\r
+\r
+real_def: \r
+  T_REAL {  \r
+    $$ = new asn1::real();\r
+  }\r
+;\r
+\r
+boolean_def: T_BOOLEAN\r
+           { $$ = new asn1::boolean();}\r
+;\r
+\r
+time_def: T_UTCTime\r
+          {$$ = new asn1::utctime();}\r
+        | T_GeneralizedTime\r
+          {$$ = new asn1::generalizedtime();}\r
+;\r
+\r
+/* See X.682 */\r
+general_constraint_def:\r
+  user_defined_constraint {\r
+    ASN_LOG_DEBUG("general_constraint_def: user_defined_constraint %s",($1==NULL)?"none":$1->name().c_str());\r
+  }\r
+  | table_constraint {\r
+    ASN_LOG_DEBUG("general_constraint_def: table_constraint %s",$1->name().c_str());\r
+  }\r
+  | contents_constraint {\r
+    ASN_LOG_DEBUG("general_constraint_def: content_constraint %s ",$1->name().c_str());\r
+  }\r
+;\r
+\r
+user_defined_constraint: \r
+  T_CONSTRAINED T_BY T_LBRACET T_RBRACET {\r
+    ASN_LOG_DEBUG("user_defined_constraint constraint by empty");\r
+    $$ = new asn1::ctype_ctdby();\r
+  }\r
+  | T_CONSTRAINED T_BY T_LBRACET type T_RBRACET {\r
+    ASN_LOG_DEBUG("user_defined_constraint contrained by type: %s",$4->name().c_str());\r
+    $$ = new asn1::ctype_ctdby();\r
+    $$->value($4);\r
+  }\r
+;\r
+\r
+table_constraint:\r
+  simple_table_constraint {\r
+    ASN_LOG_DEBUG("table_constraint:simple_table_constraint TODO %s"\r
+                 , $<constraint>1->value()->name().c_str());\r
+  }\r
+  | component_relation_constraint {\r
+    ASN_LOG_DEBUG("component_relation_constraint TODO");\r
+}\r
+;\r
+\r
+simple_table_constraint: \r
+  T_LBRACET type_reference T_RBRACET {\r
+    // The rules is wrong. According to X.681 simple_table_constraint ::= ObjectSet \r
+    // and ObjectSet ::= { ObjectSetSpec} \r
+    // and ObjectSetSpec = RootElementSetSpec, ...\r
+    ASN_LOG_DEBUG("simple_table_constraint {typeref=%s} CHECK constraint type",$2->name().c_str());\r
+    //$$ = new asn1::constraint("VALUE",asn1::constraint::EL_VALUE);\r
+    //TODO Is the line below correct ?\r
+    //$$->value($2);\r
+    $$ = new asn1::celt_type($2->as_typeref());\r
+    asn1::module *m = get_current_module();\r
+    $2->set_parent(m->current_context());\r
+  }\r
+;\r
+\r
+component_relation_constraint: simple_table_constraint T_LBRACET at_notation_list T_RBRACET\r
+  {\r
+    ASN_LOG_DEBUG("component_relation_constraint %s {@ %s}",$1->name().c_str(),$3->name().c_str());\r
+    $$ = new asn1::ca_crc();\r
+    $$->append($1);\r
+    $$->append($3);\r
+  }\r
+;\r
+\r
+at_notation_list: at_notation_element {\r
+    ASN_LOG_WARNING("at_notation_list: simple TODO  ");\r
+  }\r
+  | at_notation_list T_COMMA at_notation_element {\r
+    ASN_LOG_WARNING("at_notation_list: TODO  ");\r
+  }\r
+;\r
+\r
+at_notation_element: \r
+  T_AT component_id_list {\r
+    ASN_LOG_DEBUG("at_notation_element: TODO @ %s",$<node>2->name().c_str());\r
+    $$ = new asn1::constraint("VALUE",asn1::constraint::EL_VALUE);\r
+    $<node>2->meta_id(asn1::meta::VALUE);\r
+    $$->value($<node>2);\r
+  }\r
+  | T_AT T_POINT component_id_list {\r
+    ASN_LOG_DEBUG("at_notation_element: point TODO");\r
+    $$ = new asn1::constraint("VALUE",asn1::constraint::EL_VALUE);\r
+    $<node>3->meta_id(asn1::meta::VALUE);\r
+    $$->value($<node>3);\r
+}\r
+;\r
+\r
+component_id_list:\r
+  T_IDENTIFIER {\r
+    ASN_LOG_DEBUG("component_id_list: TODO @ %s",$1->name().c_str());\r
+  \r
+  }\r
+  | component_id_list T_POINT T_IDENTIFIER {\r
+    ASN_LOG_ERROR("component_id_list: TODO @. %s ",$3->name().c_str());\r
+  }\r
+;\r
+\r
+contents_constraint: T_CONTAINING type_reference {\r
+    ASN_LOG_DEBUG("contents_contraint %s ",$2->name().c_str());\r
+    $$ = new asn1::ctype_ctng();\r
+    $$->value($2);\r
+  }\r
+  | T_ENCODED T_BY T_IDENTIFIER  {\r
+    ASN_LOG_DEBUG("contents_contraint 1 %s ",$3->name().c_str());\r
+    $$ = new asn1::celt_encodedby();\r
+  }\r
+  | T_CONTAINING type_reference T_ENCODED T_BY T_IDENTIFIER {\r
+    ASN_LOG_DEBUG("contents_contraint 2 %s ",$2->name().c_str());\r
+    $$ = new asn1::ctype_ctng();\r
+    $$->value($2);\r
+  }\r
+;\r
+\r
+constraint_def:  subtype_constraint_def\r
+                { \r
+                  $$ = $1;\r
+                  ASN_LOG_DEBUG("constraint_def subtype_constraint_def type=%d %s",$$->type(),$$->name().c_str());\r
+                }\r
+                /* Found in X.682 45.6*/\r
+ /*     Rule in set of constraint        \r
+       | T_LPARENTHESES element_set_specs exception_spec T_RPARENTHESES\r
+                {\r
+                  printf("constraint_def 1\n");\r
+                }\r
+              | T_LPARENTHESES general_constraint_def exception_spec T_RPARENTHESES\r
+                {\r
+                  printf("constraint_def\n");\r
+                  $$ = $2;\r
+                }\r
+     */\r
+;\r
+\r
+subtype_constraint_def:\r
+  set_of_constraints { \r
+    ASN_LOG_DEBUG("subtype_constraint_def: set_of_constraints");\r
+    if ($1->size() == 1)\r
+    {\r
+      // There is only one constraint, erase set and return element\r
+      $$ = *($1->begin());\r
+      delete($1);\r
+    } else\r
+      $$ = $1;\r
+  }\r
+  | T_SIZE T_LPARENTHESES element_set_specs T_RPARENTHESES {\r
+    ASN_LOG_DEBUG("subtype_constraint_def: T_SIZE %s",$3->name().c_str());  \r
+    $$ = new asn1::ctype_size();\r
+    $$->append($3);\r
+  }\r
+                        \r
+;\r
+\r
+set_of_constraints: \r
+  T_LPARENTHESES element_set_specs  exception_spec T_RPARENTHESES\r
+  {\r
+    ASN_LOG_DEBUG("set_of_constraints 1 ( %s)",$2->name().c_str());\r
+    $$ = new asn1::ca_set();\r
+    $$->append($2);\r
+  }\r
+  | T_LPARENTHESES general_constraint_def  exception_spec T_RPARENTHESES\r
+  {\r
+    ASN_LOG_DEBUG("set_of_constraints 2 ( )");\r
+    $$ = new asn1::ca_set();\r
+    $$->append($2);\r
+    }\r
+  | set_of_constraints  T_LPARENTHESES general_constraint_def exception_spec T_RPARENTHESES\r
+  {\r
+    ASN_LOG_DEBUG("set_of_constraints 3 set ( gen) REWORK");\r
+    $$ = $1;\r
+    $$->append($3);\r
+  }\r
+  | set_of_constraints  T_LPARENTHESES element_set_specs exception_spec T_RPARENTHESES\r
+  { \r
+    ASN_LOG_DEBUG("set_of_constraints 4 set (elem ) REWORK");\r
+    $$ = $1;\r
+    $$->append($3);\r
+  }\r
+;\r
+\r
+element_set_specs: \r
+  T_THREEPOINT {\r
+    ASN_LOG_DEBUG("element_set_specs ... ");\r
+    $$ = new asn1::celt_ext();\r
+  }\r
+  | element_set_spec {\r
+    if ($1!= NULL) {\r
+      ASN_LOG_DEBUG("element_set_specs got one not null %s",$1->name().c_str());\r
+    } else {\r
+      ASN_LOG_DEBUG("element_set_specs got NULL ");\r
+    }\r
+    $$ = $1;\r
+  }\r
+  | element_set_spec T_COMMA T_THREEPOINT {\r
+    ASN_LOG_DEBUG("element_set_specs , ... ");\r
+    $$ = $1;\r
+    $$->append(new asn1::celt_ext());\r
+  }\r
+  | element_set_spec T_COMMA T_THREEPOINT T_COMMA element_set_spec {\r
+    ASN_LOG_DEBUG("element_set_specs , ... , set_spec ");\r
+    $$ = $1;\r
+    $$->append(new asn1::celt_ext());\r
+    $$->append($5);\r
+  }\r
+;\r
+\r
+\r
+element_set_spec: \r
+  constraint_subtype_element {\r
+    ASN_LOG_DEBUG("element_set_spec: constraint_subtype_element (%s)",($1 == NULL)?"none":$1->name().c_str());\r
+    $$ = $1;\r
+  }\r
+  | T_ALL T_EXCEPT constraint_subtype_element {\r
+    ASN_LOG_DEBUG("element_set_spec: ALL EXCEPT constraint_subtype_element");\r
+    $$ = new asn1::ca_aex();\r
+    $$->append($3);\r
+  }\r
+  | element_set_spec T_UNION constraint_subtype_element {\r
+    ASN_LOG_DEBUG("element_set_spec: UNION constraint_subtype_element");\r
+    $$ = $1;\r
+    if ($$ != NULL) {\r
+        ASN_LOG_DEBUG("element_set_spec: UNION $1 is not NULL");\r
+        if ($1->type() == asn1::constraint::CA_UNI) {\r
+          $$ = $1 ;\r
+          $$->append($3);\r
+        } else {\r
+          $$ = new asn1::ca_uni();\r
+          $$->append($1);\r
+          $$->append($3);\r
+        }\r
+    } else {\r
+        ASN_LOG_ERROR("element_set_spec: UNION $1 is NULL");\r
+        $$ = $3;\r
+    }\r
+  }\r
+  | element_set_spec T_INTERSECTION constraint_subtype_element {\r
+    ASN_LOG_DEBUG("element_set_spec: INTERSECTION constraint_subtype_element");\r
+    $$ = $1;\r
+    $$->append($3);\r
+  }\r
+  | constraint_subtype_element T_EXCEPT constraint_subtype_element {\r
+    ASN_LOG_DEBUG("element_set_spec: EXCEPT constraint_subtype_element");\r
+    $$ = $1;\r
+    $$->append($3);\r
+  }\r
+;\r
+\r
+constraint_subtype_element: \r
+  constraint_spec_subtype_element  T_LPARENTHESES \r
+  {\r
+       ASN_LOG_DEBUG("constraint_subtype_element start in constraint ");\r
+  }\r
+  element_set_specs T_RPARENTHESES\r
+  {\r
+      /* This rule is not correct. It should be an ObjectSetElements */\r
+       $1->append($4);\r
+       ASN_LOG_DEBUG("constraint_subtype_element end type_reference 1 %s",$1->name().c_str());\r
+       $$ = $1;\r
+  }\r
+  | T_LPARENTHESES element_set_specs T_RPARENTHESES\r
+  {\r
+      /* This rule is not correct. It should be an ObjectSetElements */\r
+      ASN_LOG_DEBUG("TODO: constraint_subtype_element (element_set_specs %s)",$2->name().c_str());\r
+       $$ = $2;\r
+  }\r
+  | referenced_type \r
+  {\r
+      /* This rule is not correct. It should be an ObjectSetElements */\r
+      ASN_LOG_ERROR("TODO: constraint_subtype_element reference type");\r
+      $$ = new asn1::celt_type();\r
+      $$->value($1);\r
+  }\r
+  | T_LOBJBRACET defined_syntax_list T_RBRACET {\r
+    ASN_LOG_ERROR("TODO: constraint_subtype_element defined syntax list");\r
+    $$ = new asn1::celt_value();\r
+    $$->value($2);\r
+  }\r
+  | value\r
+  {\r
+      ASN_LOG_DEBUG("constraint_subtype_element value");\r
+      $$ = new asn1::celt_value();\r
+      $$->value($1);\r
+  }\r
+  | T_PATTERN value\r
+  {\r
+      ASN_LOG_DEBUG("constraint_subtype_element pattern value");\r
+      $$ = new asn1::celt_value();\r
+      $$->value($2);\r
+  }\r
+  | value_range {\r
+      ASN_LOG_DEBUG("constraint_subtype_element value_range");\r
+      $$ = $1;\r
+  }\r
+  | contained_subtype\r
+  {\r
+      ASN_LOG_DEBUG("TODO: constraint_subtype_element contained_subtype");\r
+  }\r
+  | inner_type_constraint\r
+  {\r
+       ASN_LOG_DEBUG("constraint_subtype_element inner_type_contraint");\r
+  }\r
+  | T_TYPEREFERENCE\r
+  {\r
+      ASN_LOG_DEBUG("constraint_subtype_element type_reference X.680 4.7.6=%s",$1->name().c_str());\r
+      $$ = new asn1::celt_type();\r
+      asn1::typeref *tref  = new asn1::typeref($1->name(),\r
+                                 new asn1::simple_reference($1->name())\r
+                               );\r
+      delete $1;               \r
+      $$->value(tref);\r
+  }\r
+  | parameterized_objectset\r
+  {\r
+       ASN_LOG_DEBUG("constraint_subtype_element objectset=%s",$1->name().c_str());\r
+      $$ = new asn1::celt_value();\r
+      $$->value($1);\r
+  }\r
+  | type\r
+  {\r
+       ASN_LOG_DEBUG("constraint_subtype_element type %s",$1->name().c_str());\r
+       $$ = new asn1::celt_type();\r
+       $$->value($1);\r
+  }\r
+;\r
+\r
+contained_subtype: T_INCLUDES T_TYPEREFERENCE {\r
+      $$ = new asn1::constraint("INCLUDE TYPE",asn1::constraint::EL_TYPE);\r
+      asn1::typeref *tref  = new asn1::typeref($2->name(),\r
+                                 new asn1::simple_reference($2->name())\r
+                               );\r
+      delete $2;               \r
+      $$->value(tref);\r
+   }\r
+;\r
+\r
+constraint_spec_subtype_element:\r
+  T_SIZE {\r
+    ASN_LOG_DEBUG("constraint_spec_subtype_element T_SIZE");\r
+    $$ = new asn1::ctype_size();\r
+  }\r
+  | T_FROM {\r
+    ASN_LOG_DEBUG("constraint_spec_subtype_element T_FROM");\r
+    $$ = new asn1::ctype_from();\r
+  }\r
+;\r
+\r
+inner_type_constraint:\r
+  T_WITH T_COMPONENT set_of_constraints {\r
+    ASN_LOG_DEBUG("inner_type_constraint WITH_COMPONENTS ");\r
+    $$ = new asn1::ctype_wcomp();\r
+    $$->append($3);\r
+  }\r
+  | T_WITH T_COMPONENTS T_LBRACET with_components_list T_RBRACET {\r
+    ASN_LOG_DEBUG("inner_type_constraint WITH_COMPONENTS 1 ");\r
+    $$ = $4;\r
+  }\r
+;\r
+\r
+\r
+with_components_list:\r
+  with_components_element {\r
+    ASN_LOG_DEBUG("with_components_list: 1 ");\r
+    $$ = new asn1::ctype_wcomps();\r
+    $$->append($1);\r
+  }\r
+  | with_components_list T_COMMA with_components_element {\r
+    ASN_LOG_DEBUG("with_components_list: 2 ");\r
+    $1->append($3);\r
+    $$ = $1;\r
+  }\r
+;\r
+\r
+with_components_element:\r
+  T_THREEPOINT {\r
+    ASN_LOG_DEBUG("with_components_element: 1 extensible ");\r
+    $$ = new asn1::celt_ext();\r
+  }\r
+  | T_IDENTIFIER opt_constraint_def opt_presence_constraint {\r
+    ASN_LOG_DEBUG("with_components_element: 2 ");\r
+    if ($2 != NULL) \r
+    {\r
+       ASN_LOG_DEBUG("with_components_element: 2 have opt contraint %s",$1->name().c_str());\r
+       $$ = $2;\r
+    } else if ($3 != NULL) {\r
+       ASN_LOG_DEBUG("with_components_element: 3 have presence contraint %s",$1->name().c_str());\r
+      $$ = $3;\r
+      $$->value($1);\r
+    }\r
+  }\r
+;\r
+\r
+opt_presence_constraint: /* NULL */\r
+                     { $$ = NULL; }\r
+  | T_PRESENT {\r
+    ASN_LOG_DEBUG("opt_presence_constraint: PRESENT ");\r
+    $$ = new asn1::constraint("PRESENCE",asn1::constraint::EL_TYPE);\r
+    $$->presence(asn1::constraint::PRESENT);\r
+  }\r
+  | T_ABSENT {\r
+    ASN_LOG_DEBUG("opt_presence_constraint: ABSENT ");\r
+    $$ = new asn1::constraint("PRESENCE",asn1::constraint::EL_TYPE);\r
+    $$->presence(asn1::constraint::ABSENT);\r
+  }\r
+  | T_OPTIONAL {\r
+    ASN_LOG_DEBUG("opt_presence_constraint: OPTIONAL ");\r
+    $$ = new asn1::constraint("PRESENCE",asn1::constraint::EL_TYPE);\r
+    $$->presence(asn1::constraint::OPTIONAL_);\r
+  }\r
+;\r
+\r
+opt_constraint_def:  /* NULL */\r
+  { $$ = NULL; }\r
+  | constraint_def\r
+  { \r
+    ASN_LOG_DEBUG("opt_constraint_def: %s",$1->name().c_str());\r
+    $$ = $1;\r
+    asn1::parser::instance()->constraint_complet($1);\r
+  }\r
+;\r
+\r
+opt_component_type_lists: /* NULL */\r
+  { $$ = NULL; }\r
+  | component_type_lists\r
+    {\r
+      $$ = $1;\r
+    }\r
+;\r
+\r
+component_type_lists: component_type\r
+  { \r
+    asn1::parser::instance()->got_component_type($1);\r
+  }\r
+  | component_type_lists T_COMMA component_type\r
+  { \r
+    asn1::parser::instance()->got_component_type($3);\r
+  } \r
+;\r
+\r
+\r
+component_type: T_IDENTIFIER type opt_default /*NamedType*/\r
+  { \r
+    ASN_LOG_DEBUG("component_type: (%s) type %s flags=%d"\r
+                  , $1->name().c_str()\r
+                  , $2->name().c_str()\r
+                  , ($3==NULL)?0:$3->m_flags); \r
+    \r
+    asn1::module *m = get_current_module();\r
+    $2->set_parent(m->current_context());\r
+    $$ = new asn1::field($1->name(),$2);\r
+    $$->flags($3);\r
+    if ($2->type_id()() == asn1::type::ASN1_SEQUENCE\r
+        || $2->type_id()() == asn1::type::ASN1_CHOICE\r
+        || $2->type_id()() == asn1::type::ASN1_ENUMERATED\r
+    )\r
+    {\r
+       $2->name($1->name()+"_t");\r
+    }\r
+    delete ($1);\r
+\r
+  }\r
+  |  type  opt_default /*type_assign*/ /* Needs to be checked */\r
+  { \r
+    asn1::module *m = get_current_module();\r
+    ASN_LOG_DEBUG("component_type: Should go type=%s",$1->name().c_str()); \r
+    std::string ano("anonymous");\r
+    ano = ano+$1->cpp_name();\r
+    $$ = new asn1::field(ano.c_str(),$1);\r
+    $1->set_parent(m->current_context());\r
+    $$->flags($2);\r
+  }\r
+  | T_COMPONENTS T_OF type_assign_right_tag_default\r
+  {\r
+    ASN_LOG_DEBUG("component_type: component of %s",$3->name().c_str()); \r
+    $$ = new asn1::components_of($3);\r
+  }\r
+  | extension_and_exception\r
+  {\r
+    ASN_LOG_DEBUG("component_type: extension and exception %s",$1->name().c_str());\r
+    $$ = $1;\r
+  }\r
+;\r
+\r
+character_string_def:  restricted_character_string_def\r
+  { \r
+    $$ = $1;\r
+  }\r
+  | unrestricted_character_string_def\r
+  { \r
+    $$ = $1;\r
+  }\r
+;\r
+\r
+restricted_character_string_def: T_BMPString\r
+  { $$ = new asn1::bmpstring(); }\r
+  | general_string_def\r
+    {$$ = $1;}\r
+  | T_GraphicString\r
+    { $$ = new asn1::graphicstring(); }\r
+  | T_IA5String\r
+    {$$ = new asn1::ia5string();}\r
+  | T_ISO646String\r
+    { $$ = new asn1::iso646string(); }\r
+  | T_NumericString\r
+    { $$ = new asn1::numericstring(); }\r
+  | T_PrintableString\r
+    { $$ = new asn1::printablestring(); }\r
+  | T_TeletexString\r
+    { $$ = new asn1::teletexstring(); }\r
+  | T_T61String\r
+    {$$ = new asn1::node("STRING",asn1::type::ASN1_STRING_T61String);}\r
+  | T_UniversalString\r
+    { $$ = new asn1::universalstring(); }\r
+  | T_UTF8String\r
+    { $$ = new asn1::utf8string(); }\r
+  | T_VideotextString\r
+    { $$ = new asn1::videotexstring(); }\r
+  | T_VisibleString\r
+    {$$ = new asn1::visiblestring(); }\r
+  | T_ObjectDescriptorString\r
+    {$$ = new asn1::objectdescriptor_string(); }\r
+;\r
+\r
+restricted_character_string_value: T_LBRACET rcsv_char_syms T_RBRACET {\r
+    ASN_LOG_ERROR("retricted_character_string_value 1: TODO");\r
+  }\r
+  | rcsv_quadruple {\r
+    ASN_LOG_ERROR("retricted_character_string_value 2: TODO");\r
+  }\r
+  | rcsv_tuple {\r
+    ASN_LOG_ERROR("retricted_character_string_value 3: TODO");\r
+  }\r
+;\r
+\r
+rcsv_char_syms: rcsv_char_sym {\r
+  }\r
+  | rcsv_char_syms T_COMMA rcsv_char_sym {\r
+  }\r
+;\r
+\r
+rcsv_char_sym: rcsv_quadruple {\r
+    ASN_LOG_DEBUG("rcvs_char_sym: "); \r
+  }\r
+  | rcsv_tuple {\r
+    ASN_LOG_DEBUG("rcvs_char_sym: "); \r
+  }\r
+;\r
+\r
+rcsv_quadruple: T_LBRACET T_NUM T_COMMA T_NUM T_COMMA T_NUM T_COMMA T_NUM T_RBRACET {\r
+    ASN_LOG_DEBUG("rcvs_quadruple: "); \r
+  }\r
+  | T_Quadruple\r
+  {\r
+    ASN_LOG_DEBUG("rcvs_quadruple 1: "); \r
+  }\r
+;\r
+\r
+rcsv_tuple: T_LBRACET T_NUM T_COMMA T_NUM T_RBRACET {\r
+    ASN_LOG_DEBUG("rcvs_tuple: "); \r
+  }\r
+  | T_Tuple\r
+  {\r
+    ASN_LOG_DEBUG("rcvs_quadruple: "); \r
+  }\r
+\r
+unrestricted_character_string_def: T_CHARACTER T_STRING\r
+  {  $<node>$ = new asn1::node("STRING",asn1::type::ASN1_STRING);}\r
+;\r
+\r
+general_string_def: T_GeneralizedString\r
+  { $$ = new asn1::node("STRING",asn1::type::ASN1_STRING);}\r
+;\r
+\r
+octet_string_def: T_OCTET T_STRING {  \r
+    $$ = new asn1::octet_string();\r
+  }\r
+;\r
+\r
+bit_element_def: T_IDENTIFIER T_LPARENTHESES T_NUM T_RPARENTHESES\r
+  {  \r
+    ASN_LOG_DEBUG("bit_element_def: %s",$<node>1->name().c_str()); \r
+    $3->name($1->name());\r
+    delete $1;\r
+    $$ = $3;\r
+  }\r
+  | T_THREEPOINT\r
+  {\r
+    ASN_LOG_DEBUG("bit_element_def: %s is extension_filed ",$<node>1->name().c_str()); \r
+    //$$ = new asn1::node("THREEPOINT",asn1::type::ASN1_EXTENSIBLE);\r
+    $$ = new asn1::extension_field();\r
+  }\r
+  | T_IDENTIFIER\r
+  {\r
+    ASN_LOG_ERROR("bit_element_def: value reference %s should return valuetype",$<node>1->name().c_str()); \r
+    $$ = $1;\r
+    $$->meta_id(asn1::meta::VALUE);\r
+  }\r
+;\r
+\r
+bit_element_list: bit_element_def\r
+  { \r
+      asn1::module *m= get_current_module();\r
+      m->enter_symbol($<node>1,$<node>1->type_id()());\r
+  }\r
+  | bit_element_list T_COMMA bit_element_def\r
+  { \r
+      ASN_LOG_DEBUG("bit_element_list: %s %s",$1->name().c_str(),$3->name().c_str()); \r
+      asn1::parser *p = asn1::parser::instance();\r
+      asn1::module *m= (asn1::module *) p->module();\r
+      m->enter_symbol($<node>3,$<node>3->type_id()());\r
+  }\r
+;\r
+\r
+bit_string_def:\r
+  T_BIT T_STRING\r
+  {\r
+      $$ = new asn1::bit_string();\r
+  }\r
+  | T_BIT T_STRING T_LBRACET \r
+  {\r
+      asn1::module *m= get_current_module();\r
+      m->enter_context(new asn1::bit_string());\r
+      $<module>$ = m;\r
+  } constant_list T_RBRACET {\r
+      $$ = $<module>4->leave_context(); \r
+  }\r
+;\r
+\r
+enumerated_def: T_ENUMERATED T_LBRACET \r
+  {\r
+    ASN_LOG_DEBUG("enumerated_def: begin "); \r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    m->enter_context(new asn1::enumerated());\r
+    $<module>$ = m;\r
+  } bit_element_list T_RBRACET\r
+  {  \r
+    ASN_LOG_DEBUG("enumerated_def: end "); \r
+    asn1::module *m =  (asn1::module *)$<module>3;\r
+    asn1::node *res = m->leave_context();\r
+    $$ = res;\r
+  }\r
+;\r
+\r
+\r
+object_def: T_OBJECT T_STR_IDENTIFIER\r
+  {\r
+    ASN_LOG_DEBUG("\nobject_def OBJECT IDENTIFIER type");\r
+    $$ = new asn1::object_identifier();\r
+  }\r
+;\r
+\r
+/**\r
+ *\r
+ */\r
+object_class_def:\r
+  T_CLASS T_LBRACET \r
+  {\r
+    ASN_LOG_DEBUG("\nobject_class_def start");\r
+    asn1::module *m= get_current_module();\r
+    m->enter_context(new asn1::classdef() );\r
+    $<module>$ = m;\r
+  } \r
+  oclass_field_list \r
+  {\r
+    asn1::module *m =  (asn1::module *)$<module>3;\r
+    asn1::node *res = m->leave_context();\r
+    ASN_LOG_DEBUG("object_class_def: end %s %s", res->name().c_str()\r
+             ,$<module>3->name().c_str());\r
+    $<node>$ = res; \r
+    gCurrentClassDef = dynamic_cast<asn1::classdef *>(res);\r
+    gCurrentClassDef->sort_fields();\r
+    res->meta_id(asn1::meta::OBJECTCLASS);\r
+  } T_RBRACET opt_with_syntax\r
+  {\r
+    $$ = $<node>5;\r
+  }\r
+;\r
+\r
+opt_with_syntax:\r
+               | T_WITH T_SYNTAX T_LBRACET \r
+               {\r
+                 ASN_LOG_DEBUG("\nwith syntax start skip...");\r
+                 enable_with_syntax();\r
+                 gCurrentClassDef->start_syntax();\r
+               } syntax_token_list  T_RBRACET\r
+               {\r
+                 disable_with_syntax();\r
+                 ASN_LOG_DEBUG("with syntax end skip...");\r
+                 if ( $5 == NULL)\r
+                 {\r
+                   ASN_LOG_ERROR("with syntax end skip $5 IS NULL ");\r
+                 }\r
+                 gCurrentClassDef->set_nfa($5);\r
+               }\r
+;\r
+\r
+syntax_token_list: /* NULL*/ \r
+     {\r
+         ASN_LOG_DEBUG("syntax_token_list:  NULL");\r
+         $$ = NULL;\r
+     }\r
+     | token syntax_token_list\r
+     {\r
+       if ($1 != NULL && $2 != NULL)\r
+       {\r
+         ASN_LOG_DEBUG("syntax_token_list: 1 token %s append %s",$1->name().c_str(),$2->name().c_str());\r
+         asn1::classdef::fragment *f = gCurrentClassDef->parse_token($1);\r
+         $$ = f;\r
+         $$ = gCurrentClassDef->parse_append($$,$2);\r
+       } else if ($1 != NULL)\r
+       {\r
+         asn1::classdef::fragment *f = gCurrentClassDef->parse_token($1);\r
+         ASN_LOG_DEBUG("syntax_token_list: 1 token %s $2 is  NULL",f->name().c_str());\r
+         $$ = f;\r
+       } else\r
+       {\r
+         ASN_LOG_DEBUG("syntax_token_list: token NULL");\r
+       }\r
+     }\r
+     | opt_token syntax_token_list\r
+     {\r
+       /* ASN_LOG_DEBUG("syntax_token_list: [  ] "); */\r
+       if ($1 != NULL && $2 != NULL)\r
+       {\r
+         ASN_LOG_DEBUG("syntax_token_list: [ %s ] %s",$1->name().c_str(),$2->name().c_str());\r
+        asn1::classdef::fragment *f = gCurrentClassDef->parse_append($1,$2);\r
+        $$ = f;\r
+       } else if ($1 != NULL)\r
+       {\r
+         /* TODO May be this is a match*/\r
+         ASN_LOG_DEBUG("syntax_token_list: [ %s ] $1 is not NULL ",$1->name().c_str());\r
+         //asn1::classdef::fragment *f = gCurrentClassDef->parse_optional($1);\r
+         $$ = $1;\r
+       } else if ($2 != NULL)\r
+       {\r
+         ASN_LOG_DEBUG("syntax_token_list: [  ] $2 is not NULL ");\r
+         $$ = $2;\r
+       } else \r
+       {\r
+         ASN_LOG_ERROR("syntax_token_list: [  ] $1==NULL && $2 == NULL ");\r
+       }\r
+     }\r
+;\r
+/**\r
+ { $<node>$ = NULL;} \r
+ */\r
+opt_token : \r
+      T_LBRACKET syntax_token_list T_RBRACKET\r
+     {\r
+       ASN_LOG_DEBUG("opt_token : [ %s ] ",$2->name().c_str());\r
+       asn1::classdef::fragment *f = gCurrentClassDef->parse_optional($2);\r
+       $$ = f;\r
+     }\r
+;\r
+\r
+token: T_CAPITALREFERENCE {\r
+       ASN_LOG_DEBUG("token: capitalReference : %s",$1->name().c_str());\r
+     }\r
+     | T_TYPEFIELDREFERENCE {\r
+       ASN_LOG_DEBUG("token: value FieldReference : %s",$1->name().c_str());\r
+       $$ = new asn1::typeref($1);\r
+     }\r
+     | T_VALUEFIELDREFERENCE {\r
+       ASN_LOG_DEBUG("token: value FieldReference : %s",$1->name().c_str());\r
+       $$ = new asn1::typeref($1);\r
+     }\r
+     | T_COMMA {\r
+       ASN_LOG_ERROR("token: comma");\r
+     }\r
+;\r
+\r
+opt_unique: /* Empty */\r
+  | T_UNIQUE { \r
+    ASN_LOG_DEBUG("opt_unique: UNIQUE TO BE CODED NOT IMPORTANT");\r
+  \r
+  }\r
+;\r
+\r
+oclass_field_list: \r
+   oclass_field {\r
+      asn1::parser::instance()->got_class_field($1);\r
+   }\r
+   | oclass_field_list T_COMMA oclass_field {\r
+      asn1::parser::instance()->got_class_field($3);\r
+   }\r
+;\r
+\r
+oclass_field: T_TYPEFIELDREFERENCE opt_default\r
+              {\r
+                ASN_LOG_DEBUG("oclass_field: typefieldref TF %s",$1->name().c_str());\r
+                $$ = new asn1::classfield_tf($1->name());\r
+                delete ($1);\r
+                $$->flags($2);\r
+              }\r
+            | T_VALUEFIELDREFERENCE type_assign_right opt_unique opt_default\r
+              {\r
+                asn1::module *m = get_current_module();\r
+                ASN_LOG_DEBUG("oclass_field: valuefieldref FTVF %s",$1->name().c_str());\r
+                $$ = new asn1::classfield_ftvf($1->name(),$2->as_typenode());\r
+                delete ($1);\r
+                $2->set_parent(m->current_context());\r
+                $$->flags($4);\r
+              }\r
+            | T_VALUEFIELDREFERENCE field_name opt_default\r
+              {\r
+                asn1::module *m = get_current_module();\r
+                ASN_LOG_DEBUG("oclass_field: valuefieldref VTVF %s",$1->name().c_str());\r
+                $$ = new asn1::classfield_vtvf($1->name());\r
+                $$->set_reference($2);\r
+                $2->set_parent(m->current_context());\r
+                delete ($1);\r
+                $$->flags($3);\r
+              }\r
+            | T_VALUEFIELDREFERENCE defined_object_class opt_default\r
+              {\r
+                ASN_LOG_DEBUG("oclass_field: valuefieldref %s",$1->name().c_str());\r
+                $$ = new asn1::classfield_of($1->name());\r
+                delete ($1);\r
+                $$->flags($3);\r
+              }\r
+            | T_TYPEFIELDREFERENCE field_name opt_default\r
+              {\r
+                asn1::module *m = get_current_module();\r
+                ASN_LOG_DEBUG("oclass_field: typefieldref %s",$1->name().c_str());\r
+                $$ = new asn1::classfield_vtvsf($1->name());\r
+                delete ($1);\r
+                $$->set_reference($2);\r
+                $2->set_parent(m->current_context());\r
+                $$->flags($3);\r
+              }\r
+            | T_TYPEFIELDREFERENCE type opt_default\r
+              {\r
+                ASN_LOG_DEBUG("oclass_field: typefieldref %s",$1->name().c_str());\r
+                asn1::module *m = get_current_module();\r
+                $$ = new asn1::classfield_ftvsf($1->name(),$2->as_typenode());\r
+                delete ($1);\r
+                $2->set_parent(m->current_context());\r
+                $$->flags($3);\r
+              }\r
+            | T_TYPEFIELDREFERENCE defined_object_class opt_default\r
+              {\r
+                asn1::module *m = get_current_module();\r
+                ASN_LOG_DEBUG("oclass_field: typefieldref %s",$1->name().c_str());\r
+                asn1::typeref *_ref = new asn1::typeref($2,asn1::meta::TYPE);\r
+                _ref->set_parent(m->current_context());\r
+                $$ = new asn1::classfield_osf($1->name(),_ref);\r
+                $$->flags($3);\r
+              }\r
+;\r
+\r
+defined_object_class: \r
+  object_class_reference {\r
+    ASN_LOG_DEBUG("defined_object_class: object_class_reference");\r
+    $$ = $1; \r
+  }\r
+;\r
+\r
+/*\r
+ * ObjectSet rules X.681 pg 30 \r
+ */\r
+object_set:\r
+    T_LBRACET {ASN_LOG_DEBUG("object_set::Start");enable_object();} element_set_specs {disable_object();} T_RBRACET\r
+    {\r
+        ASN_LOG_DEBUG("object_set::TODO 1 %s",$3->name().c_str() );\r
+        $$ = $3;\r
+    }\r
+   | T_LOBJBRACET  element_set_specs  T_RBRACET\r
+    {\r
+        ASN_LOG_DEBUG("object_set::TODO 2 %s",$2->name().c_str());\r
+        $$ = $2;\r
+    }\r
+;\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+type_reference: T_TYPEREFERENCE\r
+                { \r
+                  if (! gLog.is_open() ) {\r
+                    open_log($1->name());\r
+                  }\r
+                  ASN_LOG_DEBUG("type_reference: %s",$1->name().c_str());\r
+                  $$ = new asn1::typeref($1->name(),\r
+                                 new asn1::simple_reference($1->name())\r
+                               );\r
+                  delete $1;               \r
+                }\r
+              | T_CAPITALREFERENCE\r
+                { // object reference\r
+                  $$ = new asn1::typeref($1->name(),\r
+                                 new asn1::objectclass_reference($1->name())\r
+                               );\r
+                  delete $1;               \r
+                }\r
+;\r
+\r
+value_reference: T_IDENTIFIER\r
+                { \r
+                    ASN_LOG_DEBUG("value_reference: Got ValueReference %s",$1->name().c_str());\r
+                    $$ = new asn1::typeref($1->name()\r
+                                         , new asn1::simple_reference($1->name()\r
+                                                      , asn1::reference::component::Lowercase)\r
+                               );\r
+                   delete $1;               \r
+                }\r
+               ;\r
+/** \r
+ *\r
+ */\r
+nstd_marker:\r
+  { \r
+  }\r
+;\r
+\r
+type_declaration:\r
+  nstd_marker type_assign_right\r
+  {\r
+    ASN_LOG_DEBUG("type_declaration: nstd_marker:%s",$2->name().c_str()); \r
+    $$ = $2;\r
+  }\r
+;\r
+\r
+\r
+\r
+type_assign_right: defined_type  \r
+  {\r
+     ASN_LOG_DEBUG("type_assign_right: defined_type:%s",$1->name().c_str()); \r
+     $$ = $1;\r
+     $$->type_id(asn1::type::ASN1_REFERENCE);\r
+     $$->meta_id(asn1::meta::TYPEREF);\r
+  }\r
+  | builtin_type {\r
+    ASN_LOG_DEBUG("type_assign_right: builtin :%s",$1->name().c_str()); \r
+    $$ = $1;\r
+  }\r
+;\r
+\r
+type_assign_right_tag: type_assign_right opt_constraint_def {\r
+    ASN_LOG_DEBUG("type_assign_right_tag: %s + opt_constraint_def %s",$1->name().c_str(),\r
+          ($2==NULL)?"none":$2->name().c_str()); \r
+    $$ = $1;\r
+    if ($2 != NULL)\r
+      $$->as_typenode()->constraint($2);\r
+  }\r
+  | tag type_assign_right opt_constraint_def {\r
+    ASN_LOG_DEBUG("type_assing_right_tag: tag type=%s opt_constaint_def",$2->name().c_str());\r
+    $$ = $2;\r
+    if ($2 != NULL)\r
+    $$->as_typenode()->constraint($3);\r
+    $$->tag($1);\r
+  }\r
+;\r
+\r
+type_assign_right_tag_default: \r
+   type_assign_right_tag opt_default {\r
+    ASN_LOG_DEBUG("type_assign_right_tag_default: + opt_default ");\r
+    $$=$1;\r
+    $$->flags($2);\r
+  }\r
+;\r
+\r
+sequence_def: T_SEQUENCE T_LBRACET   T_RBRACET\r
+                { \r
+                  asn1::module *m= get_current_module();\r
+                  m->enter_context(new asn1::sequence() );\r
+                  asn1::node *res = m->leave_context();\r
+                  $$ = res;\r
+                  $$->meta_id(asn1::meta::TYPE);\r
+                }\r
+            | T_SEQUENCE T_LBRACET \r
+              {\r
+                    ASN_LOG_DEBUG("sequence_def start -- with component_type_lists ");\r
+                    asn1::module *m= get_current_module();\r
+                    m->enter_context(new asn1::sequence() );\r
+                    $<module>$ = m;\r
+              }\r
+              opt_component_type_lists T_RBRACET\r
+              {\r
+                ASN_LOG_DEBUG("sequence_def: end  %s"\r
+                             ,$<module>3->name().c_str());\r
+                asn1::module *m =  (asn1::module *)$<module>3;\r
+                asn1::node *res = m->leave_context();\r
+                $$ = res; \r
+                $$->meta_id(asn1::meta::TYPE);\r
+              }\r
+            | T_SEQUENCE T_OF opt_identifier opt_tag type_declaration\r
+              {\r
+                ASN_LOG_DEBUG("seq_of type_declaration ");\r
+                asn1::node *ident = NULL;\r
+                $$  = new asn1::sequence_of($5);\r
+                if ( $3 == NULL)\r
+                {\r
+                  std::string ano("anonymous_seqof");\r
+                  ident = new asn1::node(ano.c_str());\r
+                  $5->identifier(ident);\r
+                } else\r
+                {\r
+                  ident = $3;\r
+                  $5->identifier($3);\r
+                }\r
+                asn1::module *m = get_current_module();\r
+                $5->set_parent(m->current_context());\r
+                if (m->current_context() == NULL)\r
+                {\r
+                  ASN_LOG_ERROR("seq_of opt_i opt_taf type_decl NOT GOOD"); \r
+                }\r
+                ident->set_parent(m->current_context());\r
+                if ($<node>4 != NULL)\r
+                  $5->tag($4);\r
+                $$->meta_id(asn1::meta::TYPE);\r
+              }\r
+            | T_SEQUENCE opt_constraint_def T_OF opt_identifier type_assign_right\r
+              {\r
+                $$  = new asn1::sequence_of($5);\r
+                if ( $4 == NULL)\r
+                {\r
+                  std::string ano("anonymous_seqofc");\r
+                  $5->identifier(new asn1::node(ano.c_str()) );\r
+                } else\r
+                  $5->identifier($4);\r
+                asn1::module *m = get_current_module();\r
+                $5->set_parent(m->current_context());\r
+                $$->as_typenode()->constraint($2);\r
+                $$->meta_id(asn1::meta::TYPE);\r
+              }\r
+;\r
+\r
+set_def: \r
+  T_SET T_LBRACET {\r
+            asn1::module *m = get_current_module();\r
+            m->enter_context(new asn1::set());\r
+            $<module>$ = m;\r
+         }\r
+         /*type_assign_list T_RBRACET */ \r
+         opt_component_type_lists T_RBRACET \r
+         {\r
+            asn1::module *m = get_current_module();\r
+            asn1::node *res = m->leave_context();\r
+            $$=res;\r
+            $$->meta_id(asn1::meta::TYPE);\r
+         }\r
+  | T_SET T_OF type_assign_right {\r
+            $$ = new asn1::set_of($3);\r
+            $$->meta_id(asn1::meta::TYPE);\r
+            asn1::module *m = get_current_module();\r
+            $3->set_parent(m->current_context());\r
+            std::string ano("anonymous_setof");\r
+            asn1::node *ident = new asn1::node(ano.c_str());\r
+            $3->identifier(ident);\r
+            ident->set_parent(m->current_context());\r
+         }\r
+  | T_SET T_OF T_IDENTIFIER type_assign_right {\r
+            $$ = new asn1::set_of($3);\r
+            $$->meta_id(asn1::meta::TYPE);\r
+            asn1::module *m = get_current_module();\r
+            $4->set_parent(m->current_context());\r
+            $4->identifier($3);\r
+         }\r
+  | T_SET opt_constraint_def T_OF type_assign_right  {\r
+            $$ = new asn1::set_of($4);\r
+            if ($2) $$->as_typenode()->constraint($2);\r
+            asn1::module *m = get_current_module();\r
+            if (m)\r
+              $4->set_parent(m->current_context());\r
+            $$->meta_id(asn1::meta::TYPE);\r
+            std::string ano("anonymous_setofc");\r
+            $4->identifier(new asn1::node(ano.c_str()) );\r
+         }\r
+  | T_SET opt_constraint_def T_OF T_IDENTIFIER type_assign_right  {\r
+            $$ = new asn1::set_of($5);\r
+            asn1::module *m = get_current_module();\r
+            if (m)\r
+              $5->set_parent(m->current_context());\r
+            if ($2) $$->as_typenode()->constraint($2);\r
+            $$->meta_id(asn1::meta::TYPE);\r
+            $5->identifier($4);\r
+         };\r
+;\r
+\r
+choice_def: T_CHOICE T_LBRACET \r
+            {\r
+                asn1::module *m = get_current_module();\r
+                m->enter_context( new asn1::choice());\r
+                $<module>$ = m;\r
+            }\r
+            /*type_assign_list */ alternative_type_lists T_RBRACET\r
+            {\r
+                asn1::module *m = get_current_module();\r
+                asn1::node *res = m->leave_context();\r
+                $$ = res;\r
+                $$->meta_id(asn1::meta::TYPE);\r
+            }\r
+;\r
+\r
+alternative_type_lists: alternative_type\r
+  {\r
+    asn1::parser::instance()->got_alternative_choice($1);\r
+  }\r
+  | alternative_type_lists T_COMMA alternative_type\r
+  {\r
+    asn1::parser::instance()->got_alternative_choice($3);\r
+  }\r
+;\r
+\r
+alternative_type:\r
+  T_IDENTIFIER type\r
+  {\r
+    asn1::module *m = get_current_module();\r
+    ASN_LOG_DEBUG("altenative_type: ident %s type %s",$1->name().c_str(),$2->name().c_str());\r
+    $$ = new asn1::field($1->name(),$2);\r
+    $2->set_parent(m->current_context());\r
+    if ($2->type_id()() == asn1::type::ASN1_SET_OF\r
+        || $2->type_id()() == asn1::type::ASN1_SEQUENCE_OF\r
+    )\r
+    {\r
+       asn1::typenode *subtype = $2->as_typenode()->get_eltype();\r
+       if (subtype && subtype->identifier()->get_parent() == NULL)\r
+       {\r
+         ASN_LOG_ERROR("altenative_type: ident %s type %s",$1->name().c_str(),$2->name().c_str());\r
+       }\r
+       $2->name($1->name()+"_t");\r
+    }\r
+    delete($1);\r
+  } \r
+  | extension_and_exception\r
+  {\r
+    ASN_LOG_DEBUG("altenative_type: extension and exception %s",$1->name().c_str());\r
+    $$ = $1;\r
+  }\r
+  | type \r
+  {\r
+    asn1::module *m = get_current_module();\r
+    ASN_LOG_WARNING("altenative_type: type =%s anonymous CHOICE attribute _%s(_t) %d",$1->name().c_str(),$1->name().c_str(),$1->type_id()());\r
+    std::string nm("_");\r
+    nm = nm+$1->name();\r
+    $$ = new asn1::field(nm.c_str(),$1);\r
+    $1->set_parent(m->current_context());\r
+    if ($1->type_id()() == asn1::type::ASN1_SEQUENCE\r
+    || $1->type_id()() == asn1::type::ASN1_CHOICE\r
+    )\r
+    {\r
+       $1->name($$->name()+"_t");\r
+    }\r
+  }\r
+;\r
+\r
+any_def: T_ANY\r
+       {\r
+         $$ = new asn1::any();\r
+       }\r
+       | T_ANY T_DEFINED T_BY T_IDENTIFIER {\r
+         ASN_LOG_DEBUG("any_def: DEPRECATED any defined by");\r
+         $$ = new asn1::any();\r
+         delete $4;\r
+       }\r
+;\r
+\r
+type: opt_tag builtin_type opt_constraint_def {\r
+        ASN_LOG_DEBUG("type: opt_tag builtin_type %s  %s"\r
+                     ,$2->name().c_str()\r
+                     ,($3 != NULL)?$3->name().c_str():"No constraint"\r
+                     );\r
+          $$= $2;\r
+          if ($3 != NULL)\r
+          {\r
+            $$->as_typenode()->constraint($3);\r
+          }\r
+          $$->tag($1);\r
+  }\r
+  | opt_tag referenced_type opt_constraint_def {\r
+        ASN_LOG_DEBUG( "type: opt_tag referenced_type %s %s"\r
+                     , $2->name().c_str()\r
+                     , ($3 != NULL)?$3->name().c_str():"No constraint"\r
+                     );\r
+        $$ = $2;\r
+        if ($3 != NULL)\r
+        $$->as_typenode()->constraint($3);\r
+        $$->tag($1);\r
+  }\r
+;\r
+\r
+builtin_type: boolean_def \r
+              {$$ = $1;}\r
+            /**\r
+             * Enum Int and bit String have someting in common. They can contain a list of literals\r
+             */\r
+             | integer_def { $$ = $1; }\r
+             | enumerated_def  {$$ = $1;}\r
+             | bit_string_def {$$ = $1;} \r
+             | real_def {$$ = $1;}\r
+             | time_def { $$ = $1;}\r
+             | octet_string_def {$$ =$1;}\r
+             | object_def {$$ = $1;}\r
+             | object_class_def {$$ = $1;}\r
+             | character_string_def \r
+               {\r
+                 $$ =$1;\r
+               }\r
+             | sequence_def { $$ = $1;}\r
+             | choice_def { $$ = $1;}\r
+             | any_def {$$ = $1;}\r
+             | set_def {$$ = $1;}\r
+             | T_EXTERNAL {\r
+               $$ = new asn1::external();\r
+             }\r
+             | T_RELATIVE_OID {\r
+               ASN_LOG_DEBUG("builtin_type: relative_OID");\r
+               $$ = new asn1::relative_oid();\r
+             }\r
+             | T_NULL  {$$ =new asn1::null();}\r
+;\r
+\r
+/**\r
+ * Don't used type_reference as defined_type already references it\r
+ */\r
+referenced_type: defined_type\r
+                 {\r
+                   // defined_type is of type asn1::typeref\r
+                   if ($1 != NULL)\r
+                   {\r
+                     $$ = $1;\r
+                     // Should not be required\r
+                     $$->type_id(asn1::type::ASN1_REFERENCE);\r
+                     $$->meta_id(asn1::meta::TYPEREF);\r
+                     ASN_LOG_DEBUG("referenced_type: defined_type %s",$1->name().c_str());\r
+                   } else {\r
+                     ASN_LOG_ERROR("referenced_type: defined_type NULL %lx",(long)$1);\r
+                   }\r
+                 }\r
+               | identifier T_LT type\r
+                 {\r
+                   ASN_LOG_DEBUG("referenced_type got selection type %s",$1->name().c_str());\r
+                   $$  = new asn1::selection($1->name(),$3);;\r
+                   delete($1);\r
+                 }\r
+               ;\r
+\r
+field_name: T_TYPEFIELDREFERENCE\r
+            {\r
+               ASN_LOG_WARNING("field_name : %s",$1->name().c_str());\r
+               $$ = $1;\r
+            }\r
+          | field_name T_POINT T_TYPEFIELDREFERENCE\r
+            {\r
+               ASN_LOG_WARNING("field_name 2 %s . %s ",$1->name().c_str(),$3->name().c_str());\r
+               $$->add_components($3->get_components());\r
+               delete($3);\r
+            }\r
+          | field_name T_POINT T_VALUEFIELDREFERENCE\r
+            {\r
+               ASN_LOG_WARNING("field_name 3 %s %s",$1->name().c_str(),$3->name().c_str());\r
+               $$->add_components($3->get_components());\r
+               delete($3);\r
+            }\r
+;\r
+\r
+/* TypeAssignment X.680 TypeAssignment -> typereference "::=" Type */\r
+type_assignment: T_TYPEREFERENCE T_ASSIGN type_assign_right_tag \r
+        {\r
+          // Set parent of type.\r
+          asn1::module *m= get_current_module();\r
+          $3->set_parent(m);\r
+\r
+          if ($3->type_id()() == asn1::type::ASN1_CHOICE) {\r
+             ASN_LOG_DEBUG("type is CHOICE set name to %s_t",$1->cpp_name().c_str());\r
+             $3->name($1->cpp_name()+"_t");\r
+          }\r
+#ifdef DEBUG\r
+     if ($3 == NULL) {printf("ERROR type is NULL"); }\r
+     ASN_LOG_DEBUG("\ntype_assignment : T_TYPEREFERENCE %s en tant que: %s %d\n",\r
+     $1->name().c_str()\r
+           ,$3->name().c_str()\r
+           ,$3->type_id()());\r
+#endif\r
+           if ( ($3->type_id() >= asn1::type::ASN1_SEQUENCE ) &&\r
+                ($3->type_id() <= asn1::type::ASN1_TYPE_MAX))\r
+           {\r
+             $$ = new asn1::type_assignment($1->name());\r
+           } else if ($3->type_id() == asn1::type::ASN1_VALUESET)\r
+           {\r
+             $$ = new asn1::valueset_assignment($1->name());\r
+           } else if ($3->type_id() == asn1::type::ASN1_REFERENCE)\r
+           {\r
+             /* THIS IS WRONG  A::= B Is a TYPE definition  \r
+              * B Is Ref and A Is new Type */\r
+             $$ = new asn1::typeref_assignment($1->name());\r
+             //$$ = new asn1::type_assignment($1->name());\r
+           }\r
+           $$->type_node($3);\r
+           $3->identifier($$);\r
+           delete($1);\r
+        }\r
+        | type_reference  parameter_list T_ASSIGN type_assign_right_tag\r
+        {\r
+           ASN_LOG_DEBUG("type_assignment : type_reference %s {} en tant que:",$1->name().c_str());\r
+           ASN_LOG_DEBUG("");\r
+           // Set parent of type.\r
+           asn1::module *m= get_current_module();\r
+           $4->set_parent(m);\r
+             \r
+           if ( ($4->type_id() >= asn1::type::ASN1_SEQUENCE ) &&\r
+                ($4->type_id() <= asn1::type::ASN1_TYPE_MAX))\r
+           {\r
+             $$ = new asn1::type_assignment($1->name());\r
+           } else if ($4->type_id() == asn1::type::ASN1_VALUESET)\r
+           {\r
+             std::cerr<<"p  "<<$1->name()<<std::endl;\r
+             $$ = new asn1::valueset_assignment($1->name());\r
+             //$$->set_reference($1->get_reference()); \r
+           } else if ($4->type_id() == asn1::type::ASN1_REFERENCE)\r
+           {\r
+             $$ = new asn1::typeref_assignment($1->name());\r
+           }\r
+           $4->identifier($$);\r
+           $$->type_node($4);\r
+           $$->parameters($2->as_parameters());\r
+           delete($1); \r
+\r
+        }\r
+        | T_CAPITALREFERENCE T_ASSIGN type_assign_right_tag\r
+          {\r
+             ASN_LOG_DEBUG("\ntype_assignement: T_CAPITALREFERENCE  Object Class or type %s meta=%d"\r
+                          ,$1->name().c_str()\r
+                          ,$3->meta_id()()\r
+                          );\r
+             ASN_LOG_DEBUG("");\r
+             // Set parent of type.\r
+             asn1::module *m= get_current_module();\r
+             $3->set_parent(m);\r
+             // $1 is either object class assignment or type assignment \r
+             switch($3->meta_id()())\r
+             {\r
+#define ASSIGNMENT(tp,cls,parent) \\r
+               case asn1::meta::tp:           \\r
+                 $$ = new asn1::cls##_assignment($1->name()); \\r
+                 break;\r
+               default:\r
+               ;\r
+#include "adt/asn1_meta.inc"\r
+             }\r
+             $3->identifier($$);\r
+             //$$ = $1;\r
+             $$->type_node($3);\r
+          }\r
+;\r
+\r
+parameter_list: T_LBRACET {\r
+    asn1::module *m = get_current_module();\r
+    m->enter_context(new asn1::parameters());\r
+    $<module>$ = m;\r
+    ASN_LOG_DEBUG("parameter_list enter  (params ...)");\r
+  } parameter_args T_RBRACET\r
+  {\r
+    asn1::module *m =  (asn1::module *)$<module>2;\r
+    asn1::node *res = m->leave_context();\r
+    ASN_LOG_DEBUG("parameter_list leave (params %s)",res->name().c_str());\r
+    $$ = res;\r
+  }\r
+;\r
+\r
+parameter_args: parameter_arg\r
+  {\r
+    ASN_LOG_DEBUG("parameter_args: %s",$1->cpp_name().c_str());\r
+    asn1::parser::instance()->got_parameter($1);\r
+  }\r
+  | parameter_args T_COMMA parameter_arg\r
+  {\r
+    ASN_LOG_DEBUG("parameter_args: %s",$3->cpp_name().c_str());\r
+    asn1::parser::instance()->got_parameter($3);\r
+  }\r
+;\r
+\r
+parameter_arg: \r
+    type_reference {\r
+        ASN_LOG_DEBUG("parameter_arg 0: %s(tp=%d)",$1->name().c_str(),$1->type_id()());\r
+        $$ = new asn1::parameter(NULL,$1->as_typeref());\r
+    }\r
+    | type_reference T_COLON type_reference {\r
+        ASN_LOG_DEBUG("parameter_arg 1: %s(tp=%d) : %s(tp=%d)",$1->name().c_str(),$1->type_id()(),\r
+          $3->name().c_str(),$3->type_id()());    \r
+        $$ = new asn1::parameter($1,$3->as_typeref());\r
+    }\r
+    | type_reference T_COLON value_reference {\r
+        ASN_LOG_DEBUG("parameter_arg 2: %s(tp=%d) : %s(tp=%d)",$1->name().c_str(),$1->type_id()(),\r
+          $3->name().c_str(),$3->type_id()());    \r
+        $$ = new asn1::parameter($1,$3->as_typeref());\r
+    }\r
+    | type T_COLON type_reference {\r
+        ASN_LOG_DEBUG("parameter_arg 3: %s(tp=%d) : %s(tp=%d)",$1->name().c_str(),$1->type_id()(),\r
+          $3->name().c_str(),$3->type_id()());    \r
+        $$ = new asn1::parameter($1,$3->as_typeref());\r
+    }\r
+    | type T_COLON value_reference {\r
+        ASN_LOG_DEBUG("parameter_arg 4: %s(tp=%d):%s",$1->name().c_str(),$1->type_id()(),$3->name().c_str());\r
+        $$ = new asn1::parameter($1,$3->as_typeref());\r
+    }\r
+;\r
+/**\r
+| type_reference T_COLON T_IDENTIFIER {\r
+        ASN_LOG_DEBUG("parameter_arg 2: %s:%s",$1->name().c_str(),$3->name().c_str());\r
+        $$ = $1;\r
+        $$->identifier($3);\r
+    }\r
+*/\r
+\r
+act_parameter_args:act_parameter_arg\r
+  {\r
+    ASN_LOG_DEBUG("act_parameter_args %s",$1->name().c_str());\r
+    asn1::parser::instance()->got_act_parameter($1);\r
+    $$ = $1;\r
+  }\r
+  | act_parameter_args T_COMMA act_parameter_arg\r
+  {\r
+    ASN_LOG_DEBUG("act_parameter_args next %s",$3->name().c_str());\r
+    asn1::parser::instance()->got_act_parameter($3);\r
+  }\r
+;\r
+\r
+act_parameter_arg: type\r
+  {\r
+    if ($1 != NULL)\r
+    { \r
+      ASN_LOG_DEBUG("act_parameter_arg:type declaration:%s",$1->name().c_str());\r
+    } else {\r
+      ASN_LOG_DEBUG("act_parameter_arg:type declaration: without identifier");\r
+    }\r
+    $$ = $1;\r
+  }\r
+  | value_set\r
+  {\r
+     ASN_LOG_DEBUG("act_parameter_arg : value_set");\r
+     $$= new asn1::valueset($1); \r
+  }\r
+  | object_set\r
+  {\r
+     ASN_LOG_DEBUG("act_parameter_arg : object_set %s",$1->name().c_str());\r
+     $$= new asn1::objectset($1); \r
+  }\r
+  | value\r
+  {\r
+     ASN_LOG_DEBUG("act_parameter_arg: value ");\r
+     $$ = $1;\r
+  }\r
+  | type_reference {\r
+     ASN_LOG_DEBUG("act_parameter_arg:reference %s",$1->name().c_str());\r
+  }\r
+   /*\r
+     | defined_object_class\r
+     | object\r
+   \r
+   */\r
+;\r
+\r
+/* */\r
+value_assignment: \r
+    T_IDENTIFIER T_OBJECT T_STR_IDENTIFIER T_ASSIGN T_LBRACET \r
+     obj_constant_list T_RBRACET\r
+    {\r
+      ASN_LOG_DEBUG( "value_assignment : ident %s OID "\r
+                   , $1->name().c_str()\r
+                   );\r
+      asn1::module *m = get_current_module();\r
+      asn1::node *i = m->leave_context(); \r
+      i->meta_id(asn1::meta::VALUE);\r
+      i->set_parent(m->current_context());\r
+      $$ = new asn1::value_assignment($1->name()); \r
+      i->identifier($$);\r
+      $$->type_node(i);\r
+      delete ($1);\r
+    }\r
+    | identifier T_TYPEREFERENCE T_ASSIGN T_LBRACET \r
+     obj_constant_list T_RBRACET\r
+    {\r
+        ASN_LOG_WARNING("value_assignment : ident %s type=%s OID 1 TO BE FINALIZED",$1->name().c_str(),$2->name().c_str());\r
+        asn1::module *m = get_current_module();\r
+        asn1::node *i = m->leave_context(); \r
+        i->set_parent(m->current_context());\r
+        $$ = new asn1::value_assignment($1->name());\r
+        i->identifier($$);\r
+        $$->type_node(i);\r
+        // Missing typeref somewhere\r
+    }\r
+    | identifier T_TYPEREFERENCE T_ASSIGN T_LBRACET restricted_character_string_value T_RBRACET {\r
+         ASN_LOG_WARNING("value_assignment : ident %s type=%s STR value=%s TO BE FINALIZED",$1->name().c_str(),$2->name().c_str(),$5->name().c_str());\r
+         asn1::node *i = new asn1::node("CONST STRING",asn1::meta::VALUE);\r
+         i->type_id(asn1::type::ASN1_OBJECT_IDENTIFIER);\r
+         $$ = new asn1::value_assignment($1->name());\r
+         $5->identifier($$);\r
+         i->identifier($$);\r
+         $$->type_node(i);\r
+         $2->type_id(asn1::type::ASN1_REFERENCE);\r
+         delete($1);\r
+    }\r
+    | identifier restricted_character_string_def T_ASSIGN restricted_character_string_value \r
+    {\r
+         ASN_LOG_WARNING("value_assignment : ident type=%s string"\r
+                         , $1->name().c_str());\r
+         asn1::node *i = new asn1::node("CONST STRING",asn1::meta::VALUE);\r
+         i->type_id(asn1::type::ASN1_STRING);\r
+         $$ = new asn1::value_assignment($1->name());\r
+         $4->identifier($$);\r
+         i->identifier($$);\r
+         $$->type_node(i);\r
+         $$->value(new asn1::value(asn1::value::VT_STRING));\r
+         delete($1);\r
+    }\r
+    | identifier T_INTEGER T_ASSIGN value {\r
+         ASN_LOG_WARNING("value_assignment : ident %s type INTEGER value=%s TO BE FINALIZED",$1->name().c_str(),$4->name().c_str());\r
+         asn1::node *i = $4;\r
+         $$ = new asn1::value_assignment($1->name());\r
+         i->identifier($$);\r
+         $$->type_node(i); //TODO remove\r
+         $$->meta_id(asn1::meta::VALUE);\r
+         $$->value($4->value());\r
+         delete($1);\r
+    }\r
+    | identifier T_TYPEREFERENCE T_ASSIGN value {\r
+         ASN_LOG_WARNING("value_assignment : ident %s type=%s value=%s TO BE FINALIZED",$1->name().c_str(),$2->name().c_str(),$4->name().c_str());\r
+         asn1::node *tr = new asn1::typeref( new asn1::simple_reference($2->name()));\r
+         delete($2); \r
+         $$ = new asn1::value_assignment($1->name());\r
+         tr->identifier($$);\r
+         $$->type_node(tr);\r
+         if ($4->meta_id()() == asn1::meta::VALUE) \r
+         {\r
+           $$->value($4->value());\r
+         }\r
+         delete($1);\r
+    }\r
+    | identifier T_TYPEREFERENCE T_ASSIGN T_LBRACET value T_RBRACET {\r
+         /* Needed for Attribute-ASN1Module.asn1 line 205 */\r
+         ASN_LOG_WARNING("value_assignment : N ident %s type=%s value=%s TO BE FINALIZED",$1->name().c_str(),$2->name().c_str(),$5->name().c_str());\r
+         asn1::node *tr = new asn1::typeref( new asn1::simple_reference($2->name()));\r
+         delete($2); \r
+         $$ = new asn1::value_assignment($1->name());\r
+         tr->identifier($$);\r
+         tr->meta_id(asn1::meta::TYPEREF);\r
+         tr->type_id(asn1::type::ASN1_REFERENCE);\r
+         $$->type_node(tr);\r
+         if ($5->meta_id()() == asn1::meta::VALUE) \r
+         {\r
+           $$->value($5->value());\r
+         }\r
+         delete($1);\r
+    }\r
+/*\r
+*/\r
+;\r
+\r
+/**\r
+ * value_range rules\r
+ */\r
+value_range:\r
+  value constraint_range_spec value {\r
+    ASN_LOG_DEBUG("value_range %s .. %s",$1->name().c_str(),$3->name().c_str());\r
+    asn1::constraint_range *cr = dynamic_cast<asn1::constraint_range *>($2);\r
+    cr->set_min_max($1,$3);\r
+    $$ = $2;\r
+  }\r
+;\r
+\r
+constraint_range_spec : T_TWOPOINT {\r
+     ASN_LOG_DEBUG("constraint_range_spec .. ");\r
+     $$= new asn1::celt_range();   \r
+   }\r
+   | T_TWOPOINT T_LT {\r
+     ASN_LOG_DEBUG("constraint_range_spec ..< ");\r
+     $$= new asn1::celt_rlrange();   \r
+   }\r
+   | T_LT T_TWOPOINT {\r
+     ASN_LOG_DEBUG("constraint_range_spec < .. ");\r
+     $$= new asn1::celt_llrange();   \r
+   }\r
+   | T_LT T_TWOPOINT T_LT {\r
+     ASN_LOG_DEBUG("constraint_range_spec <..< ");\r
+     $$= new asn1::celt_ulrange();   \r
+   }\r
+;\r
+\r
+/**\r
+ *\r
+ */\r
+value: builtin_value {\r
+    ASN_LOG_DEBUG( "value: builtin_value : %s id=%d"\r
+                 , ($1 != NULL)?$1->cpp_name().c_str():"null"\r
+                 , ($1 != NULL)?$1->type_id()(): -1\r
+                 );\r
+    $$ = $1;\r
+    $$->meta_id(asn1::meta::VALUE);\r
+  }\r
+  /* ReferencedValue */\r
+  | defined_value\r
+  {\r
+    ASN_LOG_DEBUG("value: defined_value   ..");\r
+    $$->meta_id(asn1::meta::VALUE);\r
+    asn1::value *v = new asn1::value($1->name());\r
+    $$->value(v);\r
+    $$ = $1;\r
+  }\r
+  | value_from_object {\r
+    ASN_LOG_DEBUG("value: value_from_object   ..");\r
+    $$ = $1;\r
+    $$->meta_id(asn1::meta::VALUE);\r
+  }\r
+;\r
+/* Refuse empty builtin value\r
+      ASN_LOG_WARNING("builtin_value: NONE return NULL");\r
+      $$=NULL;\r
+    }\r
+ */\r
+builtin_value: \r
+    /* Boolean value*/\r
+     T_ASN1_TRUE {\r
+      ASN_LOG_DEBUG("builtin_value: Boolean Value TRUE ");\r
+      $$ = new asn1::valuetype( new asn1::value(asn1::value::VT_TRUE));\r
+    }\r
+    | T_ASN1_FALSE {\r
+      ASN_LOG_DEBUG("builtin_value: Boolean Value FALSE ");\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_FALSE));\r
+    }\r
+    | T_NULL {\r
+      ASN_LOG_DEBUG("builtin_value: NullValue NULL ");\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_NULL));\r
+    }\r
+    | pos_neg_num {\r
+      ASN_LOG_DEBUG("builtin_value: IntegerValue pos_neg_num %s",$1->name().c_str());\r
+      $$ = $1;\r
+    }\r
+    | T_IDENTIFIER T_COLON value {\r
+      ASN_LOG_DEBUG("builtin_value: ChoiceValue identifier:value %s:%s (%d)"\r
+                   , $1->name().c_str()\r
+                   , $3->name().c_str()\r
+                   , $3->type_id()()\r
+                   );\r
+      asn1::valuetype *vt = new asn1::valuetype(std::string($1->name()),NULL);\r
+      vt->type_id(asn1::type::ASN1_CHOICE);\r
+      vt->identifier($1);\r
+      asn1::value *v = new asn1::value(asn1::value::VT_COLON);\r
+      v->m_node = $3;\r
+      vt->value(v);\r
+      $$ = vt;\r
+    }\r
+    | set_value {\r
+      /* SET_value can actually be an oid or {component_list }\r
+       *  VALUESET is element_set_specs !!!\r
+       */\r
+      ASN_LOG_ERROR("builtin_value: set_value %s id=%d wrong VT_VALUESET for set"\r
+                    ,$1->name().c_str()\r
+                    ,$1->type_id()()\r
+                   );\r
+      if ($1->is_object_identifier())\r
+      {\r
+        $$ = $1;\r
+      } else\r
+      {\r
+        asn1::valuetype *vt = new asn1::valuetype(std::string($1->name()),NULL);\r
+        asn1::value *v = new asn1::value(asn1::value::VT_SETVALUE);\r
+        v->m_node = $1;\r
+        vt->value(v);\r
+        $$ = vt;\r
+      }\r
+    }\r
+    | T_bstring {\r
+      ASN_LOG_ERROR("builtin_value got binary string");\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_BITVECTOR));\r
+    }\r
+    | T_hstring {\r
+      ASN_LOG_ERROR("builtin_value got hstring string");\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_BITVECTOR));\r
+    }\r
+    | T_MIN {\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_MIN));\r
+    }\r
+    | T_MAX {\r
+      $$ = new asn1::valuetype(new asn1::value(asn1::value::VT_MAX));\r
+    }\r
+    | T_Quadruple {\r
+      ASN_LOG_WARNING("builtin_value got quadruple TO BE CODED");\r
+      $$ = new asn1::valuetype(std::string("Quadrupple"),NULL);\r
+    }\r
+    | T_Tuple {\r
+      ASN_LOG_WARNING("builtin_value got tuple TO BE CODED");\r
+      $$ = new asn1::valuetype(std::string("TUPLE"),NULL);\r
+    }\r
+;\r
+\r
+defined_value:\r
+    identifier {\r
+      asn1::value *v = new asn1::value(asn1::value::VT_REFERENCED);\r
+      v->m_string    = $1->name();\r
+      $$ = new asn1::valuetype($1->name(),v);\r
+      ASN_LOG_DEBUG("defined_value: %s",$1->name().c_str());\r
+      delete $1;\r
+    }\r
+    | parameterized_value { \r
+      ASN_LOG_DEBUG("defined_value: parameterized_value %s",$1->name().c_str());\r
+      $$ = $1; \r
+    }\r
+;\r
+\r
+parameterized_value: \r
+  identifier T_LBRACET  {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    m->enter_context(new asn1::act_parameters());\r
+    $<module>$ = m;\r
+    ASN_LOG_DEBUG("parameterized_value enter %s (params ...)",$1->name().c_str());\r
+  } act_parameter_args T_RBRACET\r
+  {\r
+    asn1::module *m =  (asn1::module *)$<module>3;\r
+    asn1::node *res = m->leave_context();\r
+    ASN_LOG_DEBUG("parameterized_value leave (params %s)",res->name().c_str());\r
+    $$ = $1;\r
+    $$->parameters(res->as_parameters());\r
+  }\r
+;\r
+\r
+parameterized_objectset: \r
+   T_TYPEREFERENCE T_LOBJBRACET  {\r
+    asn1::parser *p = asn1::parser::instance();\r
+    asn1::module *m= (asn1::module *) p->module();\r
+    m->enter_context(new asn1::act_parameters());\r
+    $<module>$ = m;\r
+    ASN_LOG_DEBUG("parameterized_objectset enter %s (params ...)",$1->name().c_str());\r
+  } act_parameter_args T_RBRACET\r
+  {\r
+    asn1::module *m =  (asn1::module *)$<module>3;\r
+    asn1::node *res = m->leave_context();\r
+    ASN_LOG_DEBUG("parameterized_objectset leave (params %s { %s })",$1->name().c_str(),res->name().c_str());\r
+    $$ = $1;\r
+    $$->parameters(res->as_constructed());\r
+  }\r
+;\r
+\r
+\r
+\r
+\r
+value_from_object: \r
+    T_CAPITALREFERENCE  T_POINT field_name {  \r
+      ASN_LOG_WARNING("value_from_object(0) Capital INCOMPLETE %s.%s",\r
+           $1->name().c_str()\r
+         , $3->name().c_str());\r
+      //asn1::reference *ref = new asn1::objectclass_reference($1->name());\r
+      //$$ = new asn1::typeref(ref);\r
+      $$ = $1; \r
+    }\r
+    | T_TYPEREFERENCE T_POINT field_name {\r
+      ASN_LOG_DEBUG("value_from_object(1) Reference %s.%s",\r
+           $1->name().c_str()\r
+         , $3->name().c_str());\r
+      asn1::typeref *tref = new asn1::typeref($1->name(),\r
+                             new asn1::simple_reference($1->name())\r
+                            );\r
+      tref->get_reference()->add_components($3->get_components());\r
+      $$ = tref;\r
+      delete $1;\r
+    }\r
+    | identifier T_POINT primitive_field_reference {\r
+     ASN_LOG_WARNING("value_from_object(2) Identifier INCOMPLETE  %s.%s"\r
+       , $1->name().c_str()\r
+       , $3->m_identifier.c_str());\r
+     $$ = $1;\r
+     delete $3;\r
+    }\r
+;\r
+/* value set */\r
+constant_set_def: \r
+    type_reference defined_type T_ASSIGN value_set {\r
+                 ASN_LOG_ERROR("constant_set_def:%s",$1->name().c_str());\r
+                 $$ = new asn1::valueset_assignment($1->name());\r
+                 $$->type_node($2);\r
+                 $2->identifier($$);\r
+                 $2->as_typenode()->constraint($4);\r
+                 delete($1);\r
+    }\r
+    |  type_reference builtin_type T_ASSIGN value_set {\r
+                 ASN_LOG_ERROR("constant_set_def:%s of type: %s",$1->name().c_str(),$2->cpp_name().c_str());\r
+                 $$ = new asn1::valueset_assignment($1->name());\r
+                 //$$->set_reference($1->get_reference()); \r
+                 $$->type_node($2);\r
+                 $2->identifier($$);\r
+                 //$$->constraint($4);\r
+                 $2->as_typenode()->constraint($4);\r
+                 delete($1);\r
+    }\r
+;\r
+\r
+\r
+defined_type:  /* * More complex types */ \r
+  complex_type_reference T_LBRACET {\r
+      ASN_LOG_DEBUG("defined_type: 1 %s start (params:...)",$1->name().c_str());\r
+      asn1::parser *p = asn1::parser::instance();\r
+      asn1::module *m= (asn1::module *) p->module();\r
+      m->enter_context(new asn1::act_parameters());\r
+      $<module>$ = m;\r
+  }\r
+  act_parameter_args T_RBRACET {\r
+      asn1::module *m =  (asn1::module *)$<module>3;\r
+      asn1::node *res = m->leave_context();\r
+      ASN_LOG_DEBUG( "defined_type: 1 end  (params: %s) %p"\r
+                   , res->name().c_str()\r
+                   , res->as_constructed()\r
+      );\r
+      $$ = new asn1::typeref($1);\r
+      $$->act_parameters(res->as_constructed());\r
+  }\r
+  | complex_type_reference {\r
+      ASN_LOG_DEBUG("defined_type: complex_type_reference <%s>",$1->name().c_str());\r
+     $$ = new asn1::typeref($1);\r
+  }\r
+;\r
+\r
+complex_type_reference: \r
+  T_TYPEREFERENCE {\r
+      /* simple_defined_type reference */\r
+      $$ = new asn1::simple_reference($1->name());\r
+      delete($1);\r
+  }\r
+  | T_TYPEREFERENCE T_POINT type_reference {\r
+      /* External reference : Module reference . type_reference */\r
+      $$ = new asn1::reference();\r
+      asn1::reference::component c;\r
+      c.m_identifier =$1->name();\r
+      c.type = asn1::reference::component::Uppercase;\r
+      $$->add_component(c);\r
+      delete($1);\r
+      c.m_identifier = $3->name();\r
+      $$->add_component(c);\r
+      delete $3;\r
+\r
+  }\r
+  | object_class_reference  T_POINT type_reference {\r
+    $$ = $1;\r
+    ASN_LOG_DEBUG("complex_type_reference: %s . %s",$1->name().c_str(),$3->name().c_str());\r
+    asn1::reference::component c;\r
+    c.m_identifier = $3->name();\r
+    c.type = asn1::reference::component::Uppercase;\r
+    $1->add_component(c);\r
+    delete $3;\r
+  }\r
+  | T_TYPEREFERENCE T_POINT T_IDENTIFIER {\r
+      /* External reference : Module reference . value_reference */\r
+      $$ = new asn1::reference();\r
+      asn1::reference::component c;\r
+      c.m_identifier =$1->name();\r
+      c.type = asn1::reference::component::Uppercase;\r
+      $$->add_component(c);\r
+      delete($1);\r
+      c.m_identifier = $3->name();\r
+      c.type = asn1::reference::component::Lowercase;\r
+      $$->add_component(c);\r
+      delete $3;\r
+  }\r
+  | object_class_reference\r
+  {\r
+    ASN_LOG_DEBUG("complex_type_reference: %s ",$1->name().c_str());\r
+    $$ = $1;\r
+  }\r
+  | object_class_reference T_POINT {current_ref = $1;} complex_type_reference_amp_list {\r
+    $$ = $1;\r
+    ASN_LOG_DEBUG("complex_type_reference: %s .& %s",$1->name().c_str(),$4->m_identifier.c_str());\r
+    delete $4;\r
+  }\r
+;\r
+\r
+complex_type_reference_amp_list:\r
+  complex_type_reference_element {\r
+    ASN_LOG_DEBUG("complex_type_reference_apm_list 1: %s ",$1->m_identifier.c_str());\r
+    current_ref->add_component(*$1);\r
+  }\r
+  | complex_type_reference_amp_list T_POINT complex_type_reference_element {\r
+    ASN_LOG_DEBUG("complex_type_reference_apm_list 2: should add %s ",$3->m_identifier.c_str());\r
+    // Its' a ref_comp\r
+    current_ref->add_component(*$3);\r
+  }\r
+;\r
+\r
+complex_type_reference_element: primitive_field_reference\r
+                              ;\r
+primitive_field_reference:\r
+  T_TYPEFIELDREFERENCE\r
+    {\r
+        ASN_LOG_DEBUG("primitive_field_reference: TYPEFIELDREFRENE %s",$1->name().c_str());\r
+        asn1::reference::component *c = new asn1::reference::component;\r
+        c->m_identifier =$1->name();\r
+        c->type = asn1::reference::component::AmpUppercase;\r
+        delete $1;\r
+        $$ = c;\r
+    }\r
+  | T_VALUEFIELDREFERENCE\r
+    {\r
+        ASN_LOG_DEBUG("primitive_field_reference: VALUEREFERENCE %s",$1->name().c_str());\r
+        asn1::reference::component *c = new asn1::reference::component;\r
+        c->m_identifier =$1->name();\r
+        c->type = asn1::reference::component::AmpLowercase;\r
+        delete $1;\r
+        $$ = c;\r
+    }\r
+;\r
+\r
+object_class_reference: T_CAPITALREFERENCE /* X.681 7.1 */\r
+  {\r
+      ASN_LOG_DEBUG("object_class_reference: %s",$1->name().c_str());\r
+      \r
+      $$ = new asn1::objectclass_reference($1->name());\r
+      delete($1);\r
+  }\r
+;\r
+\r
+// Be carefull value_set and set_value are two different things .\r
+// I don't think that enter context is required. As element_set_specs is a constraint.\r
+value_set: T_LBRACET \r
+    {\r
+      ASN_LOG_DEBUG("value_set start");\r
+    }\r
+    element_set_specs T_RBRACET\r
+    {\r
+    /**\r
+     */\r
+      ASN_LOG_DEBUG("value_set END");\r
+      $$ = $3;\r
+    }\r
+;\r
+\r
+/** \r
+ * In term of BRACET cant be a set or an OID\r
+ *  -> set_value which_list = component_value_list\r
+ *  -> OID obj_constant_list\r
+ *  -> constraint ? why\r
+ */\r
+set_value: T_LBRACET {\r
+      ASN_LOG_DEBUG("set_value start");\r
+      asn1::parser *p = asn1::parser::instance();\r
+      asn1::module *m= (asn1::module *) p->module();\r
+       //m->enter_context("set_value",asn1::type::INVALID);\r
+      m->enter_context(new asn1::constructed(std::string("set_value 1")));\r
+       $<module>$ = m;\r
+     } \r
+     which_list T_RBRACET\r
+     {\r
+\r
+       asn1::module *m =  (asn1::module *)$<module>2;\r
+       asn1::node *res = m->leave_context();       \r
+       $$ = res;\r
+      if ($3 != NULL && $3->type_id()() == asn1::type::ASN1_OBJECT_IDENTIFIER)\r
+      {\r
+        $$ = $3;\r
+        $$->type_id(asn1::type::ASN1_OBJECT_IDENTIFIER);\r
+        $$->meta_id(asn1::meta::VALUE);\r
+        $$->name("OBJECT_IDENTIFIER");\r
+        delete res;\r
+        ASN_LOG_DEBUG("set_value end GOT OID %d",$3->type_id()());\r
+      } else  if ($3 != NULL && $3->type_id()() == asn1::type::ASN1_REFERENCE)\r
+      {\r
+        $$->meta_id(asn1::meta::VALUE);\r
+        res->as_typenode()->constraint(*($3->as_typeref()->constraint_begin()));\r
+        delete $3;\r
+        ASN_LOG_DEBUG("set_value end GOT VALUE probably ref");\r
+        assert( 0 && "set_value list contains reference ! is this possible ?");\r
+      } else {\r
+        $$->meta_id(asn1::meta::VALUE);\r
+        ASN_LOG_DEBUG("set_value end GOT VALUE NULL");\r
+      }\r
+     } \r
+;\r
+\r
+which_list:  obj_constant_list {\r
+      // node\r
+      ASN_LOG_DEBUG("which_list obj_constant_list");\r
+      asn1::parser *p = asn1::parser::instance();\r
+      asn1::module *m= (asn1::module *) p->module();\r
+      asn1::node *ids = m->leave_context();\r
+      $$ = ids;\r
+    }\r
+    | opt_component_value_list {\r
+      // node\r
+      ASN_LOG_DEBUG("which_list component_value");\r
+      $$ = NULL;\r
+    }\r
+;\r
+opt_component_value_list: /* Empty */\r
+  | component_value_list {\r
+      ASN_LOG_DEBUG("opt_component_value_list");\r
+  }\r
+;\r
+component_value_list:component_value {\r
+        asn1::parser *p = asn1::parser::instance();\r
+        asn1::module *m= (asn1::module *) p->module();\r
+        m->enter_symbol($1,$1->type_id()());\r
+        $$ = $1;\r
+    }\r
+    | component_value_list T_COMMA component_value {\r
+        asn1::parser *p = asn1::parser::instance();\r
+        asn1::module *m= (asn1::module *) p->module();\r
+        m->enter_symbol($3,$3->type_id()());\r
+        $$ = $1;\r
+    }\r
+;\r
+\r
+component_value:  T_IDENTIFIER value  {\r
+      ASN_LOG_ERROR("component_value Should be Named Not anonymous got value =%s ",$1->name().c_str());\r
+    }\r
+;\r
+\r
+/**\r
+ *\r
+ */\r
+extension_and_exception: \r
+  T_THREEPOINT {\r
+     ASN_LOG_DEBUG("extension_and_exception (...)");\r
+     $<node>$ = new asn1::extension_field();\r
+  }\r
+  | T_THREEPOINT  exception_spec {\r
+     ASN_LOG_WARNING("extension_and_exception (...) and missing exception_spec");\r
+     $<node>$ = new asn1::extension_field();\r
+     $$->meta_id(asn1::meta::TYPE);\r
+     // $$->value($2);\r
+  }\r
+;\r
+\r
+\r
+exception_spec: /* Empty */\r
+  { $$ = NULL; }            \r
+  | T_EXCLAMATION defined_value {\r
+     ASN_LOG_DEBUG("exception_spec: %s",$2->name().c_str());\r
+     $$ = $2;\r
+  }\r
+  | T_EXCLAMATION  type_reference T_COLON value\r
+    {\r
+       ASN_LOG_DEBUG("exception_spec: ! %s : %s",$2->name().c_str(),$4->name().c_str());\r
+       $$ = $2;\r
+    }\r
+  | T_EXCLAMATION pos_neg_identifier {\r
+       ASN_LOG_DEBUG("exception_spec: ! %s",$2->name().c_str());\r
+       $$ = $2;\r
+}\r
+;\r
+\r
+object_set_assignment: \r
+    type_reference parameter_list  defined_object_class T_ASSIGN {\r
+         ASN_LOG_DEBUG("object_set_assignment parameterized start %s",$1->name().c_str());\r
+    }\r
+    object_set\r
+    {\r
+     ASN_LOG_DEBUG("object_set_assignment parameterized end %s",$1->name().c_str());\r
+     $$ = new asn1::objectset_assignment($1->name());\r
+     $$->parameters($2->as_parameters());\r
+     asn1::objectset *objs = new asn1::objectset($6);\r
+     asn1::typeref *typeref = new asn1::typeref($3);\r
+     objs->set_classref(typeref);\r
+     objs->name($1->name());\r
+     objs->identifier($$);\r
+     $$->type_node(objs);\r
+     delete($1);\r
+    }\r
+    |\r
+    type_reference defined_object_class T_ASSIGN {\r
+         ASN_LOG_DEBUG("object_set_assignment start %s",$1->name().c_str());\r
+    }\r
+    object_set\r
+    {\r
+     ASN_LOG_DEBUG("object_set_assignment end %s",$1->name().c_str());\r
+     asn1::typeref *typeref = new asn1::typeref($2);\r
+     $$ = new asn1::objectset_assignment($1->name());\r
+     asn1::objectset *objs = new asn1::objectset($5);\r
+     objs->identifier($$);\r
+     objs->name($1->name());\r
+     objs->set_classref(typeref);\r
+     $$->type_node(objs);\r
+     delete($1);\r
+    }\r
+;\r
+\r
+\r
+/*\r
+ *\r
+ */\r
+object_assignment: \r
+    identifier defined_type T_ASSIGN \r
+    {\r
+      ASN_LOG_DEBUG("\nobject_assignment start 1 object:%s class:%s",$1->name().c_str(),$2->name().c_str());\r
+\r
+      $<module>$ = get_current_module();\r
+      $<module>$->enter_context(new asn1::object());\r
+    }\r
+    object\r
+    {\r
+      asn1::node *res = $<module>4->leave_context();\r
+      $$ = new asn1::object_assignment($1->name());\r
+      res->identifier($$);\r
+      $2->type_node(res);\r
+      $$->type_node($2);\r
+      delete($1);\r
+      ASN_LOG_DEBUG("object_assignment end");\r
+    }\r
+    | identifier T_LBRACET { /*3*/\r
+        ASN_LOG_DEBUG("object_assignment: start %s {params}",$1->cpp_name().c_str());\r
+        asn1::module *m= get_current_module();\r
+        m->enter_context(new asn1::parameters());\r
+        $<module>$ = m;\r
+    } parameter_args T_RBRACET \r
+    { /*6*/\r
+        ASN_LOG_DEBUG("object_assignment: %s",$1->cpp_name().c_str());\r
+        asn1::module *m =  (asn1::module *)$<module>3;\r
+        asn1::node *res = m->leave_context();\r
+    } object_class_reference T_ASSIGN { /*9*/\r
+      ASN_LOG_DEBUG("\nobject_assignment with params start object:%s class:%s"\r
+                     ,$1->name().c_str()\r
+                     ,$7->name().c_str());\r
+      asn1::module *m= get_current_module();\r
+      $<module>$= m;\r
+      m->enter_context(new asn1::object());\r
+    } object {\r
+      ASN_LOG_DEBUG("object_assignment: end %s {params}",$1->cpp_name().c_str());\r
+      $$ = new asn1::object_assignment($1->name());\r
+      asn1::node *res = $<module>9->leave_context();\r
+      res->identifier($$);\r
+      res->meta_id(asn1::meta::OBJECT);\r
+      asn1::typeref *ref = new asn1::typeref($7,asn1::meta::TYPE);\r
+      ref->type_node(res);\r
+      $$->type_node(ref);\r
+      $$->parameters($4->as_parameters());\r
+      delete($1);\r
+    }\r
+;\r
+\r
+object:\r
+    defined_object {\r
+     $$ = $1;\r
+    }\r
+    | object_defn {\r
+     $$ = $1;\r
+    }\r
+;\r
+\r
+\r
+\r
+defined_object:\r
+  T_IDENTIFIER {\r
+  }\r
+;\r
+\r
+object_defn:\r
+  default_syntax {\r
+     ASN_LOG_DEBUG("object_defn: default_syntax");\r
+     $$ = $1;\r
+    }\r
+  | defined_syntax {\r
+     ASN_LOG_DEBUG("object_defn: defined_syntax");\r
+     $$ = $1;\r
+  }\r
+;\r
+\r
+default_syntax: {\r
+    $$ = NULL;\r
+  }\r
+;\r
+\r
+defined_syntax: \r
+  T_LBRACET defined_syntax_list T_RBRACET {\r
+     ASN_LOG_DEBUG("defined_syntax: defined_syntax_list");\r
+    $$ =$2;\r
+  }\r
+;\r
+\r
+defined_syntax_list:\r
+  defined_syntax_token {\r
+    ASN_LOG_DEBUG("defined_syntax_list got item :%s",$1->name().c_str());\r
+    asn1::module *m =  get_current_module ( );\r
+    m->enter_symbol($1,$1->type_id()());\r
+  }\r
+  | defined_syntax_list defined_syntax_token {\r
+    ASN_LOG_DEBUG("defined_syntax_list got item 1");\r
+    asn1::module *m =  get_current_module ( );\r
+    m->enter_symbol($2,$2->type_id()());\r
+  }\r
+;\r
+\r
+defined_syntax_token: \r
+  object_set {\r
+    ASN_LOG_DEBUG("defined_syntax_token object_set:");\r
+    $$= new asn1::objectset($1); \r
+  }\r
+  | value {\r
+    ASN_LOG_DEBUG("defined_syntax_token value:%s type id=%d",$1->name().c_str(),$1->type_id()());\r
+    $$ = $1;\r
+  }\r
+  | type\r
+  {\r
+    $$ = $1;\r
+    if ($$->type_id()() == asn1::type::ASN1_SET_OF\r
+        && $$->identifier()  == NULL)\r
+    {\r
+      $$->identifier(new asn1::node("anonmyous"));\r
+    }\r
+    ASN_LOG_DEBUG("defined_syntax_token type %s",$1->name().c_str());\r
+  }\r
+  | T_OPTIONAL {\r
+    ASN_LOG_DEBUG("defined_syntax_token OPTIONAL");\r
+    $$ = new asn1::node("OPTIONAL",asn1::type::INVALID);\r
+  }\r
+  | T_BY {\r
+    ASN_LOG_DEBUG("defined_syntax_token BY");\r
+    $$ = new asn1::node("BY",asn1::type::INVALID);\r
+  }\r
+  | T_SYNTAX {\r
+    $$ = new asn1::node("SYNTAX",asn1::type::INVALID);\r
+  }\r
+  | type_reference {\r
+    ASN_LOG_DEBUG("defined_syntax_token type_reference %s",$1->name().c_str());\r
+    $$ = $1;\r
+  }\r
+  | T_TYPEREFERENCE T_POINT type_reference {\r
+    /* External reference : Module reference . type_reference */\r
+    asn1::reference *r = $3->as_typeref()->get_reference();\r
+    asn1::module *mod = get_current_module();\r
+    asn1::import *imp = mod->get_import($1->name());\r
+    // If import does not exists, add it to module\r
+    if ( ! imp)\r
+    {\r
+      ASN_LOG_DEBUG( "defined_syntax_token type_reference No import:%s"\r
+                   , $1->name().c_str());\r
+      imp = new asn1::import($1->name());\r
+      imp->identifier($1);\r
+      mod->imports()->append(imp);\r
+    }\r
+    // Simple reference\r
+    asn1::typeref *tref = new asn1::typeref($3->name(), r);\r
+    // If reference not in import add one in import too\r
+    if (! imp->get_item($3->name() ) )\r
+    {\r
+      imp->append(tref->clone());\r
+    }\r
+    $$ = tref;\r
+    delete $3;\r
+  }\r
+;\r
+\r
+/*\r
+ *\r
+ */\r
+\r
+type_constant: \r
+  type_assignment {\r
+    ASN_LOG_DEBUG("type_constant: Got type_assignment ");\r
+    $$ = $1;\r
+  }\r
+  | value_assignment {\r
+    ASN_LOG_DEBUG("type_constant: Got value assignement ");\r
+    $$ = $1;\r
+  }\r
+  | object_assignment {\r
+    ASN_LOG_DEBUG("type_constant: Got object assignement ");\r
+    $$ =$1;\r
+  }\r
+  | object_set_assignment {  \r
+    ASN_LOG_DEBUG("type_constant: object_set_assignment");\r
+    $$ =$1;\r
+  }\r
+  | constant_set_def {\r
+    ASN_LOG_DEBUG("type_constant: constant_set_def");\r
+    $$ = $1;\r
+  } \r
+  | T_ENCODING_CONTROL  T_CAPITALREFERENCE {\r
+    ASN_LOG_DEBUG("type_constant: encoding control start enable ignored for now");\r
+    enable_encoding_control();\r
+  }\r
+  {\r
+    ASN_LOG_DEBUG("type_constant: encoding control ignored for now");\r
+    $$ = NULL;\r
+  }\r
+\r
+    \r
+;\r
+\r
+type_constant_list: type_constant\r
+      {\r
+        asn1::parser *p = asn1::parser::instance();\r
+        $$ = p->module(NULL);\r
+        ASN_LOG_DEBUG("Got type_constant_list: %s type_constant %s"\r
+                     ,$$->name().c_str()\r
+                     ,$1->name().c_str());\r
+        $$->add_type( $1->as_assignment());\r
+      }\r
+      | type_constant_list type_constant\r
+      {\r
+         if ($2 != NULL) {\r
+           ASN_LOG_DEBUG("type_constant_list %s append:%s"\r
+                        , $1->name().c_str()\r
+                        , $2->name().c_str()\r
+                        );\r
+           $$->add_type( $2->as_assignment());\r
+         } else\r
+           ASN_LOG_DEBUG("type_constant_list append NOTHING ");\r
+         $$ =$1;\r
+      }\r
+;\r
+\r
+definitions_id: \r
+    type_reference T_LBRACET {\r
+        // Special case\r
+        if (! gLog.is_open()) \r
+          open_log($1->name());\r
+        ASN_LOG_DEBUG("definitions_id :%s",$1->name().c_str());\r
+        asn1::parser *p = asn1::parser::instance();\r
+        asn1::module *m = NULL;\r
+        if (p->begin() == p->end())\r
+        {\r
+          m=  p->module($1->name().c_str());\r
+        } else\r
+        {\r
+          m=  p->module();\r
+        }\r
+        $<module>$ = m;\r
+    } obj_constant_list T_RBRACET\r
+    {\r
+        ASN_LOG_DEBUG("Go definitions ID %s",static_cast<asn1::node *>($1)->name().c_str());\r
+        asn1::node *ids = $<module>3->leave_context();\r
+        $$ = $1;\r
+        $$->type_node(ids);\r
+    }\r
+    | T_IDENTIFIER T_LBRACET T_RBRACET\r
+    { $$ = $1;}\r
+    | T_TYPEREFERENCE \r
+    { \r
+      // Special case\r
+      if (! gLog.is_open()) \r
+        open_log($1->name());\r
+      ASN_LOG_DEBUG("definitions_id :%s",$1->name().c_str());\r
+      $$ = $1;\r
+     }\r
+    | T_CAPITALREFERENCE \r
+    { \r
+      // Special case\r
+      if (! gLog.is_open()) \r
+        open_log($1->name());\r
+      $$ = $1;\r
+    }\r
+;\r
+\r
+opt_explicit_implicit: {\r
+    $$.m_mode = asn1::node::tag_type::TM_DEFAULT;\r
+  }\r
+  | explicit_implicit {\r
+    $$ = $1;\r
+  }\r
+;\r
+\r
+explicit_implicit: T_EXPLICIT {\r
+    $$.m_mode = asn1::node::tag_type::TM_EXPLICIT;\r
+  }\r
+  | T_IMPLICIT {\r
+    $$.m_mode = asn1::node::tag_type::TM_IMPLICIT;\r
+  }\r
+  | T_AUTOMATIC {\r
+    ASN_LOG_DEBUG("explicit_implicit: TM_AUTOMATIC");\r
+    $$.m_mode = asn1::node::tag_type::TM_AUTOMATIC;\r
+  }\r
+;\r
+\r
+%%\r
+/*\r
+  vim:et:sw=2:ts=2:\r
+*/\r
+\r
diff --git a/libparser/asn1_parser.cpp b/libparser/asn1_parser.cpp
new file mode 100644 (file)
index 0000000..95cf42a
--- /dev/null
@@ -0,0 +1,274 @@
+#include <sstream>
+#include <fstream>
+#include <cstdio>
+#include <stdio.h>
+#include <list>
+#include <algorithm>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if defined(__APPLE__) || defined(HAVE_UNISTD_H) || defined(__GNUC__)
+// for access function I need unistd
+#include <unistd.h>
+#endif
+#if defined (_WIN32)
+#include <io.h>
+#define access _access_s
+#define F_OK 0
+#endif
+
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_constraint.h"
+#include "asn1_reference.h"
+#include "asn1_value.h"
+
+#include "asn1_parser_listener.h"
+#include "asn1_parser.h"
+
+extern int _asn1_parse();
+extern FILE *_asn1_in;
+extern "C" int _asn1_wrap(void);
+extern "C" int _asn1_lineno;
+asn1::parser *
+asn1::parser::m_instance = NULL;
+
+/**
+ * wrap function to handle multiple file parsing other than through stdin
+ */
+int _asn1_wrap()
+{
+    asn1::parser *asn1p = asn1::parser::instance();
+    std::string fullname;
+    // If they are files to parse, return 0, but first,
+    // close the current in, and open the new one
+    if ((asn1p->file_mode() )  && _asn1_in != NULL)
+    {
+       fclose(_asn1_in);
+      _asn1_in = NULL;
+    } else if (!asn1p->file_mode())
+    {
+        return 1;
+    }
+    // Only process files if specified
+    if (asn1p->files().size() > 0)
+    {
+      if (asn1p->includes().size() > 0) {
+        std::list<std::string>::iterator it;
+        for ( it = asn1p->includes().begin()
+            ; it != asn1p->includes().end(); ++it)
+        {
+            fullname = (*it) + asn1p->files().back();
+            if (!access(fullname.c_str(),F_OK))
+            { 
+                break;
+            }
+        }
+      }
+      if (fullname.size() > 0)
+      {
+        _asn1_in = fopen(fullname.c_str(),"r");
+        if (_asn1_in != NULL)
+        {
+           std::cout<<"New File : "<<fullname<<std::endl;
+            asn1p->files().pop_back();
+            return  0;
+        } else {
+            return 1;
+        }
+      } else 
+          return 1;
+    } 
+    return 1;
+}
+
+
+namespace asn1
+{
+
+//
+struct got_constraint
+{
+  got_constraint(asn1::constraint *c) : m_c(c) {};   
+  void operator ()(parser_listener *l)
+  {
+    l->onConstraint(m_c);  
+  }
+  asn1::constraint *m_c;  
+};
+
+//
+struct create_module
+{
+  create_module(asn1::module *m) : m_c(m) {};   
+  void operator ()(parser_listener *l)
+  {
+    l->onModule(m_c);  
+  }
+  asn1::module *m_c;  
+};
+
+
+
+/**
+ *
+ */ 
+asn1::module * 
+parser::module(const char *n ) 
+{
+  iterator it;
+  if (m_modules.size() == 0)
+  {
+    //std::cerr<<"parser::module Create module new 0 :"<<n<<std::endl;
+    m_modules.push_back(new asn1::module(n));
+    
+    std::for_each(m_listeners.begin() 
+                 , m_listeners.end()
+                 ,create_module(m_modules.back()));
+    return m_modules.back();
+  }
+  if (n !=NULL)
+  {
+    // std::cout<<"parser::module("<<n<<") modules size="<<m_modules.size()<<std::endl;
+    it = std::find_if(m_modules.begin(),
+        m_modules.end(),asn1::find_module(std::string(n)));
+    // Return found module
+    if (it != m_modules.end() && ! m_modules.empty())
+    {
+      //std::cerr<<"parser::module Found "<<n<<" module:"<<(*it)->name()<<std::endl;
+      return (*it);
+    } else
+    {
+     
+      //std::cerr<<"parser::module Create new module:"<<n<<std::endl;
+      m_modules.push_back(new asn1::module(n));
+      std::for_each(m_listeners.begin() 
+                 , m_listeners.end()
+                 ,create_module(m_modules.back()));
+    }
+  }
+  return m_modules.back();
+}
+
+
+/**
+ *
+ */ 
+void parser::register_listener(parser_listener *l)
+{
+m_listeners.push_back(l);  
+}
+
+/**
+ *
+ */ 
+void parser::constraint_complet(asn1::constraint *c)
+{
+    std::for_each(m_listeners.begin() 
+                 , m_listeners.end()
+                 , got_constraint(c));
+}
+
+/**
+ * Called for each component in a sequence 
+ *   Get the appropriate module and cast
+ *   the container to sequence. 
+ */ 
+void parser::got_component_type(asn1::node *c)
+{
+  asn1::module *m   =  m_modules.back();
+  asn1::sequence *seq = dynamic_cast<asn1::sequence *>(m->current_context());
+  asn1::set      *set = dynamic_cast<asn1::set *>(m->current_context());
+
+  if (seq && c->get_parent() == NULL)
+  {
+    c->set_parent(seq);  
+  } 
+  if (seq)
+  {
+    seq->add_component(c);
+  } else if (set)
+  {
+    c->set_parent(set);  
+    set->append(c); 
+  } else
+  {
+  }
+}
+/**
+ * Called for each alternative choice
+ */
+void parser::got_alternative_choice(asn1::node *c)
+{
+  asn1::module *m   =  m_modules.back();
+  asn1::choice *s = dynamic_cast<asn1::choice *>(m->current_context());
+
+  if (c->get_parent() == NULL)
+  {
+    c->set_parent(s);  
+  }
+  s->add_alternative(c);
+}
+//
+void 
+parser::got_class_field(asn1::classfield *c)
+{
+  asn1::module *m   =  m_modules.back();
+  asn1::classdef *s = dynamic_cast<asn1::classdef *>(m->current_context());
+
+  if (c->get_parent() == NULL)
+  {
+    c->set_parent(s);  
+  }
+  s->add_field(c);
+}
+
+
+void 
+parser::got_parameter(asn1::parameter *p)
+{
+  asn1::module *m   =  m_modules.back();
+  asn1::parameters *pl  = dynamic_cast<asn1::parameters *>(m->current_context());
+  if (p->get_parent() == NULL)
+  {
+    p->set_parent(pl);  
+  }
+  pl->add_parameter(p);
+}
+
+void 
+parser::got_act_parameter(asn1::node *c)
+{
+  asn1::module *m           =  m_modules.back();
+  asn1::act_parameters *pl  = dynamic_cast<asn1::act_parameters *>(m->current_context());
+  if (c->get_parent() == NULL)
+  {
+    c->set_parent(pl);  
+  }
+  pl->add_parameter(c);
+}
+
+int 
+parser::parse()
+{
+  if ( file_mode() )
+  {
+    _asn1_in = NULL;
+    if (   !_asn1_wrap() )
+    {
+      _asn1_parse();
+      return 0;
+    } else
+    {
+      return 1;
+    }   
+  } else if (! file_mode())
+  {
+    _asn1_parse();
+    return 0;
+  }
+  {
+    return 1;
+  }
+}
+
+}
diff --git a/libparser/asn1_parser.h b/libparser/asn1_parser.h
new file mode 100644 (file)
index 0000000..0e418fc
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef ASN1_PARSER_H__
+#define ASN1_PARSER_H__
+
+#include "asn1_node.h"
+#include "asn1_module.h"
+#include "asn1_parser_listener.h"
+
+namespace asn1 {
+
+class asn1_parser_listener;
+
+class parser
+{
+  public:
+    typedef std::vector<asn1::module *> modules_type;
+    typedef std::vector<asn1::module *>::iterator iterator;
+
+    typedef std::list<asn1::parser_listener *> listener_list;
+    
+    typedef std::list<std::string>        string_list;
+
+    static parser *instance()
+    {
+      if (m_instance == NULL) 
+      {
+        m_instance = new parser();
+      } 
+      return m_instance;
+    }
+
+    inline iterator begin() {return m_modules.begin();}
+    inline iterator end() {return m_modules.end();}
+
+    asn1::module * module(const char *n = NULL); 
+
+    modules_type &modules() { return m_modules;};
+
+    /**
+     *
+     */
+    void register_listener(parser_listener *l);
+    
+    /**
+     * Entry point to notify listeners that a constraint definition
+     * has occured.
+     */
+    void constraint_complet(asn1::constraint *c);
+
+    /**
+     * Called for each component in a sequence 
+     */ 
+    void got_component_type(asn1::node *c);
+    /**
+     * Called for each alternative choice
+     */
+    void got_alternative_choice(asn1::node *c);
+    /**
+     * Called for each alternative choice
+     */
+    void got_class_field(asn1::classfield *c);
+
+    void got_parameter(asn1::parameter *p);
+
+    void got_act_parameter(asn1::node *n);
+
+    int parse();
+
+    inline bool debug_console() const
+    { return m_debug_console ; }
+
+    inline void debug_console(bool b)
+    { m_debug_console = true; }
+    inline string_list &includes()  { return m_includes; }
+    inline string_list &files()     { return m_files;    }
+    inline bool         file_mode() { return m_file_mode;}
+    inline void set_file_mode(bool fm)
+    { m_file_mode = fm;}    
+  private:
+    parser() 
+      : m_file_mode(false) , m_root(NULL)
+    {};
+    parser(const parser &p)
+    {};
+    parser &operator =(const parser &p) { return *this;};
+
+
+  private:
+    modules_type    m_modules;
+    static parser  *m_instance;
+
+  protected:
+   bool             m_debug_console;
+   node            *m_root; 
+   listener_list    m_listeners;
+   string_list      m_includes;
+   string_list      m_files;
+   bool             m_file_mode;
+};
+
+//parser::m_instance = NULL;
+}
+
+/*
+ * vim:et:sw=2:ts=2
+ */
+
+#endif
diff --git a/libparser/asn1_parser_listener.h b/libparser/asn1_parser_listener.h
new file mode 100644 (file)
index 0000000..27587d7
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef ASN1_PARSER_LISTENER_H
+#define ASN1_PARSER_LISTENER_H
+
+namespace asn1
+{
+
+/**
+ * @brief This class is an interface that is used by the parser. It allows an application
+ * to listen to some events from the parser.
+ *  Example:  a contraints has been parsed
+ *            a typedefinition is completed
+ *            a component of a set or sequence has been parser.
+ */ 
+class parser_listener 
+{
+  public:  
+    parser_listener () {};
+
+    // Constraint
+    virtual void onConstraint(asn1::constraint *c) {};    
+    
+    virtual void onModule(asn1::module *m) {};    
+  protected:  
+};
+
+}
+#endif /*ASN1_PARSER_LISTENER_H*/
diff --git a/main.cpp b/main.cpp
new file mode 100644 (file)
index 0000000..2746367
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,375 @@
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <map>
+#include <list>
+
+// For open / close
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "asn1_generator.h"
+#include "asn1_gen_cpp.h"
+#include "asn1_gen_hpp.h"
+#include "js/asn1_gen_js.h"
+#include "uml/asn1_gen_uml.h"
+#include "lds/asn1_gen_lds.h"
+#include "asn1_gen_codec_cpp.h"
+#include "asn1_gen_auto_tag.h"
+#include "asn1_gen_optimizer.h"
+#include "libparser/asn1_parser.h"
+#include "asn1_gen_constraints.h"
+
+#include "optionparser.h"
+
+/**
+ * Global Variables for the parser / lexer
+ */
+
+
+enum optionIndex {
+  UNKNOWN, HELP
+  ,UML,ERULE
+  ,FICHIER,OUTPUT,INCLUDE
+  ,PLANG,COMMENT,CODEC,OPTSPLIT,OPTDBG,OPT_END};
+/*----------------------------------------------------------------------------*/
+const option::Descriptor usage[] = {
+ {UNKNOWN,      0, "", "", option::Arg::None,"Welcome to asn1p compiler (c) aeb"
+                   " 2016-2018 " BUILD_TYPE " " BUILD_VERSION "\n"
+                   "Usage asn1p [options]\n\texample:"
+                   " asn1p -e ber -f toto.asn1 -I[path]\n"},
+ {HELP,         0, "h",  "help",option::Arg::None,"--help,-h \tPrint help and quit."},
+ {UML,          0, "u", "uml",  option::Arg::Optional,"--uml,-u \tGenerate UML model of asn1 model."},
+ {ERULE,        0, "e", "ecoding_rule",  option::Arg::Required,"--encoding_rule ,-e \t Encoding rules to use"
+                   " accepted ER: ber,per,oer,jer,xer "},
+ {FICHIER,      0, "f", "file", option::Arg::Required,"--file,-f \tAsn1 input file to parse"},
+ {OUTPUT,       0, "o", "ouput", option::Arg::Required,"--output,-o \toutput file without extension to be generated"},
+ {INCLUDE,      0, "I", "include",     option::Arg::Required,"--include,-I\tInclude path to look for other asn1 files."},
+ {PLANG,        0, "l", "language",     option::Arg::Required,"--language,-l\t"
+                   "Programming language cpp, uml, javascript, lds, sql [default: cpp]"},
+ {COMMENT,      0, "n", "comment",     option::Arg::Required,"--comment,-n\t"
+                "(true or ON)/(false or OFF) generate comment in source def true"},
+ {CODEC,        0, "c", "codec",     option::Arg::Required,"--codec,-c\tCodecs"
+                   " functions ON or OFF [default: OFF]"
+ },
+ {OPTSPLIT,     0, "s", "split",     option::Arg::None,"--split,-s\t"
+                   " put codec code in separated cpp files. Needed for huge definitions"
+ },
+ {OPTDBG,       0, "d", "debug",     option::Arg::Required,"--debug,-d\tconsole=1 "
+                   " msg=1 debug messages in code parser=<1-8> parser debug traces"},
+ {0,0,0,0,0,0}
+};
+
+struct language_config
+{
+  language_config()
+   : m_cpp(true) 
+           , m_uml(true)
+           , m_javascript(false)
+           , m_lds(false)
+           , m_java(false)
+           , m_csharp(true)
+           , m_sql(true) 
+           , m_c(false) 
+  {}; 
+#define WITH_PLANG(nm) \
+  bool with_##nm() { return m_##nm; } ; \
+  void with_##nm(bool b) { m_##nm = b ; } ;
+  WITH_PLANG(cpp)
+  WITH_PLANG(javascript)
+  WITH_PLANG(lds)
+  WITH_PLANG(java)
+  WITH_PLANG(csharp)
+  WITH_PLANG(sql)
+  WITH_PLANG(c)
+  WITH_PLANG(uml)
+#undef WITH_PLANG  
+  // generator configuration flags
+  bool    m_cpp;
+  bool    m_uml;
+  bool    m_javascript;
+  bool    m_lds;
+  bool    m_java;
+  bool    m_csharp;
+  bool    m_sql;
+  bool    m_c;
+};
+
+
+/**
+ * Main entry point
+ */
+int main(int argc,char **argv)
+{
+    std::map<std::string,std::string> module_map;
+    std::string umlname;
+    asn1::parser::iterator it;
+    asn1::parser *p = asn1::parser::instance();
+    asn1::generator_config g_config;
+    language_config        l_config;
+    gen_constraints        constraints;
+    // Option stuff must go here
+    option::Stats   stats(usage,argc-1,&argv[1]);
+    //const int            max(stats.options_max);
+    option::Option  options[OPT_END*3],buffer[OPT_END*4];
+    option::Parser  parser(usage,argc-1,&argv[1],options,buffer);
+
+    p->register_listener(&constraints);
+    if (parser.error()) {
+        return 1;
+    }
+    if (options[HELP] )
+    {
+        option::printUsage(std::cout,usage);
+        return 1;
+    }
+    if (options[INCLUDE])
+    {
+        for ( option::Option *opts = options[INCLUDE] 
+            ; opts; opts = opts->next())
+        {
+            if (opts->arg)
+                p->includes().push_back(std::string(opts->arg));
+        }
+    }
+    if (options[OPTSPLIT])
+    {
+          g_config.with_split_cpp(true);  
+    }
+    /**
+     * Codecs included in structures
+     */ 
+    if (options[CODEC])
+    {
+      for (option::Option *opts = options[CODEC] ;opts; opts = opts->next())
+      {
+        while (* opts->arg == ' ') opts->arg++;
+        if (opts->arg && 
+            (! strcmp(opts->arg,"false") || !strcmp(opts->arg,"OFF")))
+        {
+          g_config.with_codec(false);  
+        } else if (opts->arg && 
+            (! strcmp(opts->arg,"true") || !strcmp(opts->arg,"ON")))
+        {
+          g_config.with_codec(true);  
+        } else
+             {
+              std::cerr<<"Wrong argument for CODEC"<<std::endl;
+             }
+      }
+    }
+    /**
+     * Codecs included in structures
+     */ 
+    if (options[PLANG])
+    {
+      for (option::Option *opts = options[PLANG] ;opts; opts = opts->next())
+      {
+        while (* opts->arg == ' ') opts->arg++;
+        if (opts->arg && ! strcmp(opts->arg,"uml"))
+        { l_config.with_uml(true); continue; }
+
+        if (opts->arg && ! strcmp(opts->arg,"cpp"))
+        { l_config.with_cpp(true);  continue; }
+        
+        if (opts->arg && ! strcmp(opts->arg,"javascript"))
+        { l_config.with_javascript(true);  continue; }
+        
+        if (opts->arg && ! strcmp(opts->arg,"lds"))
+        { l_config.with_lds(true);  continue; }
+        
+
+        std::cerr<<"Unsuported language. "<<opts->arg<<std::endl;
+        exit(1);
+      }
+    }
+    /**
+     * Encoding rules to be implemented in structures
+     */ 
+    if (options[ERULE])
+    {
+      for (option::Option *opts = options[ERULE] ;opts; opts = opts->next())
+      {
+        /* remove spaces */
+        while (* opts->arg == ' ') opts->arg++;
+        if (opts->arg && ! strcmp(opts->arg,"ber"))
+        { g_config.with_ber(true); continue; }
+
+        if (opts->arg && ! strcmp(opts->arg,"jer"))
+        { g_config.with_jer(true);  continue; }
+        
+        if (opts->arg && ! strcmp(opts->arg,"oer"))
+        { g_config.with_oer(true);  continue; }
+        
+        if (opts->arg && ! strcmp(opts->arg,"per"))
+        { g_config.with_per(true);  continue; }
+        
+        if (opts->arg && ! strcmp(opts->arg,"xer"))
+        { g_config.with_xer(true);  continue; }
+        
+
+        std::cerr<<"Unsuported encoding rule. <"<<opts->arg<<">"<<std::endl;
+        exit(1);
+      }
+    }
+    if (options[OPTDBG])
+    {
+      for (option::Option *opts = options[OPTDBG] ;opts; opts = opts->next())
+      {
+        if (opts->arg && ! strcmp(opts->arg,"msg=1"))
+        { g_config.with_source_debug(true); continue; }
+
+        
+        if (opts->arg && ! strcmp(opts->arg,"console=1"))
+        { std::cout<<"TODO"<<std::endl;  continue; }
+        
+        if (opts->arg && ! strncmp(opts->arg,"parser=",7))
+        { std::cout<<"TODO parser debug level";  continue; }
+        
+        std::cerr<<"Unsuported option "<<opts->arg<<std::endl;
+        exit(1);
+      }
+    }
+    if (options[COMMENT])
+    {
+      for ( option::Option *opts = options[COMMENT]
+          ; opts; opts = opts->next())
+      {
+        if (opts->arg && (
+            (! strcmp(opts->arg,"false") ||!strcmp(opts->arg,"OFF")) ))
+        {
+          g_config.with_source_comment(false);  
+        }
+      }
+    }
+    
+    if (options[FICHIER] )
+    {
+      for ( option::Option *opts = options[FICHIER] 
+          ; opts; opts = opts->next())
+      {
+        if (opts->arg)
+          p->files().push_back(std::string(opts->arg));
+      }
+      p->set_file_mode(true);
+      std::cout<<"Main: start with wrap feature"<<std::endl;
+      if (p->parse())
+      {
+        std::cout<<"Main: start with wrap failed "<<std::endl;
+      }
+    } else
+    {
+      // Parsing of stdin this might change in the future
+      //_asn1_parse();
+      p->parse();
+    }
+    
+    if (options[UML] && options[UML].arg != NULL) {
+      umlname = std::string(options[UML].arg);
+      std::cout<<"Will generate : "<<umlname<<std::endl;
+    } else
+      umlname = std::string("_model.uml");
+    
+    // Launch optimization on all modules
+    // before any generation....
+    //  Does not work for cstav1 2017-05-02
+
+    // Launch generation
+    //
+    for ( it = p->begin(); it != p->end(); it++ )
+    {
+      std::fstream os;
+      std::fstream osauto;
+      std::string fname = (*it)->cpp_name() + std::string(".h");
+      std::string fcname = (*it)->name() + std::string(".cpp");
+      std::string jsname = (*it)->name() + std::string(".js");
+      std::string autoname = (*it)->name() + std::string(".auto");
+      asn1::gen_auto_tag gen_auto((*it),p->modules());
+
+      // If OUTPUT option is set, only generate the specified module
+      if (options[OUTPUT] && (options[OUTPUT].arg != NULL ))
+      {
+        bool found = false;  
+        for ( option::Option *opts = options[OUTPUT]
+            ; opts; opts = opts->next())
+        {
+          if (! (*it)->name().compare(opts->arg))
+          {
+            found = true;
+            break;  
+          }
+        }
+        if (!found )
+                continue;
+      }
+      // Launch optimization
+      asn1::gen_optimizer ogen((*it),p->modules());
+      ogen.set_config(g_config);
+      ogen.gen(std::cout,".optimize" );
+      // Do automatic tagging
+      osauto.open(autoname.c_str(),std::fstream::out);
+      gen_auto.gen(osauto,".auto");
+      osauto.close();
+      //
+      if (l_config.with_javascript())  
+      {
+        os.open(jsname.c_str(),std::fstream::out);
+        std::cout<<"\n*\n*Process javascript generation for Definition :";
+        std::cout<<(*it)->name()<<"\n*"<<std::endl;
+        generate_js gen((*it),p->modules());
+        // Generate automatic tag.
+        // This class goes through the module for automatic tagging
+        gen.gen(os,".js");
+        os.close();
+          
+      } else if (options[UML] )
+      {
+        std::fstream umlos;
+        std::cout<<"\n*\n*Process uml generation for Definition :";
+        std::cout<<(*it)->name()<<"\n*"<<std::endl;
+        umlos.open(umlname.c_str(),std::fstream::out);
+        generate_uml gen_uml((*it),p->modules());
+        gen_uml.gen(umlos,".uml");
+        umlos.close();
+      } else 
+      {
+        os.open(fname.c_str(),std::fstream::out);
+        std::cout<<"\n*\n*Process cpp generation for Definition :";
+        std::cout<<(*it)->name()<<"\n*"<<std::endl;
+        // Lets go and generate headers
+        generate_header gen((*it),p->modules());
+        gen.set_config(g_config);
+        gen.gen(os,".hpp");
+        os.close();
+        
+        // Reset generated flag
+        asn1::node::iterator nit = (*it)->begin();
+        for (; nit != (*it)->end() ; nit++) 
+        {
+          (*nit)->set_generated(false);
+        }
+        // Generate codec cod
+        os.open(fcname.c_str(),std::fstream::out);
+        generate_codec_cpp genc((*it),p->modules(),constraints);
+        genc.set_config(g_config);
+        genc.gen(os,".cpp");
+        os.close();
+      }
+      if (l_config.with_lds())
+      {
+        std::string ldsname = (*it)->name() + std::string(".lds");
+        os.open(ldsname.c_str(),std::fstream::out);
+        generate_lds genlds((*it),p->modules());
+        std::cout<<"\n*\n*Process lds generation for Definition :";
+        std::cout<<(*it)->name()<<"\n*"<<std::endl;
+        genlds.gen(os,".lds");
+        os.close();
+      }
+    }
+    std::cout<<"Bye "<<argv[0]<<std::endl;
+}
+
+/*
+ * vim: et sw=2 ts=2 :
+ */ 
diff --git a/megaco/CMakeLists.txt b/megaco/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f824326
--- /dev/null
@@ -0,0 +1,129 @@
+PROJECT(megaco)
+
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${rules_SOURCE_DIR}/")
+
+SET(MEGACO_ERULE -e jer -e ber -c ON)
+FIND_PACKAGE(PCAP REQUIRED)
+INCLUDE_DIRECTORIES(${PCAP_INCLUDE_DIRS})
+
+FIND_PACKAGE(Sqlite3)
+FIND_PACKAGE(Fcgi)
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt MEGACOMODULES)
+
+FOREACH(ITEM ${MEGACOMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}_codec.cpp GENERATED)
+ SET(MEGACOSRC ${MEGACOSRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(MEGACOSRC ${MEGACOSRC} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}_codec.cpp)
+ SET(MEGACOHDR ${MEGACOHDR} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp"
+    )
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}_codec.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h"
+    )
+
+ENDFOREACH(ITEM)
+
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h 
+      ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp 
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS -I ${asn1-data-models_SOURCE_DIR}/cstav1/
+         -f Remote-Operations-Information-Objects.asn1
+         -o Remote-Operations-Information-Objects
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build ROIO .h and .cpp"
+    )
+      
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote_Operations_Information_Objects.h
+    GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp
+    GENERATED)
+
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.h ${CMAKE_CURRENT_BINARY_DIR}/Remote-Operations-Information-Objects.cpp"
+    )
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${MEGACOSRC}
+      ${MEGACOHDR}
+    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    ARGS ${MEGACO_ERULE} -I ${asn1-data-models_SOURCE_DIR}/
+         -f rfc3525-MEDIA-GATEWAY-CONTROL.asn1
+         -o MEDIA-GATEWAY-CONTROL
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build MEDIA-GATEWAY-CONTROL .h and .cpp"
+    )
+
+
+
+ADD_LIBRARY(megaco
+      ${MEGACOSRC}
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/main.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+ADD_EXECUTABLE(test_megaco
+    main.cpp
+    )
+
+TARGET_LINK_LIBRARIES(test_megaco megaco asn1)
+
+
+
+
+#
+# Install stuff
+#
+INSTALL(TARGETS test_megaco megaco
+        RUNTIME DESTINATION bin
+        LIBRARY DESTINATION lib
+        ARCHIVE DESTINATION lib
+        COMPONENT           megaco
+        )
+
+#
+# Ok start working with Packaging stuff
+#
+INCLUDE(InstallRequiredSystemLibraries)
+
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Graphical user interface to visualize
+csta phase 2 and sip messages from pcap files")
+SET(CPACK_PACKAGE_VENDOR "Aeb")
+#SET(CPACK_PACKAGE_DESCRIPTION_FILE "")
+#SET(CPACK_RESOURCE_FILE_LICENSE "")
+SET(CPACK_PACKAGE_VERSION_MAJOR "1")
+SET(CPACK_PACKAGE_VERSION_MINOR "0")
+SET(CPACK_PACKAGE_VERSION_PATCH "0")
+
+SET(CPACK_PACKAGE_FILE_NAME "CstaSpyInstaller")
+SET(CPACK_PACKAGE_NAME "CstaSpy")
+
+IF(WIN32)
+  SET(CPACK_GENERATOR "NSIS")
+ENDIF()
+
+IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux" )
+  SET(CPACK_GENERATOR "RPM")
+ENDIF()
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy")
+#SET(CPACK_PACKAGE_EXECUTABLES "cstaspy" "CSTA Spy")
+INCLUDE(CPack)
diff --git a/megaco/main.cpp b/megaco/main.cpp
new file mode 100644 (file)
index 0000000..12722ab
--- /dev/null
@@ -0,0 +1,100 @@
+#include <iostream>
+#include <fstream>
+#include <string.h>
+#include <typeinfo>
+#include <stdlib.h>
+#include "rtasn1/asn1_config.h"
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "rtasn1/asn1_codec_jer.h"
+
+#include "MEDIA_GATEWAY_CONTROL.h"
+#include "MEDIA_GATEWAY_CONTROL_codec.hpp"
+
+using namespace MEDIA_GATEWAY_CONTROL;
+
+void test_message() {
+    asn1::streams::ber ctx;
+    asn1::streams::jer ctx_jer;
+    IP4Address ip4;
+    Message m,mjer;
+    m.version = 2;
+    ip4.address     = std::string("0345");
+    ip4.portNumber.get()  =  1045;
+    Transaction  trans;
+    CommandRequest cr;
+    ActionRequest ar;
+    TerminationID tid;
+    WildcardField wf; wf = std::string("*");
+    ar.contextId = 0xFFFFFFFF;
+    tid.id = std::string("100");
+    cr.command.get_addReq().terminationID.push_back(tid);
+    tid.id = std::string("101");
+    tid.wildcard.push_back(wf);
+    tid.wildcard.push_back(wf);
+    cr.command.get_addReq().terminationID.push_back(tid);
+    ar.commandRequests.push_back(cr);
+    //m.mId.ip4Address =  ip4;
+    //m.mId.kind_         = MId::typeof_ip4Address;
+    //m.mId.set_tag(asn1::tag(asn1::types::CONTEXT_SPECIFIC,MId::typeof_ip4Address));
+    //m.mId.set_tag(asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+    m.mId.set_ip4Address (  ip4 );
+    trans.get_transactionRequest().transactionId = 5;
+    trans.get_transactionRequest().actions.push_back(ar);
+    m.messageBody.get_transactions().push_back(trans);
+    //m.messageBody.get_transactions().push_back(trans);
+#if 0
+    // This should be possible as well;
+    mIP4Address &ip4 = m.mId.get_ip4Addres();
+    ip4.address     = std::string("0345");
+    ip4.portNumber.get()  = 1045;
+#endif
+    std::cout<<"Message:\n"<<m<<"\nmId should be:\n "<<ip4<<"\n"<<std::endl;
+    m.encode(ctx);
+    std::cout<<"encoded\n"<<m<<"\nmId encode JER:\n "<<std::endl;
+    asn1::codecJER cb;
+    cb.encode(ctx_jer,m);
+    std::cout<<"JER:<"<<ctx_jer<<">"<<std::endl;
+    asn1::streams::jer cddec(ctx_jer.buffer(),512);
+    if ( cb.decode(cddec,mjer) != asn1::ok)
+    {
+      std::cout<<"JER: Failed decode"<<std::endl;
+    } else
+    {
+      std::cout<<"Decode JER:\n"<<mjer<<"\n"<<std::endl;
+    }
+
+}
+
+void message(const char *program)
+{
+  printf("%s [OPTIONS]\n",program);
+  printf("\t-d\tdebug level [0-7]\n");
+}
+
+int main(int argc,char **argv)
+{
+#ifdef HAVE_UNISTD_H
+  char ch;
+  while ( (ch  = getopt(argc,argv,"d:h")) != -1)
+  {
+    switch (ch)
+    {
+      case 'd':
+      {
+        asn1::types::debug_level = atoi(optarg);
+      }
+      break;
+      case 'h':
+      case '?':
+      default:
+        message(argv[0]);
+
+    }
+  }
+#endif
+  test_message();
+}
+
diff --git a/megaco/modules.txt b/megaco/modules.txt
new file mode 100644 (file)
index 0000000..7be8352
--- /dev/null
@@ -0,0 +1 @@
+MEDIA-GATEWAY-CONTROL
diff --git a/optionparser.h b/optionparser.h
new file mode 100755 (executable)
index 0000000..fab5d9b
--- /dev/null
@@ -0,0 +1,2829 @@
+/*
+ * The Lean Mean C++ Option Parser
+ *
+ * Copyright (C) 2012 Matthias S. Benkmann
+ *
+ * The "Software" in the following 2 paragraphs refers to this file containing
+ * the code to The Lean Mean C++ Option Parser.
+ * The "Software" does NOT refer to any other files which you
+ * may have received alongside this file (e.g. as part of a larger project that
+ * incorporates The Lean Mean C++ Option Parser).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software, to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * NOTE: It is recommended that you read the processed HTML doxygen documentation
+ * rather than this source. If you don't know doxygen, it's like javadoc for C++.
+ * If you don't want to install doxygen you can find a copy of the processed
+ * documentation at
+ *
+ * http://optionparser.sourceforge.net/
+ *
+ */
+
+/**
+ * @file
+ *
+ * @brief This is the only file required to use The Lean Mean C++ Option Parser.
+ *        Just \#include it and you're set.
+ *
+ * The Lean Mean C++ Option Parser handles the program's command line arguments 
+ * (argc, argv).
+ * It supports the short and long option formats of getopt(), getopt_long() 
+ * and getopt_long_only() but has a more convenient interface.
+ * The following features set it apart from other option parsers:
+ *
+ * @par Highlights:
+ * <ul style="padding-left:1em;margin-left:0">
+ * <li> It is a header-only library. Just <code>\#include "optionparser.h"</code> and you're set.
+ * <li> It is freestanding. There are no dependencies whatsoever, not even the
+ *      C or C++ standard library.
+ * <li> It has a usage message formatter that supports column alignment and
+ *      line wrapping. This aids localization because it adapts to
+ *      translated strings that are shorter or longer (even if they contain
+ *      Asian wide characters).
+ * <li> Unlike getopt() and derivatives it doesn't force you to loop through
+ *     options sequentially. Instead you can access options directly like this:
+ *     <ul style="margin-top:.5em">
+ *     <li> Test for presence of a switch in the argument vector:
+ *      @code if ( options[QUIET] ) ... @endcode
+ *     <li> Evaluate --enable-foo/--disable-foo pair where the last one used wins:
+ *     @code if ( options[FOO].last()->type() == DISABLE ) ... @endcode
+ *     <li> Cumulative option (-v verbose, -vv more verbose, -vvv even more verbose):
+ *     @code int verbosity = options[VERBOSE].count(); @endcode
+ *     <li> Iterate over all --file=&lt;fname> arguments:
+ *     @code for (Option* opt = options[FILE]; opt; opt = opt->next())
+ *   fname = opt->arg; ... @endcode
+ *     <li> If you really want to, you can still process all arguments in order:
+ *     @code
+ *   for (int i = 0; i < p.optionsCount(); ++i) {
+ *     Option& opt = buffer[i];
+ *     switch(opt.index()) {
+ *       case HELP:    ...
+ *       case VERBOSE: ...
+ *       case FILE:    fname = opt.arg; ...
+ *       case UNKNOWN: ...
+ *     @endcode
+ *     </ul>
+ * </ul> @n
+ * Despite these features the code size remains tiny. 
+ * It is smaller than <a href="http://uclibc.org">uClibc</a>'s GNU getopt() and just a
+ * couple 100 bytes larger than uClibc's SUSv3 getopt(). @n
+ * (This does not include the usage formatter, of course. But you don't have to use that.)
+ *
+ * @par Download:
+ * Tarball with examples and test programs:
+ * <a style="font-size:larger;font-weight:bold" href="http://sourceforge.net/projects/optionparser/files/optionparser-1.3.tar.gz/download">optionparser-1.3.tar.gz</a> @n
+ * Just the header (this is all you really need):
+ * <a style="font-size:larger;font-weight:bold" href="http://optionparser.sourceforge.net/optionparser.h">optionparser.h</a>
+ *
+ * @par Changelog:
+ * <b>Version 1.3:</b> Compatible with Microsoft Visual C++. @n
+ * <b>Version 1.2:</b> Added @ref option::Option::namelen "Option::namelen" and removed the extraction
+ *                     of short option characters into a special buffer. @n
+ *                     Changed @ref option::Arg::Optional "Arg::Optional" to accept arguments if they are attached
+ *                     rather than separate. This is what GNU getopt() does and how POSIX recommends
+ *                     utilities should interpret their arguments.@n
+ * <b>Version 1.1:</b> Optional mode with argument reordering as done by GNU getopt(), so that
+ *                     options and non-options can be mixed. See
+ *                     @ref option::Parser::parse() "Parser::parse()".
+ *
+ * @par Feedback:
+ * Send questions, bug reports, feature requests etc. to: <tt><b>optionparser-feedback<span id="antispam">&nbsp;(a)&nbsp;</span>lists.sourceforge.net</b></tt>
+ * @htmlonly <script type="text/javascript">document.getElementById("antispam").innerHTML="@"</script> @endhtmlonly
+ *
+ *
+ * @par Example program:
+ * (Note: @c option::* identifiers are links that take you to their documentation.)
+ * @code
+ * #include <iostream>
+ * #include "optionparser.h"
+ *
+ * enum  optionIndex { UNKNOWN, HELP, PLUS };
+ * const option::Descriptor usage[] =
+ * {
+ *  {UNKNOWN, 0,"" , ""    ,option::Arg::None, "USAGE: example [options]\n\n"
+ *                                             "Options:" },
+ *  {HELP,    0,"" , "help",option::Arg::None, "  --help  \tPrint usage and exit." },
+ *  {PLUS,    0,"p", "plus",option::Arg::None, "  --plus, -p  \tIncrement count." },
+ *  {UNKNOWN, 0,"" ,  ""   ,option::Arg::None, "\nExamples:\n"
+ *                                             "  example --unknown -- --this_is_no_option\n"
+ *                                             "  example -unk --plus -ppp file1 file2\n" },
+ *  {0,0,0,0,0,0}
+ * };
+ *
+ * int main(int argc, char* argv[])
+ * {
+ *   argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
+ *   option::Stats  stats(usage, argc, argv);
+ *   option::Option options[stats.options_max], buffer[stats.buffer_max];
+ *   option::Parser parse(usage, argc, argv, options, buffer);
+ *
+ *   if (parse.error())
+ *     return 1;
+ *
+ *   if (options[HELP] || argc == 0) {
+ *     option::printUsage(std::cout, usage);
+ *     return 0;
+ *   }
+ *
+ *   std::cout << "--plus count: " <<
+ *     options[PLUS].count() << "\n";
+ *
+ *   for (option::Option* opt = options[UNKNOWN]; opt; opt = opt->next())
+ *     std::cout << "Unknown option: " << opt->name << "\n";
+ *
+ *   for (int i = 0; i < parse.nonOptionsCount(); ++i)
+ *     std::cout << "Non-option #" << i << ": " << parse.nonOption(i) << "\n";
+ * }
+ * @endcode
+ *
+ * @par Option syntax:
+ * @li The Lean Mean C++ Option Parser follows POSIX <code>getopt()</code> conventions and supports
+ *     GNU-style <code>getopt_long()</code> long options as well as Perl-style single-minus
+ *     long options (<code>getopt_long_only()</code>).
+ * @li short options have the format @c -X where @c X is any character that fits in a char.
+ * @li short options can be grouped, i.e. <code>-X -Y</code> is equivalent to @c -XY.
+ * @li a short option may take an argument either separate (<code>-X foo</code>) or
+ *     attached (@c -Xfoo). You can make the parser accept the additional format @c -X=foo by
+ *     registering @c X as a long option (in addition to being a short option) and
+ *     enabling single-minus long options.
+ * @li an argument-taking short option may be grouped if it is the last in the group, e.g.
+ *     @c -ABCXfoo or <code> -ABCX foo </code> (@c foo is the argument to the @c -X option).
+ * @li a lone minus character @c '-' is not treated as an option. It is customarily used where
+ *     a file name is expected to refer to stdin or stdout.
+ * @li long options have the format @c --option-name.
+ * @li the option-name of a long option can be anything and include any characters.
+ *     Even @c = characters will work, but don't do that.
+ * @li [optional] long options may be abbreviated as long as the abbreviation is unambiguous.
+ *     You can set a minimum length for abbreviations.
+ * @li [optional] long options may begin with a single minus. The double minus form is always
+ *     accepted, too.
+ * @li a long option may take an argument either separate (<code> --option arg </code>) or
+ *     attached (<code> --option=arg </code>). In the attached form the equals sign is mandatory.
+ * @li an empty string can be passed as an attached long option argument: <code> --option-name= </code>.
+ *     Note the distinction between an empty string as argument and no argument at all.
+ * @li an empty string is permitted as separate argument to both long and short options.
+ * @li Arguments to both short and long options may start with a @c '-' character. E.g.
+ *     <code> -X-X </code>, <code>-X -X</code> or <code> --long-X=-X </code>. If @c -X
+ *     and @c --long-X take an argument, that argument will be @c "-X" in all 3 cases.
+ * @li If using the built-in @ref option::Arg::Optional "Arg::Optional", optional arguments must
+ *     be attached.
+ * @li the special option @c -- (i.e. without a name) terminates the list of
+ *     options. Everything that follows is a non-option argument, even if it starts with
+ *     a @c '-' character. The @c -- itself will not appear in the parse results.
+ * @li the first argument that doesn't start with @c '-' or @c '--' and does not belong to
+ *     a preceding argument-taking option, will terminate the option list and is the
+ *     first non-option argument. All following command line arguments are treated as
+ *     non-option arguments, even if they start with @c '-' . @n
+ *     NOTE: This behaviour is mandated by POSIX, but GNU getopt() only honours this if it is
+ *     explicitly requested (e.g. by setting POSIXLY_CORRECT). @n
+ *     You can enable the GNU behaviour by passing @c true as first argument to
+ *     e.g. @ref option::Parser::parse() "Parser::parse()".
+ * @li Arguments that look like options (i.e. @c '-' followed by at least 1 character) but
+ *     aren't, are NOT treated as non-option arguments. They are treated as unknown options and
+ *     are collected into a list of unknown options for error reporting. @n
+ *     This means that in order to pass a first non-option
+ *     argument beginning with the minus character it is required to use the
+ *     @c -- special option, e.g.
+ *     @code
+ *     program -x -- --strange-filename
+ *     @endcode
+ *     In this example, @c --strange-filename is a non-option argument. If the @c --
+ *     were omitted, it would be treated as an unknown option. @n
+ *     See @ref option::Descriptor::longopt for information on how to collect unknown options.
+ *
+ */
+
+#ifndef OPTIONPARSER_H_
+#define OPTIONPARSER_H_
+
+/** @brief The namespace of The Lean Mean C++ Option Parser. */
+namespace option
+{
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#pragma intrinsic(_BitScanReverse)
+struct MSC_Builtin_CLZ
+{
+  static int builtin_clz(unsigned x)
+  {
+    unsigned long index;
+    _BitScanReverse(&index, x);
+    return 32-index; // int is always 32bit on Windows, even for target x64
+  }
+};
+#define __builtin_clz(x) MSC_Builtin_CLZ::builtin_clz(x)
+#endif
+
+class Option;
+
+/**
+ * @brief Possible results when checking if an argument is valid for a certain option.
+ *
+ * In the case that no argument is provided for an option that takes an
+ * optional argument, return codes @c ARG_OK and @c ARG_IGNORE are equivalent.
+ */
+enum ArgStatus
+{
+  //! The option does not take an argument.
+  ARG_NONE,
+  //! The argument is acceptable for the option.
+  ARG_OK,
+  //! The argument is not acceptable but that's non-fatal because the option's argument is optional.
+  ARG_IGNORE,
+  //! The argument is not acceptable and that's fatal.
+  ARG_ILLEGAL
+};
+
+/**
+ * @brief Signature of functions that check if an argument is valid for a certain type of option.
+ *
+ * Every Option has such a function assigned in its Descriptor.
+ * @code
+ * Descriptor usage[] = { {UNKNOWN, 0, "", "", Arg::None, ""}, ... };
+ * @endcode
+ *
+ * A CheckArg function has the following signature:
+ * @code ArgStatus CheckArg(const Option& option, bool msg); @endcode
+ *
+ * It is used to check if a potential argument would be acceptable for the option.
+ * It will even be called if there is no argument. In that case @c option.arg will be @c NULL.
+ *
+ * If @c msg is @c true and the function determines that an argument is not acceptable and
+ * that this is a fatal error, it should output a message to the user before
+ * returning @ref ARG_ILLEGAL. If @c msg is @c false the function should remain silent (or you
+ * will get duplicate messages).
+ *
+ * See @ref ArgStatus for the meaning of the return values.
+ *
+ * While you can provide your own functions,
+ * often the following pre-defined checks (which never return @ref ARG_ILLEGAL) will suffice:
+ *
+ * @li @c Arg::None @copybrief Arg::None
+ * @li @c Arg::Optional @copybrief Arg::Optional
+ *
+ */
+typedef ArgStatus (*CheckArg)(const Option& option, bool msg);
+
+/**
+ * @brief Describes an option, its help text (usage) and how it should be parsed.
+ *
+ * The main input when constructing an option::Parser is an array of Descriptors.
+
+ * @par Example:
+ * @code
+ * enum OptionIndex {CREATE, ...};
+ * enum OptionType {DISABLE, ENABLE, OTHER};
+ *
+ * const option::Descriptor usage[] = {
+ *   { CREATE,                                            // index
+ *     OTHER,                                             // type
+ *     "c",                                               // shortopt
+ *     "create",                                          // longopt
+ *     Arg::None,                                         // check_arg
+ *     "--create  Tells the program to create something." // help
+ *   }
+ *   , ...
+ * };
+ * @endcode
+ */
+struct Descriptor
+{
+  /**
+   * @brief Index of this option's linked list in the array filled in by the parser.
+   *
+   * Command line options whose Descriptors have the same index will end up in the same
+   * linked list in the order in which they appear on the command line. If you have
+   * multiple long option aliases that refer to the same option, give their descriptors
+   * the same @c index.
+   *
+   * If you have options that mean exactly opposite things
+   * (e.g. @c --enable-foo and @c --disable-foo ), you should also give them the same
+   * @c index, but distinguish them through different values for @ref type.
+   * That way they end up in the same list and you can just take the last element of the
+   * list and use its type. This way you get the usual behaviour where switches later
+   * on the command line override earlier ones without having to code it manually.
+   *
+   * @par Tip:
+   * Use an enum rather than plain ints for better readability, as shown in the example
+   * at Descriptor.
+   */
+  const unsigned index;
+
+  /**
+   * @brief Used to distinguish between options with the same @ref index.
+   * See @ref index for details.
+   *
+   * It is recommended that you use an enum rather than a plain int to make your
+   * code more readable.
+   */
+  const int type;
+
+  /**
+   * @brief Each char in this string will be accepted as a short option character.
+   *
+   * The string must not include the minus character @c '-' or you'll get undefined
+   * behaviour.
+   *
+   * If this Descriptor should not have short option characters, use the empty
+   * string "". NULL is not permitted here!
+   *
+   * See @ref longopt for more information.
+   */
+  const char* const shortopt;
+
+  /**
+   * @brief The long option name (without the leading @c -- ).
+   *
+   * If this Descriptor should not have a long option name, use the empty
+   * string "". NULL is not permitted here!
+   *
+   * While @ref shortopt allows multiple short option characters, each
+   * Descriptor can have only a single long option name. If you have multiple
+   * long option names referring to the same option use separate Descriptors
+   * that have the same @ref index and @ref type. You may repeat
+   * short option characters in such an alias Descriptor but there's no need to.
+   *
+   * @par Dummy Descriptors:
+   * You can use dummy Descriptors with an
+   * empty string for both @ref shortopt and @ref longopt to add text to
+   * the usage that is not related to a specific option. See @ref help.
+   * The first dummy Descriptor will be used for unknown options (see below).
+   *
+   * @par Unknown Option Descriptor:
+   * The first dummy Descriptor in the list of Descriptors,
+   * whose @ref shortopt and @ref longopt are both the empty string, will be used
+   * as the Descriptor for unknown options. An unknown option is a string in
+   * the argument vector that is not a lone minus @c '-' but starts with a minus
+   * character and does not match any Descriptor's @ref shortopt or @ref longopt. @n
+   * Note that the dummy descriptor's @ref check_arg function @e will be called and
+   * its return value will be evaluated as usual. I.e. if it returns @ref ARG_ILLEGAL
+   * the parsing will be aborted with <code>Parser::error()==true</code>. @n
+   * if @c check_arg does not return @ref ARG_ILLEGAL the descriptor's
+   * @ref index @e will be used to pick the linked list into which
+   * to put the unknown option. @n
+   * If there is no dummy descriptor, unknown options will be dropped silently.
+   *
+   */
+  const char* const longopt;
+
+  /**
+   * @brief For each option that matches @ref shortopt or @ref longopt this function
+   * will be called to check a potential argument to the option.
+   *
+   * This function will be called even if there is no potential argument. In that case
+   * it will be passed @c NULL as @c arg parameter. Do not confuse this with the empty
+   * string.
+   *
+   * See @ref CheckArg for more information.
+   */
+  const CheckArg check_arg;
+
+  /**
+   * @brief The usage text associated with the options in this Descriptor.
+   *
+   * You can use option::printUsage() to format your usage message based on
+   * the @c help texts. You can use dummy Descriptors where
+   * @ref shortopt and @ref longopt are both the empty string to add text to
+   * the usage that is not related to a specific option.
+   *
+   * See option::printUsage() for special formatting characters you can use in
+   * @c help to get a column layout.
+   *
+   * @attention
+   * Must be UTF-8-encoded. If your compiler supports C++11 you can use the "u8"
+   * prefix to make sure string literals are properly encoded.
+   */
+  const char* help;
+};
+
+/**
+ * @brief A parsed option from the command line together with its argument if it has one.
+ *
+ * The Parser chains all parsed options with the same Descriptor::index together
+ * to form a linked list. This allows you to easily implement all of the common ways
+ * of handling repeated options and enable/disable pairs.
+ *
+ * @li Test for presence of a switch in the argument vector:
+ *      @code if ( options[QUIET] ) ... @endcode
+ * @li Evaluate --enable-foo/--disable-foo pair where the last one used wins:
+ *     @code if ( options[FOO].last()->type() == DISABLE ) ... @endcode
+ * @li Cumulative option (-v verbose, -vv more verbose, -vvv even more verbose):
+ *     @code int verbosity = options[VERBOSE].count(); @endcode
+ * @li Iterate over all --file=&lt;fname> arguments:
+ *     @code for (Option* opt = options[FILE]; opt; opt = opt->next())
+ *   fname = opt->arg; ... @endcode
+ */
+class Option
+{
+  Option* next_;
+  Option* prev_;
+public:
+  /**
+   * @brief Pointer to this Option's Descriptor.
+   *
+   * Remember that the first dummy descriptor (see @ref Descriptor::longopt) is used
+   * for unknown options.
+   *
+   * @attention
+   * @c desc==NULL signals that this Option is unused. This is the default state of
+   * elements in the result array. You don't need to test @c desc explicitly. You
+   * can simply write something like this:
+   * @code
+   * if (options[CREATE])
+   * {
+   *   ...
+   * }
+   * @endcode
+   * This works because of <code> operator const Option*() </code>.
+   */
+  const Descriptor* desc;
+
+  /**
+   * @brief The name of the option as used on the command line.
+   *
+   * The main purpose of this string is to be presented to the user in messages.
+   *
+   * In the case of a long option, this is the actual @c argv pointer, i.e. the first
+   * character is a '-'. In the case of a short option this points to the option
+   * character within the @c argv string.
+   *
+   * Note that in the case of a short option group or an attached option argument, this
+   * string will contain additional characters following the actual name. Use @ref namelen
+   * to filter out the actual option name only.
+   *
+   */
+  const char* name;
+
+  /**
+   * @brief Pointer to this Option's argument (if any).
+   *
+   * NULL if this option has no argument. Do not confuse this with the empty string which
+   * is a valid argument.
+   */
+  const char* arg;
+
+  /**
+   * @brief The length of the option @ref name.
+   *
+   * Because @ref name points into the actual @c argv string, the option name may be
+   * followed by more characters (e.g. other short options in the same short option group).
+   * This value is the number of bytes (not characters!) that are part of the actual name.
+   *
+   * For a short option, this length is always 1. For a long option this length is always
+   * at least 2 if single minus long options are permitted and at least 3 if they are disabled.
+   *
+   * @note
+   * In the pathological case of a minus within a short option group (e.g. @c -xf-z), this
+   * length is incorrect, because this case will be misinterpreted as a long option and the
+   * name will therefore extend to the string's 0-terminator or a following '=" character
+   * if there is one. This is irrelevant for most uses of @ref name and @c namelen. If you
+   * really need to distinguish the case of a long and a short option, compare @ref name to
+   * the @c argv pointers. A long option's @c name is always identical to one of them,
+   * whereas a short option's is never.
+   */
+  int namelen;
+
+  /**
+   * @brief Returns Descriptor::type of this Option's Descriptor, or 0 if this Option
+   * is invalid (unused).
+   *
+   * Because this method (and last(), too) can be used even on unused Options with desc==0, you can (provided
+   * you arrange your types properly) switch on type() without testing validity first.
+   * @code
+   * enum OptionType { UNUSED=0, DISABLED=0, ENABLED=1 };
+   * enum OptionIndex { FOO };
+   * const Descriptor usage[] = {
+   *   { FOO, ENABLED,  "", "enable-foo",  Arg::None, 0 },
+   *   { FOO, DISABLED, "", "disable-foo", Arg::None, 0 },
+   *   { 0, 0, 0, 0, 0, 0 } };
+   * ...
+   * switch(options[FOO].last()->type()) // no validity check required!
+   * {
+   *   case ENABLED: ...
+   *   case DISABLED: ...  // UNUSED==DISABLED !
+   * }
+   * @endcode
+   */
+  int type() const
+  {
+    return desc == 0 ? 0 : desc->type;
+  }
+
+  /**
+   * @brief Returns Descriptor::index of this Option's Descriptor, or -1 if this Option
+   * is invalid (unused).
+   */
+  int index() const
+  {
+    return desc == 0 ? -1 : desc->index;
+  }
+
+  /**
+   * @brief Returns the number of times this Option (or others with the same Descriptor::index)
+   * occurs in the argument vector.
+   *
+   * This corresponds to the number of elements in the linked list this Option is part of.
+   * It doesn't matter on which element you call count(). The return value is always the same.
+   *
+   * Use this to implement cumulative options, such as -v, -vv, -vvv for
+   * different verbosity levels.
+   *
+   * Returns 0 when called for an unused/invalid option.
+   */
+  int count()
+  {
+    int c = (desc == 0 ? 0 : 1);
+    Option* p = first();
+    while (!p->isLast())
+    {
+      ++c;
+      p = p->next_;
+    };
+    return c;
+  }
+
+  /**
+   * @brief Returns true iff this is the first element of the linked list.
+   *
+   * The first element in the linked list is the first option on the command line
+   * that has the respective Descriptor::index value.
+   *
+   * Returns true for an unused/invalid option.
+   */
+  bool isFirst() const
+  {
+    return isTagged(prev_);
+  }
+
+  /**
+   * @brief Returns true iff this is the last element of the linked list.
+   *
+   * The last element in the linked list is the last option on the command line
+   * that has the respective Descriptor::index value.
+   *
+   * Returns true for an unused/invalid option.
+   */
+  bool isLast() const
+  {
+    return isTagged(next_);
+  }
+
+  /**
+   * @brief Returns a pointer to the first element of the linked list.
+   *
+   * Use this when you want the first occurrence of an option on the command line to
+   * take precedence. Note that this is not the way most programs handle options.
+   * You should probably be using last() instead.
+   *
+   * @note
+   * This method may be called on an unused/invalid option and will return a pointer to the
+   * option itself.
+   */
+  Option* first()
+  {
+    Option* p = this;
+    while (!p->isFirst())
+      p = p->prev_;
+    return p;
+  }
+
+  /**
+   * @brief Returns a pointer to the last element of the linked list.
+   *
+   * Use this when you want the last occurrence of an option on the command line to
+   * take precedence. This is the most common way of handling conflicting options.
+   *
+   * @note
+   * This method may be called on an unused/invalid option and will return a pointer to the
+   * option itself.
+   *
+   * @par Tip:
+   * If you have options with opposite meanings (e.g. @c --enable-foo and @c --disable-foo), you
+   * can assign them the same Descriptor::index to get them into the same list. Distinguish them by
+   * Descriptor::type and all you have to do is check <code> last()->type() </code> to get
+   * the state listed last on the command line.
+   */
+  Option* last()
+  {
+    return first()->prevwrap();
+  }
+
+  /**
+   * @brief Returns a pointer to the previous element of the linked list or NULL if
+   * called on first().
+   *
+   * If called on first() this method returns NULL. Otherwise it will return the
+   * option with the same Descriptor::index that precedes this option on the command
+   * line.
+   */
+  Option* prev()
+  {
+    return isFirst() ? 0 : prev_;
+  }
+
+  /**
+   * @brief Returns a pointer to the previous element of the linked list with wrap-around from
+   * first() to last().
+   *
+   * If called on first() this method returns last(). Otherwise it will return the
+   * option with the same Descriptor::index that precedes this option on the command
+   * line.
+   */
+  Option* prevwrap()
+  {
+    return untag(prev_);
+  }
+
+  /**
+   * @brief Returns a pointer to the next element of the linked list or NULL if called
+   * on last().
+   *
+   * If called on last() this method returns NULL. Otherwise it will return the
+   * option with the same Descriptor::index that follows this option on the command
+   * line.
+   */
+  Option* next()
+  {
+    return isLast() ? 0 : next_;
+  }
+
+  /**
+   * @brief Returns a pointer to the next element of the linked list with wrap-around from
+   * last() to first().
+   *
+   * If called on last() this method returns first(). Otherwise it will return the
+   * option with the same Descriptor::index that follows this option on the command
+   * line.
+   */
+  Option* nextwrap()
+  {
+    return untag(next_);
+  }
+
+  /**
+   * @brief Makes @c new_last the new last() by chaining it into the list after last().
+   *
+   * It doesn't matter which element you call append() on. The new element will always
+   * be appended to last().
+   *
+   * @attention
+   * @c new_last must not yet be part of a list, or that list will become corrupted, because
+   * this method does not unchain @c new_last from an existing list.
+   */
+  void append(Option* new_last)
+  {
+    Option* p = last();
+    Option* f = first();
+    p->next_ = new_last;
+    new_last->prev_ = p;
+    new_last->next_ = tag(f);
+    f->prev_ = tag(new_last);
+  }
+
+  /**
+   * @brief Casts from Option to const Option* but only if this Option is valid.
+   *
+   * If this Option is valid (i.e. @c desc!=NULL), returns this.
+   * Otherwise returns NULL. This allows testing an Option directly
+   * in an if-clause to see if it is used:
+   * @code
+   * if (options[CREATE])
+   * {
+   *   ...
+   * }
+   * @endcode
+   * It also allows you to write loops like this:
+   * @code for (Option* opt = options[FILE]; opt; opt = opt->next())
+   *   fname = opt->arg; ... @endcode
+   */
+  operator const Option*() const
+  {
+    return desc ? this : 0;
+  }
+
+  /**
+   * @brief Casts from Option to Option* but only if this Option is valid.
+   *
+   * If this Option is valid (i.e. @c desc!=NULL), returns this.
+   * Otherwise returns NULL. This allows testing an Option directly
+   * in an if-clause to see if it is used:
+   * @code
+   * if (options[CREATE])
+   * {
+   *   ...
+   * }
+   * @endcode
+   * It also allows you to write loops like this:
+   * @code for (Option* opt = options[FILE]; opt; opt = opt->next())
+   *   fname = opt->arg; ... @endcode
+   */
+  operator Option*()
+  {
+    return desc ? this : 0;
+  }
+
+  /**
+   * @brief Creates a new Option that is a one-element linked list and has NULL
+   * @ref desc, @ref name, @ref arg and @ref namelen.
+   */
+  Option() :
+      desc(0), name(0), arg(0), namelen(0)
+  {
+    prev_ = tag(this);
+    next_ = tag(this);
+  }
+
+  /**
+   * @brief Creates a new Option that is a one-element linked list and has the given
+   * values for @ref desc, @ref name and @ref arg.
+   *
+   * If @c name_ points at a character other than '-' it will be assumed to refer to a
+   * short option and @ref namelen will be set to 1. Otherwise the length will extend to
+   * the first '=' character or the string's 0-terminator.
+   */
+  Option(const Descriptor* desc_, const char* name_, const char* arg_)
+  {
+    init(desc_, name_, arg_);
+  }
+
+  /**
+   * @brief Makes @c *this a copy of @c orig except for the linked list pointers.
+   *
+   * After this operation @c *this will be a one-element linked list.
+   */
+  void operator=(const Option& orig)
+  {
+    init(orig.desc, orig.name, orig.arg);
+  }
+
+  /**
+   * @brief Makes @c *this a copy of @c orig except for the linked list pointers.
+   *
+   * After this operation @c *this will be a one-element linked list.
+   */
+  Option(const Option& orig)
+  {
+    init(orig.desc, orig.name, orig.arg);
+  }
+
+private:
+  /**
+   * @internal
+   * @brief Sets the fields of this Option to the given values (extracting @c name if necessary).
+   *
+   * If @c name_ points at a character other than '-' it will be assumed to refer to a
+   * short option and @ref namelen will be set to 1. Otherwise the length will extend to
+   * the first '=' character or the string's 0-terminator.
+   */
+  void init(const Descriptor* desc_, const char* name_, const char* arg_)
+  {
+    desc = desc_;
+    name = name_;
+    arg = arg_;
+    prev_ = tag(this);
+    next_ = tag(this);
+    namelen = 0;
+    if (name == 0)
+      return;
+    namelen = 1;
+    if (name[0] != '-')
+      return;
+    while (name[namelen] != 0 && name[namelen] != '=')
+      ++namelen;
+  }
+
+  static Option* tag(Option* ptr)
+  {
+    return (Option*) ((unsigned long long) ptr | 1);
+  }
+
+  static Option* untag(Option* ptr)
+  {
+    return (Option*) ((unsigned long long) ptr & ~1ull);
+  }
+
+  static bool isTagged(Option* ptr)
+  {
+    return ((unsigned long long) ptr & 1);
+  }
+};
+
+/**
+ * @brief Functions for checking the validity of option arguments.
+ *
+ * @copydetails CheckArg
+ *
+ * The following example code
+ * can serve as starting place for writing your own more complex CheckArg functions:
+ * @code
+ * struct Arg: public option::Arg
+ * {
+ *   static void printError(const char* msg1, const option::Option& opt, const char* msg2)
+ *   {
+ *     fprintf(stderr, "ERROR: %s", msg1);
+ *     fwrite(opt.name, opt.namelen, 1, stderr);
+ *     fprintf(stderr, "%s", msg2);
+ *   }
+ *
+ *   static option::ArgStatus Unknown(const option::Option& option, bool msg)
+ *   {
+ *     if (msg) printError("Unknown option '", option, "'\n");
+ *     return option::ARG_ILLEGAL;
+ *   }
+ *
+ *   static option::ArgStatus Required(const option::Option& option, bool msg)
+ *   {
+ *     if (option.arg != 0)
+ *       return option::ARG_OK;
+ *
+ *     if (msg) printError("Option '", option, "' requires an argument\n");
+ *     return option::ARG_ILLEGAL;
+ *   }
+ *
+ *   static option::ArgStatus NonEmpty(const option::Option& option, bool msg)
+ *   {
+ *     if (option.arg != 0 && option.arg[0] != 0)
+ *       return option::ARG_OK;
+ *
+ *     if (msg) printError("Option '", option, "' requires a non-empty argument\n");
+ *     return option::ARG_ILLEGAL;
+ *   }
+ *
+ *   static option::ArgStatus Numeric(const option::Option& option, bool msg)
+ *   {
+ *     char* endptr = 0;
+ *     if (option.arg != 0 && strtol(option.arg, &endptr, 10)){};
+ *     if (endptr != option.arg && *endptr == 0)
+ *       return option::ARG_OK;
+ *
+ *     if (msg) printError("Option '", option, "' requires a numeric argument\n");
+ *     return option::ARG_ILLEGAL;
+ *   }
+ * };
+ * @endcode
+ */
+struct Arg
+{
+  //! @brief For options that don't take an argument: Returns ARG_NONE.
+  static ArgStatus None(const Option&, bool)
+  {
+    return ARG_NONE;
+  }
+ static void printError(const char* msg1, const option::Option& opt, const char* msg2)
+ {
+   fprintf(stderr, "ERROR: %s", msg1);
+   fwrite(opt.name, opt.namelen, 1, stderr);
+   fprintf(stderr, "%s", msg2);
+ }
+
+  //! @brief Returns ARG_OK if the argument is attached and ARG_IGNORE otherwise.
+  static ArgStatus Optional(const Option& option, bool)
+  {
+    if (option.arg && option.name[option.namelen] != 0)
+      return ARG_OK;
+    else
+      return ARG_IGNORE;
+  }
+  static option::ArgStatus Required(const option::Option& option, bool msg)
+  {
+      if (option.arg != 0)
+        return option::ARG_OK;
+     if (msg) printError("Option '", option, "' requires an argument\n");
+     return option::ARG_ILLEGAL;
+ }
+};
+
+/**
+ * @brief Determines the minimum lengths of the buffer and options arrays used for Parser.
+ *
+ * Because Parser doesn't use dynamic memory its output arrays have to be pre-allocated.
+ * If you don't want to use fixed size arrays (which may turn out too small, causing
+ * command line arguments to be dropped), you can use Stats to determine the correct sizes.
+ * Stats work cumulative. You can first pass in your default options and then the real
+ * options and afterwards the counts will reflect the union.
+ */
+struct Stats
+{
+  /**
+   * @brief Number of elements needed for a @c buffer[] array to be used for
+   * @ref Parser::parse() "parsing" the same argument vectors that were fed
+   * into this Stats object.
+   *
+   * @note
+   * This number is always 1 greater than the actual number needed, to give
+   * you a sentinel element.
+   */
+  unsigned buffer_max;
+
+  /**
+   * @brief Number of elements needed for an @c options[] array to be used for
+   * @ref Parser::parse() "parsing" the same argument vectors that were fed
+   * into this Stats object.
+   *
+   * @note
+   * @li This number is always 1 greater than the actual number needed, to give
+   * you a sentinel element.
+   * @li This number depends only on the @c usage, not the argument vectors, because
+   * the @c options array needs exactly one slot for each possible Descriptor::index.
+   */
+  unsigned options_max;
+
+  /**
+   * @brief Creates a Stats object with counts set to 1 (for the sentinel element).
+   */
+  Stats() :
+      buffer_max(1), options_max(1) // 1 more than necessary as sentinel
+  {
+  }
+
+  /**
+   * @brief Creates a new Stats object and immediately updates it for the
+   * given @c usage and argument vector. You may pass 0 for @c argc and/or @c argv,
+   * if you just want to update @ref options_max.
+   *
+   * @note
+   * The calls to Stats methods must match the later calls to Parser methods.
+   * See Parser::parse() for the meaning of the arguments.
+   */
+  Stats(bool gnu, const Descriptor usage[], int argc, const char** argv, int min_abbr_len = 0, //
+        bool single_minus_longopt = false) :
+      buffer_max(1), options_max(1) // 1 more than necessary as sentinel
+  {
+    add(gnu, usage, argc, argv, min_abbr_len, single_minus_longopt);
+  }
+
+  //! @brief Stats(...) with non-const argv.
+  Stats(bool gnu, const Descriptor usage[], int argc, char** argv, int min_abbr_len = 0, //
+        bool single_minus_longopt = false) :
+      buffer_max(1), options_max(1) // 1 more than necessary as sentinel
+  {
+    add(gnu, usage, argc, (const char**) argv, min_abbr_len, single_minus_longopt);
+  }
+
+  //! @brief POSIX Stats(...) (gnu==false).
+  Stats(const Descriptor usage[], int argc, const char** argv, int min_abbr_len = 0, //
+        bool single_minus_longopt = false) :
+      buffer_max(1), options_max(1) // 1 more than necessary as sentinel
+  {
+    add(false, usage, argc, argv, min_abbr_len, single_minus_longopt);
+  }
+
+  //! @brief POSIX Stats(...) (gnu==false) with non-const argv.
+  Stats(const Descriptor usage[], int argc, char** argv, int min_abbr_len = 0, //
+        bool single_minus_longopt = false) :
+      buffer_max(1), options_max(1) // 1 more than necessary as sentinel
+  {
+    add(false, usage, argc, (const char**) argv, min_abbr_len, single_minus_longopt);
+  }
+
+  /**
+   * @brief Updates this Stats object for the
+   * given @c usage and argument vector. You may pass 0 for @c argc and/or @c argv,
+   * if you just want to update @ref options_max.
+   *
+   * @note
+   * The calls to Stats methods must match the later calls to Parser methods.
+   * See Parser::parse() for the meaning of the arguments.
+   */
+  void add(bool gnu, const Descriptor usage[], int argc, const char** argv, int min_abbr_len = 0, //
+           bool single_minus_longopt = false);
+
+  //! @brief add() with non-const argv.
+  void add(bool gnu, const Descriptor usage[], int argc, char** argv, int min_abbr_len = 0, //
+           bool single_minus_longopt = false)
+  {
+    add(gnu, usage, argc, (const char**) argv, min_abbr_len, single_minus_longopt);
+  }
+
+  //! @brief POSIX add() (gnu==false).
+  void add(const Descriptor usage[], int argc, const char** argv, int min_abbr_len = 0, //
+           bool single_minus_longopt = false)
+  {
+    add(false, usage, argc, argv, min_abbr_len, single_minus_longopt);
+  }
+
+  //! @brief POSIX add() (gnu==false) with non-const argv.
+  void add(const Descriptor usage[], int argc, char** argv, int min_abbr_len = 0, //
+           bool single_minus_longopt = false)
+  {
+    add(false, usage, argc, (const char**) argv, min_abbr_len, single_minus_longopt);
+  }
+private:
+  class CountOptionsAction;
+};
+
+/**
+ * @brief Checks argument vectors for validity and parses them into data
+ * structures that are easier to work with.
+ *
+ * @par Example:
+ * @code
+ * int main(int argc, char* argv[])
+ * {
+ *   argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
+ *   option::Stats  stats(usage, argc, argv);
+ *   option::Option options[stats.options_max], buffer[stats.buffer_max];
+ *   option::Parser parse(usage, argc, argv, options, buffer);
+ *
+ *   if (parse.error())
+ *     return 1;
+ *
+ *   if (options[HELP])
+ *   ...
+ * @endcode
+ */
+class Parser
+{
+  int op_count; //!< @internal @brief see optionsCount()
+  int nonop_count; //!< @internal @brief see nonOptionsCount()
+  const char** nonop_args; //!< @internal @brief see nonOptions()
+  bool err; //!< @internal @brief see error()
+public:
+
+  /**
+   * @brief Creates a new Parser.
+   */
+  Parser() :
+      op_count(0), nonop_count(0), nonop_args(0), err(false)
+  {
+  }
+
+  /**
+   * @brief Creates a new Parser and immediately parses the given argument vector.
+   * @copydetails parse()
+   */
+  Parser(bool gnu, const Descriptor usage[], int argc, const char** argv, Option options[], Option buffer[],
+         int min_abbr_len = 0, bool single_minus_longopt = false, int bufmax = -1) :
+      op_count(0), nonop_count(0), nonop_args(0), err(false)
+  {
+    parse(gnu, usage, argc, argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  //! @brief Parser(...) with non-const argv.
+  Parser(bool gnu, const Descriptor usage[], int argc, char** argv, Option options[], Option buffer[],
+         int min_abbr_len = 0, bool single_minus_longopt = false, int bufmax = -1) :
+      op_count(0), nonop_count(0), nonop_args(0), err(false)
+  {
+    parse(gnu, usage, argc, (const char**) argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  //! @brief POSIX Parser(...) (gnu==false).
+  Parser(const Descriptor usage[], int argc, const char** argv, Option options[], Option buffer[], int min_abbr_len = 0,
+         bool single_minus_longopt = false, int bufmax = -1) :
+      op_count(0), nonop_count(0), nonop_args(0), err(false)
+  {
+    parse(false, usage, argc, argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  //! @brief POSIX Parser(...) (gnu==false) with non-const argv.
+  Parser(const Descriptor usage[], int argc, char** argv, Option options[], Option buffer[], int min_abbr_len = 0,
+         bool single_minus_longopt = false, int bufmax = -1) :
+      op_count(0), nonop_count(0), nonop_args(0), err(false)
+  {
+    parse(false, usage, argc, (const char**) argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  /**
+   * @brief Parses the given argument vector.
+   *
+   * @param gnu if true, parse() will not stop at the first non-option argument. Instead it will
+   *            reorder arguments so that all non-options are at the end. This is the default behaviour
+   *            of GNU getopt() but is not conforming to POSIX. @n
+   *            Note, that once the argument vector has been reordered, the @c gnu flag will have
+   *            no further effect on this argument vector. So it is enough to pass @c gnu==true when
+   *            creating Stats.
+   * @param usage Array of Descriptor objects that describe the options to support. The last entry
+   *              of this array must have 0 in all fields.
+   * @param argc The number of elements from @c argv that are to be parsed. If you pass -1, the number
+   *             will be determined automatically. In that case the @c argv list must end with a NULL
+   *             pointer.
+   * @param argv The arguments to be parsed. If you pass -1 as @c argc the last pointer in the @c argv
+   *             list must be NULL to mark the end.
+   * @param options Each entry is the first element of a linked list of Options. Each new option
+   *                that is parsed will be appended to the list specified by that Option's
+   *                Descriptor::index. If an entry is not yet used (i.e. the Option is invalid),
+   *                it will be replaced rather than appended to. @n
+   *                The minimum length of this array is the greatest Descriptor::index value that
+   *                occurs in @c usage @e PLUS ONE.
+   * @param buffer Each argument that is successfully parsed (including unknown arguments, if they
+   *        have a Descriptor whose CheckArg does not return @ref ARG_ILLEGAL) will be stored in this
+   *        array. parse() scans the array for the first invalid entry and begins writing at that
+   *        index. You can pass @c bufmax to limit the number of options stored.
+   * @param min_abbr_len Passing a value <code> min_abbr_len > 0 </code> enables abbreviated long
+   *               options. The parser will match a prefix of a long option as if it was
+   *               the full long option (e.g. @c --foob=10 will be interpreted as if it was
+   *               @c --foobar=10 ), as long as the prefix has at least @c min_abbr_len characters
+   *               (not counting the @c -- ) and is unambiguous.
+   *               @n Be careful if combining @c min_abbr_len=1 with @c single_minus_longopt=true
+   *               because the ambiguity check does not consider short options and abbreviated
+   *               single minus long options will take precedence over short options.
+   * @param single_minus_longopt Passing @c true for this option allows long options to begin with
+   *               a single minus. The double minus form will still be recognized. Note that
+   *               single minus long options take precedence over short options and short option
+   *               groups. E.g. @c -file would be interpreted as @c --file and not as
+   *               <code> -f -i -l -e </code> (assuming a long option named @c "file" exists).
+   * @param bufmax The greatest index in the @c buffer[] array that parse() will write to is
+   *               @c bufmax-1. If there are more options, they will be processed (in particular
+   *               their CheckArg will be called) but not stored. @n
+   *               If you used Stats::buffer_max to dimension this array, you can pass
+   *               -1 (or not pass @c bufmax at all) which tells parse() that the buffer is
+   *               "large enough".
+   * @attention
+   * Remember that @c options and @c buffer store Option @e objects, not pointers. Therefore it
+   * is not possible for the same object to be in both arrays. For those options that are found in
+   * both @c buffer[] and @c options[] the respective objects are independent copies. And only the
+   * objects in @c options[] are properly linked via Option::next() and Option::prev().
+   * You can iterate over @c buffer[] to
+   * process all options in the order they appear in the argument vector, but if you want access to
+   * the other Options with the same Descriptor::index, then you @e must access the linked list via
+   * @c options[]. You can get the linked list in options from a buffer object via something like
+   * @c options[buffer[i].index()].
+   */
+  void parse(bool gnu, const Descriptor usage[], int argc, const char** argv, Option options[], Option buffer[],
+             int min_abbr_len = 0, bool single_minus_longopt = false, int bufmax = -1);
+
+  //! @brief parse() with non-const argv.
+  void parse(bool gnu, const Descriptor usage[], int argc, char** argv, Option options[], Option buffer[],
+             int min_abbr_len = 0, bool single_minus_longopt = false, int bufmax = -1)
+  {
+    parse(gnu, usage, argc, (const char**) argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  //! @brief POSIX parse() (gnu==false).
+  void parse(const Descriptor usage[], int argc, const char** argv, Option options[], Option buffer[],
+             int min_abbr_len = 0, bool single_minus_longopt = false, int bufmax = -1)
+  {
+    parse(false, usage, argc, argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  //! @brief POSIX parse() (gnu==false) with non-const argv.
+  void parse(const Descriptor usage[], int argc, char** argv, Option options[], Option buffer[], int min_abbr_len = 0,
+             bool single_minus_longopt = false, int bufmax = -1)
+  {
+    parse(false, usage, argc, (const char**) argv, options, buffer, min_abbr_len, single_minus_longopt, bufmax);
+  }
+
+  /**
+   * @brief Returns the number of valid Option objects in @c buffer[].
+   *
+   * @note
+   * @li The returned value always reflects the number of Options in the buffer[] array used for
+   * the most recent call to parse().
+   * @li The count (and the buffer[]) includes unknown options if they are collected
+   * (see Descriptor::longopt).
+   */
+  int optionsCount()
+  {
+    return op_count;
+  }
+
+  /**
+   * @brief Returns the number of non-option arguments that remained at the end of the
+   * most recent parse() that actually encountered non-option arguments.
+   *
+   * @note
+   * A parse() that does not encounter non-option arguments will leave this value
+   * as well as nonOptions() undisturbed. This means you can feed the Parser a
+   * default argument vector that contains non-option arguments (e.g. a default filename).
+   * Then you feed it the actual arguments from the user. If the user has supplied at
+   * least one non-option argument, all of the non-option arguments from the default
+   * disappear and are replaced by the user's non-option arguments. However, if the
+   * user does not supply any non-option arguments the defaults will still be in
+   * effect.
+   */
+  int nonOptionsCount()
+  {
+    return nonop_count;
+  }
+
+  /**
+   * @brief Returns a pointer to an array of non-option arguments (only valid
+   * if <code>nonOptionsCount() >0 </code>).
+   *
+   * @note
+   * @li parse() does not copy arguments, so this pointer points into the actual argument
+   * vector as passed to parse().
+   * @li As explained at nonOptionsCount() this pointer is only changed by parse() calls
+   * that actually encounter non-option arguments. A parse() call that encounters only
+   * options, will not change nonOptions().
+   */
+  const char** nonOptions()
+  {
+    return nonop_args;
+  }
+
+  /**
+   * @brief Returns <b><code>nonOptions()[i]</code></b> (@e without checking if i is in range!).
+   */
+  const char* nonOption(int i)
+  {
+    return nonOptions()[i];
+  }
+
+  /**
+   * @brief Returns @c true if an unrecoverable error occurred while parsing options.
+   *
+   * An illegal argument to an option (i.e. CheckArg returns @ref ARG_ILLEGAL) is an
+   * unrecoverable error that aborts the parse. Unknown options are only an error if
+   * their CheckArg function returns @ref ARG_ILLEGAL. Otherwise they are collected.
+   * In that case if you want to exit the program if either an illegal argument
+   * or an unknown option has been passed, use code like this
+   *
+   * @code
+   * if (parser.error() || options[UNKNOWN])
+   *   exit(1);
+   * @endcode
+   *
+   */
+  bool error()
+  {
+    return err;
+  }
+
+private:
+  friend struct Stats;
+  class StoreOptionAction;
+  struct Action;
+
+  /**
+   * @internal
+   * @brief This is the core function that does all the parsing.
+   * @retval false iff an unrecoverable error occurred.
+   */
+  static bool workhorse(bool gnu, const Descriptor usage[], int numargs, const char** args, Action& action,
+                        bool single_minus_longopt, bool print_errors, int min_abbr_len);
+
+  /**
+   * @internal
+   * @brief Returns true iff @c st1 is a prefix of @c st2 and
+   * in case @c st2 is longer than @c st1, then
+   * the first additional character is '='.
+   *
+   * @par Examples:
+   * @code
+   * streq("foo", "foo=bar") == true
+   * streq("foo", "foobar")  == false
+   * streq("foo", "foo")     == true
+   * streq("foo=bar", "foo") == false
+   * @endcode
+   */
+  static bool streq(const char* st1, const char* st2)
+  {
+    while (*st1 != 0)
+      if (*st1++ != *st2++)
+        return false;
+    return (*st2 == 0 || *st2 == '=');
+  }
+
+  /**
+   * @internal
+   * @brief Like streq() but handles abbreviations.
+   *
+   * Returns true iff @c st1 and @c st2 have a common
+   * prefix with the following properties:
+   * @li (if min > 0) its length is at least @c min characters or the same length as @c st1 (whichever is smaller).
+   * @li (if min <= 0) its length is the same as that of @c st1
+   * @li within @c st2 the character following the common prefix is either '=' or end-of-string.
+   *
+   * Examples:
+   * @code
+   * streqabbr("foo", "foo=bar",<anything>) == true
+   * streqabbr("foo", "fo=bar" , 2) == true
+   * streqabbr("foo", "fo"     , 2) == true
+   * streqabbr("foo", "fo"     , 0) == false
+   * streqabbr("foo", "f=bar"  , 2) == false
+   * streqabbr("foo", "f"      , 2) == false
+   * streqabbr("fo" , "foo=bar",<anything>)  == false
+   * streqabbr("foo", "foobar" ,<anything>)  == false
+   * streqabbr("foo", "fobar"  ,<anything>)  == false
+   * streqabbr("foo", "foo"    ,<anything>)  == true
+   * @endcode
+   */
+  static bool streqabbr(const char* st1, const char* st2, long long min)
+  {
+    const char* st1start = st1;
+    while (*st1 != 0 && (*st1 == *st2))
+    {
+      ++st1;
+      ++st2;
+    }
+
+    return (*st1 == 0 || (min > 0 && (st1 - st1start) >= min)) && (*st2 == 0 || *st2 == '=');
+  }
+
+  /**
+   * @internal
+   * @brief Returns true iff character @c ch is contained in the string @c st.
+   *
+   * Returns @c true for @c ch==0 .
+   */
+  static bool instr(char ch, const char* st)
+  {
+    while (*st != 0 && *st != ch)
+      ++st;
+    return *st == ch;
+  }
+
+  /**
+   * @internal
+   * @brief Rotates <code>args[-count],...,args[-1],args[0]</code> to become
+   *        <code>args[0],args[-count],...,args[-1]</code>.
+   */
+  static void shift(const char** args, int count)
+  {
+    for (int i = 0; i > -count; --i)
+    {
+      const char* temp = args[i];
+      args[i] = args[i - 1];
+      args[i - 1] = temp;
+    }
+  }
+};
+
+/**
+ * @internal
+ * @brief Interface for actions Parser::workhorse() should perform for each Option it
+ * parses.
+ */
+struct Parser::Action
+{
+  /**
+   * @brief Called by Parser::workhorse() for each Option that has been successfully
+   * parsed (including unknown
+   * options if they have a Descriptor whose Descriptor::check_arg does not return
+   * @ref ARG_ILLEGAL.
+   *
+   * Returns @c false iff a fatal error has occured and the parse should be aborted.
+   */
+  virtual bool perform(Option&)
+  {
+    return true;
+  }
+
+  /**
+   * @brief Called by Parser::workhorse() after finishing the parse.
+   * @param numargs the number of non-option arguments remaining
+   * @param args pointer to the first remaining non-option argument (if numargs > 0).
+   *
+   * @return
+   * @c false iff a fatal error has occurred.
+   */
+  virtual bool finished(int numargs, const char** args)
+  {
+    (void) numargs;
+    (void) args;
+    return true;
+  }
+};
+
+/**
+ * @internal
+ * @brief An Action to pass to Parser::workhorse() that will increment a counter for
+ * each parsed Option.
+ */
+class Stats::CountOptionsAction: public Parser::Action
+{
+  unsigned* buffer_max;
+public:
+  /**
+   * Creates a new CountOptionsAction that will increase @c *buffer_max_ for each
+   * parsed Option.
+   */
+  CountOptionsAction(unsigned* buffer_max_) :
+      buffer_max(buffer_max_)
+  {
+  }
+
+  bool perform(Option&)
+  {
+    if (*buffer_max == 0x7fffffff)
+      return false; // overflow protection: don't accept number of options that doesn't fit signed int
+    ++*buffer_max;
+    return true;
+  }
+};
+
+/**
+ * @internal
+ * @brief An Action to pass to Parser::workhorse() that will store each parsed Option in
+ * appropriate arrays (see Parser::parse()).
+ */
+class Parser::StoreOptionAction: public Parser::Action
+{
+  Parser& parser;
+  Option* options;
+  Option* buffer;
+  int bufmax; //! Number of slots in @c buffer. @c -1 means "large enough".
+public:
+  /**
+   * @brief Creates a new StoreOption action.
+   * @param parser_ the parser whose op_count should be updated.
+   * @param options_ each Option @c o is chained into the linked list @c options_[o.desc->index]
+   * @param buffer_ each Option is appended to this array as long as there's a free slot.
+   * @param bufmax_ number of slots in @c buffer_. @c -1 means "large enough".
+   */
+  StoreOptionAction(Parser& parser_, Option options_[], Option buffer_[], int bufmax_) :
+      parser(parser_), options(options_), buffer(buffer_), bufmax(bufmax_)
+  {
+    // find first empty slot in buffer (if any)
+    int bufidx = 0;
+    while ((bufmax < 0 || bufidx < bufmax) && buffer[bufidx])
+      ++bufidx;
+
+    // set parser's optionCount
+    parser.op_count = bufidx;
+  }
+
+  bool perform(Option& option)
+  {
+    if (bufmax < 0 || parser.op_count < bufmax)
+    {
+      if (parser.op_count == 0x7fffffff)
+        return false; // overflow protection: don't accept number of options that doesn't fit signed int
+
+      buffer[parser.op_count] = option;
+      int idx = buffer[parser.op_count].desc->index;
+      if (options[idx])
+        options[idx].append(buffer[parser.op_count]);
+      else
+        options[idx] = buffer[parser.op_count];
+      ++parser.op_count;
+    }
+    return true; // NOTE: an option that is discarded because of a full buffer is not fatal
+  }
+
+  bool finished(int numargs, const char** args)
+  {
+    // only overwrite non-option argument list if there's at least 1
+    // new non-option argument. Otherwise we keep the old list. This
+    // makes it easy to use default non-option arguments.
+    if (numargs > 0)
+    {
+      parser.nonop_count = numargs;
+      parser.nonop_args = args;
+    }
+
+    return true;
+  }
+};
+
+inline void Parser::parse(bool gnu, const Descriptor usage[], int argc, const char** argv, Option options[],
+                          Option buffer[], int min_abbr_len, bool single_minus_longopt, int bufmax)
+{
+  StoreOptionAction action(*this, options, buffer, bufmax);
+  err = !workhorse(gnu, usage, argc, argv, action, single_minus_longopt, true, min_abbr_len);
+}
+
+inline void Stats::add(bool gnu, const Descriptor usage[], int argc, const char** argv, int min_abbr_len,
+                       bool single_minus_longopt)
+{
+  // determine size of options array. This is the greatest index used in the usage + 1
+  int i = 0;
+  while (usage[i].shortopt != 0)
+  {
+    if (usage[i].index + 1 >= options_max)
+      options_max = (usage[i].index + 1) + 1; // 1 more than necessary as sentinel
+
+    ++i;
+  }
+
+  CountOptionsAction action(&buffer_max);
+  Parser::workhorse(gnu, usage, argc, argv, action, single_minus_longopt, false, min_abbr_len);
+}
+
+inline bool Parser::workhorse(bool gnu, const Descriptor usage[], int numargs, const char** args, Action& action,
+                              bool single_minus_longopt, bool print_errors, int min_abbr_len)
+{
+  // protect against NULL pointer
+  if (args == 0)
+    numargs = 0;
+
+  int nonops = 0;
+
+  while (numargs != 0 && *args != 0)
+  {
+    const char* param = *args; // param can be --long-option, -srto or non-option argument
+
+    // in POSIX mode the first non-option argument terminates the option list
+    // a lone minus character is a non-option argument
+    if (param[0] != '-' || param[1] == 0)
+    {
+      if (gnu)
+      {
+        ++nonops;
+        ++args;
+        if (numargs > 0)
+          --numargs;
+        continue;
+      }
+      else
+        break;
+    }
+
+    // -- terminates the option list. The -- itself is skipped.
+    if (param[1] == '-' && param[2] == 0)
+    {
+      shift(args, nonops);
+      ++args;
+      if (numargs > 0)
+        --numargs;
+      break;
+    }
+
+    bool handle_short_options;
+    const char* longopt_name;
+    if (param[1] == '-') // if --long-option
+    {
+      handle_short_options = false;
+      longopt_name = param + 2;
+    }
+    else
+    {
+      handle_short_options = true;
+      longopt_name = param + 1; //for testing a potential -long-option
+    }
+
+    bool try_single_minus_longopt = single_minus_longopt;
+    bool have_more_args = (numargs > 1 || numargs < 0); // is referencing argv[1] valid?
+
+    do // loop over short options in group, for long options the body is executed only once
+    {
+      int idx;
+
+      const char* optarg;
+
+      /******************** long option **********************/
+      if (handle_short_options == false || try_single_minus_longopt)
+      {
+        idx = 0;
+        while (usage[idx].longopt != 0 && !streq(usage[idx].longopt, longopt_name))
+          ++idx;
+
+        if (usage[idx].longopt == 0 && min_abbr_len > 0) // if we should try to match abbreviated long options
+        {
+          int i1 = 0;
+          while (usage[i1].longopt != 0 && !streqabbr(usage[i1].longopt, longopt_name, min_abbr_len))
+            ++i1;
+          if (usage[i1].longopt != 0)
+          { // now test if the match is unambiguous by checking for another match
+            int i2 = i1 + 1;
+            while (usage[i2].longopt != 0 && !streqabbr(usage[i2].longopt, longopt_name, min_abbr_len))
+              ++i2;
+
+            if (usage[i2].longopt == 0) // if there was no second match it's unambiguous, so accept i1 as idx
+              idx = i1;
+          }
+        }
+
+        // if we found something, disable handle_short_options (only relevant if single_minus_longopt)
+        if (usage[idx].longopt != 0)
+          handle_short_options = false;
+
+        try_single_minus_longopt = false; // prevent looking for longopt in the middle of shortopt group
+
+        optarg = longopt_name;
+        while (*optarg != 0 && *optarg != '=')
+          ++optarg;
+        if (*optarg == '=') // attached argument
+          ++optarg;
+        else
+          // possibly detached argument
+          optarg = (have_more_args ? args[1] : 0);
+      }
+
+      /************************ short option ***********************************/
+      if (handle_short_options)
+      {
+        if (*++param == 0) // point at the 1st/next option character
+          break; // end of short option group
+
+        idx = 0;
+        while (usage[idx].shortopt != 0 && !instr(*param, usage[idx].shortopt))
+          ++idx;
+
+        if (param[1] == 0) // if the potential argument is separate
+          optarg = (have_more_args ? args[1] : 0);
+        else
+          // if the potential argument is attached
+          optarg = param + 1;
+      }
+
+      const Descriptor* descriptor = &usage[idx];
+
+      if (descriptor->shortopt == 0) /**************  unknown option ********************/
+      {
+        // look for dummy entry (shortopt == "" and longopt == "") to use as Descriptor for unknown options
+        idx = 0;
+        while (usage[idx].shortopt != 0 && (usage[idx].shortopt[0] != 0 || usage[idx].longopt[0] != 0))
+          ++idx;
+        descriptor = (usage[idx].shortopt == 0 ? 0 : &usage[idx]);
+      }
+
+      if (descriptor != 0)
+      {
+        Option option(descriptor, param, optarg);
+        switch (descriptor->check_arg(option, print_errors))
+        {
+          case ARG_ILLEGAL:
+            return false; // fatal
+          case ARG_OK:
+            // skip one element of the argument vector, if it's a separated argument
+            if (optarg != 0 && have_more_args && optarg == args[1])
+            {
+              shift(args, nonops);
+              if (numargs > 0)
+                --numargs;
+              ++args;
+            }
+
+            // No further short options are possible after an argument
+            handle_short_options = false;
+
+            break;
+          case ARG_IGNORE:
+          case ARG_NONE:
+            option.arg = 0;
+            break;
+        }
+
+        if (!action.perform(option))
+          return false;
+      }
+
+    } while (handle_short_options);
+
+    shift(args, nonops);
+    ++args;
+    if (numargs > 0)
+      --numargs;
+
+  } // while
+
+  if (numargs > 0 && *args == 0) // It's a bug in the caller if numargs is greater than the actual number
+    numargs = 0; // of arguments, but as a service to the user we fix this if we spot it.
+
+  if (numargs < 0) // if we don't know the number of remaining non-option arguments
+  { // we need to count them
+    numargs = 0;
+    while (args[numargs] != 0)
+      ++numargs;
+  }
+
+  return action.finished(numargs + nonops, args - nonops);
+}
+
+/**
+ * @internal
+ * @brief The implementation of option::printUsage().
+ */
+struct PrintUsageImplementation
+{
+  /**
+   * @internal
+   * @brief Interface for Functors that write (part of) a string somewhere.
+   */
+  struct IStringWriter
+  {
+    /**
+     * @brief Writes the given number of chars beginning at the given pointer somewhere.
+     */
+    virtual void operator()(const char*, int)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Encapsulates a function with signature <code>func(string, size)</code> where
+   * string can be initialized with a const char* and size with an int.
+   */
+  template<typename Function>
+  struct FunctionWriter: public IStringWriter
+  {
+    Function* write;
+
+    virtual void operator()(const char* str, int size)
+    {
+      (*write)(str, size);
+    }
+
+    FunctionWriter(Function* w) :
+        write(w)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Encapsulates a reference to an object with a <code>write(string, size)</code>
+   * method like that of @c std::ostream.
+   */
+  template<typename OStream>
+  struct OStreamWriter: public IStringWriter
+  {
+    OStream& ostream;
+
+    virtual void operator()(const char* str, int size)
+    {
+      ostream.write(str, size);
+    }
+
+    OStreamWriter(OStream& o) :
+        ostream(o)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Like OStreamWriter but encapsulates a @c const reference, which is
+   * typically a temporary object of a user class.
+   */
+  template<typename Temporary>
+  struct TemporaryWriter: public IStringWriter
+  {
+    const Temporary& userstream;
+
+    virtual void operator()(const char* str, int size)
+    {
+      userstream.write(str, size);
+    }
+
+    TemporaryWriter(const Temporary& u) :
+        userstream(u)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Encapsulates a function with the signature <code>func(fd, string, size)</code> (the
+   * signature of the @c write() system call)
+   * where fd can be initialized from an int, string from a const char* and size from an int.
+   */
+  template<typename Syscall>
+  struct SyscallWriter: public IStringWriter
+  {
+    Syscall* write;
+    int fd;
+
+    virtual void operator()(const char* str, int size)
+    {
+      (*write)(fd, str, size);
+    }
+
+    SyscallWriter(Syscall* w, int f) :
+        write(w), fd(f)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Encapsulates a function with the same signature as @c std::fwrite().
+   */
+  template<typename Function, typename Stream>
+  struct StreamWriter: public IStringWriter
+  {
+    Function* fwrite;
+    Stream* stream;
+
+    virtual void operator()(const char* str, int size)
+    {
+      (*fwrite)(str, size, 1, stream);
+    }
+
+    StreamWriter(Function* w, Stream* s) :
+        fwrite(w), stream(s)
+    {
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Sets <code> i1 = max(i1, i2) </code>
+   */
+  static void upmax(int& i1, int i2)
+  {
+    i1 = (i1 >= i2 ? i1 : i2);
+  }
+
+  /**
+   * @internal
+   * @brief Moves the "cursor" to column @c want_x assuming it is currently at column @c x
+   * and sets @c x=want_x .
+   * If <code> x > want_x </code>, a line break is output before indenting.
+   *
+   * @param write Spaces and possibly a line break are written via this functor to get
+   *        the desired indentation @c want_x .
+   * @param[in,out] x the current indentation. Set to @c want_x by this method.
+   * @param want_x the desired indentation.
+   */
+  static void indent(IStringWriter& write, int& x, int want_x)
+  {
+    int indent = want_x - x;
+    if (indent < 0)
+    {
+      write("\n", 1);
+      indent = want_x;
+    }
+
+    if (indent > 0)
+    {
+      char space = ' ';
+      for (int i = 0; i < indent; ++i)
+        write(&space, 1);
+      x = want_x;
+    }
+  }
+
+  /**
+   * @brief Returns true if ch is the unicode code point of a wide character.
+   *
+   * @note
+   * The following character ranges are treated as wide
+   * @code
+   * 1100..115F
+   * 2329..232A  (just 2 characters!)
+   * 2E80..A4C6  except for 303F
+   * A960..A97C
+   * AC00..D7FB
+   * F900..FAFF
+   * FE10..FE6B
+   * FF01..FF60
+   * FFE0..FFE6
+   * 1B000......
+   * @endcode
+   */
+  static bool isWideChar(unsigned ch)
+  {
+    if (ch == 0x303F)
+      return false;
+
+    return ((0x1100 <= ch && ch <= 0x115F) || (0x2329 <= ch && ch <= 0x232A) || (0x2E80 <= ch && ch <= 0xA4C6)
+        || (0xA960 <= ch && ch <= 0xA97C) || (0xAC00 <= ch && ch <= 0xD7FB) || (0xF900 <= ch && ch <= 0xFAFF)
+        || (0xFE10 <= ch && ch <= 0xFE6B) || (0xFF01 <= ch && ch <= 0xFF60) || (0xFFE0 <= ch && ch <= 0xFFE6)
+        || (0x1B000 <= ch));
+  }
+
+  /**
+   * @internal
+   * @brief Splits a @c Descriptor[] array into tables, rows, lines and columns and
+   * iterates over these components.
+   *
+   * The top-level organizational unit is the @e table.
+   * A table begins at a Descriptor with @c help!=NULL and extends up to
+   * a Descriptor with @c help==NULL.
+   *
+   * A table consists of @e rows. Due to line-wrapping and explicit breaks
+   * a row may take multiple lines on screen. Rows within the table are separated
+   * by \\n. They never cross Descriptor boundaries. This means a row ends either
+   * at \\n or the 0 at the end of the help string.
+   *
+   * A row consists of columns/cells. Columns/cells within a row are separated by \\t.
+   * Line breaks within a cell are marked by \\v.
+   *
+   * Rows in the same table need not have the same number of columns/cells. The
+   * extreme case are interjections, which are rows that contain neither \\t nor \\v.
+   * These are NOT treated specially by LinePartIterator, but they are treated
+   * specially by printUsage().
+   *
+   * LinePartIterator iterates through the usage at 3 levels: table, row and part.
+   * Tables and rows are as described above. A @e part is a line within a cell.
+   * LinePartIterator iterates through 1st parts of all cells, then through the 2nd
+   * parts of all cells (if any),... @n
+   * Example: The row <code> "1 \v 3 \t 2 \v 4" </code> has 2 cells/columns and 4 parts.
+   * The parts will be returned in the order 1, 2, 3, 4.
+   *
+   * It is possible that some cells have fewer parts than others. In this case
+   * LinePartIterator will "fill up" these cells with 0-length parts. IOW, LinePartIterator
+   * always returns the same number of parts for each column. Note that this is different
+   * from the way rows and columns are handled. LinePartIterator does @e not guarantee that
+   * the same number of columns will be returned for each row.
+   *
+   */
+  class LinePartIterator
+  {
+    const Descriptor* tablestart; //!< The 1st descriptor of the current table.
+    const Descriptor* rowdesc; //!< The Descriptor that contains the current row.
+    const char* rowstart; //!< Ptr to 1st character of current row within rowdesc->help.
+    const char* ptr; //!< Ptr to current part within the current row.
+    int col; //!< Index of current column.
+    int len; //!< Length of the current part (that ptr points at) in BYTES
+    int screenlen; //!< Length of the current part in screen columns (taking narrow/wide chars into account).
+    int max_line_in_block; //!< Greatest index of a line within the block. This is the number of \\v within the cell with the most \\vs.
+    int line_in_block; //!< Line index within the current cell of the current part.
+    int target_line_in_block; //!< Line index of the parts we should return to the user on this iteration.
+    bool hit_target_line; //!< Flag whether we encountered a part with line index target_line_in_block in the current cell.
+
+    /** 
+     * @brief Determines the byte and character lengths of the part at @ref ptr and 
+     * stores them in @ref len and @ref screenlen respectively.
+     */
+    void update_length()
+    {
+      screenlen = 0;
+      for (len = 0; ptr[len] != 0 && ptr[len] != '\v' && ptr[len] != '\t' && ptr[len] != '\n'; ++len)
+      {
+        ++screenlen;
+        unsigned ch = (unsigned char) ptr[len];
+        if (ch > 0xC1) // everything <= 0xC1 (yes, even 0xC1 itself) is not a valid UTF-8 start byte
+        {
+          // int __builtin_clz (unsigned int x)
+          // Returns the number of leading 0-bits in x, starting at the most significant bit
+          unsigned mask = (unsigned) -1 >> __builtin_clz(ch ^ 0xff);
+          ch = ch & mask; // mask out length bits, we don't verify their correctness
+          while (((unsigned char) ptr[len + 1] ^ 0x80) <= 0x3F) // while next byte is continuation byte
+          {
+            ch = (ch << 6) ^ (unsigned char) ptr[len + 1] ^ 0x80; // add continuation to char code
+            ++len;
+          }
+          // ch is the decoded unicode code point
+          if (ch >= 0x1100 && isWideChar(ch)) // the test for 0x1100 is here to avoid the function call in the Latin case
+            ++screenlen;
+        }
+      }
+    }
+
+  public:
+    //! @brief Creates an iterator for @c usage.
+    LinePartIterator(const Descriptor usage[]) :
+        tablestart(usage), rowdesc(0), rowstart(0), ptr(0), col(-1), len(0), max_line_in_block(0), line_in_block(0),
+        target_line_in_block(0), hit_target_line(true)
+    {
+    }
+
+    /**
+     * @brief Moves iteration to the next table (if any). Has to be called once on a new
+     * LinePartIterator to move to the 1st table.
+     * @retval false if moving to next table failed because no further table exists.
+     */
+    bool nextTable()
+    {
+      // If this is NOT the first time nextTable() is called after the constructor,
+      // then skip to the next table break (i.e. a Descriptor with help == 0)
+      if (rowdesc != 0)
+      {
+        while (tablestart->help != 0 && tablestart->shortopt != 0)
+          ++tablestart;
+      }
+
+      // Find the next table after the break (if any)
+      while (tablestart->help == 0 && tablestart->shortopt != 0)
+        ++tablestart;
+
+      restartTable();
+      return rowstart != 0;
+    }
+
+    /**
+     * @brief Reset iteration to the beginning of the current table.
+     */
+    void restartTable()
+    {
+      rowdesc = tablestart;
+      rowstart = tablestart->help;
+      ptr = 0;
+    }
+
+    /**
+     * @brief Moves iteration to the next row (if any). Has to be called once after each call to
+     * @ref nextTable() to move to the 1st row of the table.
+     * @retval false if moving to next row failed because no further row exists.
+     */
+    bool nextRow()
+    {
+      if (ptr == 0)
+      {
+        restartRow();
+        return rowstart != 0;
+      }
+
+      while (*ptr != 0 && *ptr != '\n')
+        ++ptr;
+
+      if (*ptr == 0)
+      {
+        if ((rowdesc + 1)->help == 0) // table break
+          return false;
+
+        ++rowdesc;
+        rowstart = rowdesc->help;
+      }
+      else // if (*ptr == '\n')
+      {
+        rowstart = ptr + 1;
+      }
+
+      restartRow();
+      return true;
+    }
+
+    /**
+     * @brief Reset iteration to the beginning of the current row.
+     */
+    void restartRow()
+    {
+      ptr = rowstart;
+      col = -1;
+      len = 0;
+      screenlen = 0;
+      max_line_in_block = 0;
+      line_in_block = 0;
+      target_line_in_block = 0;
+      hit_target_line = true;
+    }
+
+    /**
+     * @brief Moves iteration to the next part (if any). Has to be called once after each call to
+     * @ref nextRow() to move to the 1st part of the row.
+     * @retval false if moving to next part failed because no further part exists.
+     *
+     * See @ref LinePartIterator for details about the iteration.
+     */
+    bool next()
+    {
+      if (ptr == 0)
+        return false;
+
+      if (col == -1)
+      {
+        col = 0;
+        update_length();
+        return true;
+      }
+
+      ptr += len;
+      while (true)
+      {
+        switch (*ptr)
+        {
+          case '\v':
+            upmax(max_line_in_block, ++line_in_block);
+            ++ptr;
+            break;
+          case '\t':
+            if (!hit_target_line) // if previous column did not have the targetline
+            { // then "insert" a 0-length part
+              update_length();
+              hit_target_line = true;
+              return true;
+            }
+
+            hit_target_line = false;
+            line_in_block = 0;
+            ++col;
+            ++ptr;
+            break;
+          case 0:
+          case '\n':
+            if (!hit_target_line) // if previous column did not have the targetline
+            { // then "insert" a 0-length part
+              update_length();
+              hit_target_line = true;
+              return true;
+            }
+
+            if (++target_line_in_block > max_line_in_block)
+            {
+              update_length();
+              return false;
+            }
+
+            hit_target_line = false;
+            line_in_block = 0;
+            col = 0;
+            ptr = rowstart;
+            continue;
+          default:
+            ++ptr;
+            continue;
+        } // switch
+
+        if (line_in_block == target_line_in_block)
+        {
+          update_length();
+          hit_target_line = true;
+          return true;
+        }
+      } // while
+    }
+
+    /**
+     * @brief Returns the index (counting from 0) of the column in which
+     * the part pointed to by @ref data() is located.
+     */
+    int column()
+    {
+      return col;
+    }
+
+    /**
+     * @brief Returns the index (counting from 0) of the line within the current column
+     * this part belongs to.
+     */
+    int line()
+    {
+      return target_line_in_block; // NOT line_in_block !!! It would be wrong if !hit_target_line
+    }
+
+    /**
+     * @brief Returns the length of the part pointed to by @ref data() in raw chars (not UTF-8 characters).
+     */
+    int length()
+    {
+      return len;
+    }
+
+    /**
+     * @brief Returns the width in screen columns of the part pointed to by @ref data().
+     * Takes multi-byte UTF-8 sequences and wide characters into account.
+     */
+    int screenLength()
+    {
+      return screenlen;
+    }
+
+    /**
+     * @brief Returns the current part of the iteration.
+     */
+    const char* data()
+    {
+      return ptr;
+    }
+  };
+
+  /**
+   * @internal
+   * @brief Takes input and line wraps it, writing out one line at a time so that
+   * it can be interleaved with output from other columns.
+   *
+   * The LineWrapper is used to handle the last column of each table as well as interjections.
+   * The LineWrapper is called once for each line of output. If the data given to it fits
+   * into the designated width of the last column it is simply written out. If there
+   * is too much data, an appropriate split point is located and only the data up to this
+   * split point is written out. The rest of the data is queued for the next line.
+   * That way the last column can be line wrapped and interleaved with data from
+   * other columns. The following example makes this clearer:
+   * @code
+   * Column 1,1    Column 2,1     This is a long text
+   * Column 1,2    Column 2,2     that does not fit into
+   *                              a single line.
+   * @endcode
+   *
+   * The difficulty in producing this output is that the whole string
+   * "This is a long text that does not fit into a single line" is the
+   * 1st and only part of column 3. In order to produce the above
+   * output the string must be output piecemeal, interleaved with
+   * the data from the other columns.
+   */
+  class LineWrapper
+  {
+    static const int bufmask = 15; //!< Must be a power of 2 minus 1.
+    /**
+     * @brief Ring buffer for length component of pair (data, length).
+     */
+    int lenbuf[bufmask + 1];
+    /**
+     * @brief Ring buffer for data component of pair (data, length).
+     */
+    const char* datbuf[bufmask + 1];
+    /**
+     * @brief The indentation of the column to which the LineBuffer outputs. LineBuffer
+     * assumes that the indentation has already been written when @ref process()
+     * is called, so this value is only used when a buffer flush requires writing
+     * additional lines of output.
+     */
+    int x;
+    /**
+     * @brief The width of the column to line wrap.
+     */
+    int width;
+    int head; //!< @brief index for next write
+    int tail; //!< @brief index for next read - 1 (i.e. increment tail BEFORE read)
+
+    /**
+     * @brief Multiple methods of LineWrapper may decide to flush part of the buffer to
+     * free up space. The contract of process() says that only 1 line is output. So
+     * this variable is used to track whether something has output a line. It is
+     * reset at the beginning of process() and checked at the end to decide if
+     * output has already occurred or is still needed.
+     */
+    bool wrote_something;
+
+    bool buf_empty()
+    {
+      return ((tail + 1) & bufmask) == head;
+    }
+
+    bool buf_full()
+    {
+      return tail == head;
+    }
+
+    void buf_store(const char* data, int len)
+    {
+      lenbuf[head] = len;
+      datbuf[head] = data;
+      head = (head + 1) & bufmask;
+    }
+
+    //! @brief Call BEFORE reading ...buf[tail].
+    void buf_next()
+    {
+      tail = (tail + 1) & bufmask;
+    }
+
+    /**
+     * @brief Writes (data,len) into the ring buffer. If the buffer is full, a single line
+     * is flushed out of the buffer into @c write.
+     */
+    void output(IStringWriter& write, const char* data, int len)
+    {
+      if (buf_full())
+        write_one_line(write);
+
+      buf_store(data, len);
+    }
+
+    /**
+     * @brief Writes a single line of output from the buffer to @c write.
+     */
+    void write_one_line(IStringWriter& write)
+    {
+      if (wrote_something) // if we already wrote something, we need to start a new line
+      {
+        write("\n", 1);
+        int _ = 0;
+        indent(write, _, x);
+      }
+
+      if (!buf_empty())
+      {
+        buf_next();
+        write(datbuf[tail], lenbuf[tail]);
+      }
+
+      wrote_something = true;
+    }
+  public:
+
+    /**
+     * @brief Writes out all remaining data from the LineWrapper using @c write.
+     * Unlike @ref process() this method indents all lines including the first and
+     * will output a \\n at the end (but only if something has been written).
+     */
+    void flush(IStringWriter& write)
+    {
+      if (buf_empty())
+        return;
+      int _ = 0;
+      indent(write, _, x);
+      wrote_something = false;
+      while (!buf_empty())
+        write_one_line(write);
+      write("\n", 1);
+    }
+
+    /**
+     * @brief Process, wrap and output the next piece of data.
+     *
+     * process() will output at least one line of output. This is not necessarily
+     * the @c data passed in. It may be data queued from a prior call to process().
+     * If the internal buffer is full, more than 1 line will be output.
+     *
+     * process() assumes that the a proper amount of indentation has already been
+     * output. It won't write any further indentation before the 1st line. If
+     * more than 1 line is written due to buffer constraints, the lines following
+     * the first will be indented by this method, though.
+     *
+     * No \\n is written by this method after the last line that is written.
+     *
+     * @param write where to write the data.
+     * @param data the new chunk of data to write.
+     * @param len the length of the chunk of data to write.
+     */
+    void process(IStringWriter& write, const char* data, int len)
+    {
+      wrote_something = false;
+
+      while (len > 0)
+      {
+        if (len <= width) // quick test that works because utf8width <= len (all wide chars have at least 2 bytes)
+        {
+          output(write, data, len);
+          len = 0;
+        }
+        else // if (len > width)  it's possible (but not guaranteed) that utf8len > width
+        {
+          int utf8width = 0;
+          int maxi = 0;
+          while (maxi < len && utf8width < width)
+          {
+            int charbytes = 1;
+            unsigned ch = (unsigned char) data[maxi];
+            if (ch > 0xC1) // everything <= 0xC1 (yes, even 0xC1 itself) is not a valid UTF-8 start byte
+            {
+              // int __builtin_clz (unsigned int x)
+              // Returns the number of leading 0-bits in x, starting at the most significant bit
+              unsigned mask = (unsigned) -1 >> __builtin_clz(ch ^ 0xff);
+              ch = ch & mask; // mask out length bits, we don't verify their correctness
+              while ((maxi + charbytes < len) && //
+                  (((unsigned char) data[maxi + charbytes] ^ 0x80) <= 0x3F)) // while next byte is continuation byte
+              {
+                ch = (ch << 6) ^ (unsigned char) data[maxi + charbytes] ^ 0x80; // add continuation to char code
+                ++charbytes;
+              }
+              // ch is the decoded unicode code point
+              if (ch >= 0x1100 && isWideChar(ch)) // the test for 0x1100 is here to avoid the function call in the Latin case
+              {
+                if (utf8width + 2 > width)
+                  break;
+                ++utf8width;
+              }
+            }
+            ++utf8width;
+            maxi += charbytes;
+          }
+
+          // data[maxi-1] is the last byte of the UTF-8 sequence of the last character that fits
+          // onto the 1st line. If maxi == len, all characters fit on the line.
+
+          if (maxi == len)
+          {
+            output(write, data, len);
+            len = 0;
+          }
+          else // if (maxi < len)  at least 1 character (data[maxi] that is) doesn't fit on the line
+          {
+            int i;
+            for (i = maxi; i >= 0; --i)
+              if (data[i] == ' ')
+                break;
+
+            if (i >= 0)
+            {
+              output(write, data, i);
+              data += i + 1;
+              len -= i + 1;
+            }
+            else // did not find a space to split at => split before data[maxi]
+            { // data[maxi] is always the beginning of a character, never a continuation byte
+              output(write, data, maxi);
+              data += maxi;
+              len -= maxi;
+            }
+          }
+        }
+      }
+      if (!wrote_something) // if we didn't already write something to make space in the buffer
+        write_one_line(write); // write at most one line of actual output
+    }
+
+    /**
+     * @brief Constructs a LineWrapper that wraps its output to fit into
+     * screen columns @c x1 (incl.) to @c x2 (excl.).
+     *
+     * @c x1 gives the indentation LineWrapper uses if it needs to indent.
+     */
+    LineWrapper(int x1, int x2) :
+        x(x1), width(x2 - x1), head(0), tail(bufmask)
+    {
+      if (width < 2) // because of wide characters we need at least width 2 or the code breaks
+        width = 2;
+    }
+  };
+
+  /**
+   * @internal
+   * @brief This is the implementation that is shared between all printUsage() templates.
+   * Because all printUsage() templates share this implementation, there is no template bloat.
+   */
+  static void printUsage(IStringWriter& write, const Descriptor usage[], int width = 80, //
+                         int last_column_min_percent = 50, int last_column_own_line_max_percent = 75)
+  {
+    if (width < 1) // protect against nonsense values
+      width = 80;
+
+    if (width > 10000) // protect against overflow in the following computation
+      width = 10000;
+
+    int last_column_min_width = ((width * last_column_min_percent) + 50) / 100;
+    int last_column_own_line_max_width = ((width * last_column_own_line_max_percent) + 50) / 100;
+    if (last_column_own_line_max_width == 0)
+      last_column_own_line_max_width = 1;
+
+    LinePartIterator part(usage);
+    while (part.nextTable())
+    {
+
+      /***************** Determine column widths *******************************/
+
+      const int maxcolumns = 8; // 8 columns are enough for everyone
+      int col_width[maxcolumns];
+      int lastcolumn;
+      int leftwidth;
+      int overlong_column_threshold = 10000;
+      do
+      {
+        lastcolumn = 0;
+        for (int i = 0; i < maxcolumns; ++i)
+          col_width[i] = 0;
+
+        part.restartTable();
+        while (part.nextRow())
+        {
+          while (part.next())
+          {
+            if (part.column() < maxcolumns)
+            {
+              upmax(lastcolumn, part.column());
+              if (part.screenLength() < overlong_column_threshold)
+                // We don't let rows that don't use table separators (\t or \v) influence
+                // the width of column 0. This allows the user to interject section headers
+                // or explanatory paragraphs that do not participate in the table layout.
+                if (part.column() > 0 || part.line() > 0 || part.data()[part.length()] == '\t'
+                    || part.data()[part.length()] == '\v')
+                  upmax(col_width[part.column()], part.screenLength());
+            }
+          }
+        }
+
+        /*
+         * If the last column doesn't fit on the same
+         * line as the other columns, we can fix that by starting it on its own line.
+         * However we can't do this for any of the columns 0..lastcolumn-1.
+         * If their sum exceeds the maximum width we try to fix this by iteratively
+         * ignoring the widest line parts in the width determination until
+         * we arrive at a series of column widths that fit into one line.
+         * The result is a layout where everything is nicely formatted
+         * except for a few overlong fragments.
+         * */
+
+        leftwidth = 0;
+        overlong_column_threshold = 0;
+        for (int i = 0; i < lastcolumn; ++i)
+        {
+          leftwidth += col_width[i];
+          upmax(overlong_column_threshold, col_width[i]);
+        }
+
+      } while (leftwidth > width);
+
+      /**************** Determine tab stops and last column handling **********************/
+
+      int tabstop[maxcolumns];
+      tabstop[0] = 0;
+      for (int i = 1; i < maxcolumns; ++i)
+        tabstop[i] = tabstop[i - 1] + col_width[i - 1];
+
+      int rightwidth = width - tabstop[lastcolumn];
+      bool print_last_column_on_own_line = false;
+      if (rightwidth < last_column_min_width && rightwidth < col_width[lastcolumn])
+      {
+        print_last_column_on_own_line = true;
+        rightwidth = last_column_own_line_max_width;
+      }
+
+      // If lastcolumn == 0 we must disable print_last_column_on_own_line because
+      // otherwise 2 copies of the last (and only) column would be output.
+      // Actually this is just defensive programming. It is currently not
+      // possible that lastcolumn==0 and print_last_column_on_own_line==true
+      // at the same time, because lastcolumn==0 => tabstop[lastcolumn] == 0 =>
+      // rightwidth==width => rightwidth>=last_column_min_width  (unless someone passes
+      // a bullshit value >100 for last_column_min_percent) => the above if condition
+      // is false => print_last_column_on_own_line==false
+      if (lastcolumn == 0)
+        print_last_column_on_own_line = false;
+
+      LineWrapper lastColumnLineWrapper(width - rightwidth, width);
+      LineWrapper interjectionLineWrapper(0, width);
+
+      part.restartTable();
+
+      /***************** Print out all rows of the table *************************************/
+
+      while (part.nextRow())
+      {
+        int x = -1;
+        while (part.next())
+        {
+          if (part.column() > lastcolumn)
+            continue; // drop excess columns (can happen if lastcolumn == maxcolumns-1)
+
+          if (part.column() == 0)
+          {
+            if (x >= 0)
+              write("\n", 1);
+            x = 0;
+          }
+
+          indent(write, x, tabstop[part.column()]);
+
+          if ((part.column() < lastcolumn)
+              && (part.column() > 0 || part.line() > 0 || part.data()[part.length()] == '\t'
+                  || part.data()[part.length()] == '\v'))
+          {
+            write(part.data(), part.length());
+            x += part.screenLength();
+          }
+          else // either part.column() == lastcolumn or we are in the special case of
+               // an interjection that doesn't contain \v or \t
+          {
+            // NOTE: This code block is not necessarily executed for
+            // each line, because some rows may have fewer columns.
+
+            LineWrapper& lineWrapper = (part.column() == 0) ? interjectionLineWrapper : lastColumnLineWrapper;
+
+            if (!print_last_column_on_own_line)
+              lineWrapper.process(write, part.data(), part.length());
+          }
+        } // while
+
+        if (print_last_column_on_own_line)
+        {
+          part.restartRow();
+          while (part.next())
+          {
+            if (part.column() == lastcolumn)
+            {
+              write("\n", 1);
+              int _ = 0;
+              indent(write, _, width - rightwidth);
+              lastColumnLineWrapper.process(write, part.data(), part.length());
+            }
+          }
+        }
+
+        write("\n", 1);
+        lastColumnLineWrapper.flush(write);
+        interjectionLineWrapper.flush(write);
+      }
+    }
+  }
+
+}
+;
+
+/**
+ * @brief Outputs a nicely formatted usage string with support for multi-column formatting
+ * and line-wrapping.
+ *
+ * printUsage() takes the @c help texts of a Descriptor[] array and formats them into
+ * a usage message, wrapping lines to achieve the desired output width.
+ *
+ * <b>Table formatting:</b>
+ *
+ * Aside from plain strings which are simply line-wrapped, the usage may contain tables. Tables
+ * are used to align elements in the output.
+ *
+ * @code
+ * // Without a table. The explanatory texts are not aligned.
+ * -c, --create  |Creates something.
+ * -k, --kill  |Destroys something.
+ *
+ * // With table formatting. The explanatory texts are aligned.
+ * -c, --create  |Creates something.
+ * -k, --kill    |Destroys something.
+ * @endcode
+ *
+ * Table formatting removes the need to pad help texts manually with spaces to achieve
+ * alignment. To create a table, simply insert \\t (tab) characters to separate the cells
+ * within a row.
+ *
+ * @code
+ * const option::Descriptor usage[] = {
+ * {..., "-c, --create  \tCreates something." },
+ * {..., "-k, --kill  \tDestroys something." }, ...
+ * @endcode
+ *
+ * Note that you must include the minimum amount of space desired between cells yourself.
+ * Table formatting will insert further spaces as needed to achieve alignment.
+ *
+ * You can insert line breaks within cells by using \\v (vertical tab).
+ *
+ * @code
+ * const option::Descriptor usage[] = {
+ * {..., "-c,\v--create  \tCreates\vsomething." },
+ * {..., "-k,\v--kill  \tDestroys\vsomething." }, ...
+ *
+ * // results in
+ *
+ * -c,       Creates
+ * --create  something.
+ * -k,       Destroys
+ * --kill    something.
+ * @endcode
+ *
+ * You can mix lines that do not use \\t or \\v with those that do. The plain
+ * lines will not mess up the table layout. Alignment of the table columns will
+ * be maintained even across these interjections.
+ *
+ * @code
+ * const option::Descriptor usage[] = {
+ * {..., "-c, --create  \tCreates something." },
+ * {..., "----------------------------------" },
+ * {..., "-k, --kill  \tDestroys something." }, ...
+ *
+ * // results in
+ *
+ * -c, --create  Creates something.
+ * ----------------------------------
+ * -k, --kill    Destroys something.
+ * @endcode
+ *
+ * You can have multiple tables within the same usage whose columns are
+ * aligned independently. Simply insert a dummy Descriptor with @c help==0.
+ *
+ * @code
+ * const option::Descriptor usage[] = {
+ * {..., "Long options:" },
+ * {..., "--very-long-option  \tDoes something long." },
+ * {..., "--ultra-super-mega-long-option  \tTakes forever to complete." },
+ * {..., 0 }, // ---------- table break -----------
+ * {..., "Short options:" },
+ * {..., "-s  \tShort." },
+ * {..., "-q  \tQuick." }, ...
+ *
+ * // results in
+ *
+ * Long options:
+ * --very-long-option              Does something long.
+ * --ultra-super-mega-long-option  Takes forever to complete.
+ * Short options:
+ * -s  Short.
+ * -q  Quick.
+ *
+ * // Without the table break it would be
+ *
+ * Long options:
+ * --very-long-option              Does something long.
+ * --ultra-super-mega-long-option  Takes forever to complete.
+ * Short options:
+ * -s                              Short.
+ * -q                              Quick.
+ * @endcode
+ *
+ * <b>Output methods:</b>
+ *
+ * Because TheLeanMeanC++Option parser is freestanding, you have to provide the means for
+ * output in the first argument(s) to printUsage(). Because printUsage() is implemented as
+ * a set of template functions, you have great flexibility in your choice of output
+ * method. The following example demonstrates typical uses. Anything that's similar enough
+ * will work.
+ *
+ * @code
+ * #include <unistd.h>  // write()
+ * #include <iostream>  // cout
+ * #include <sstream>   // ostringstream
+ * #include <cstdio>    // fwrite()
+ * using namespace std;
+ *
+ * void my_write(const char* str, int size) {
+ *   fwrite(str, size, 1, stdout);
+ * }
+ *
+ * struct MyWriter {
+ *   void write(const char* buf, size_t size) const {
+ *      fwrite(str, size, 1, stdout);
+ *   }
+ * };
+ *
+ * struct MyWriteFunctor {
+ *   void operator()(const char* buf, size_t size) {
+ *      fwrite(str, size, 1, stdout);
+ *   }
+ * };
+ * ...
+ * printUsage(my_write, usage);    // custom write function
+ * printUsage(MyWriter(), usage);  // temporary of a custom class
+ * MyWriter writer;
+ * printUsage(writer, usage);      // custom class object
+ * MyWriteFunctor wfunctor;
+ * printUsage(&wfunctor, usage);   // custom functor
+ * printUsage(write, 1, usage);    // write() to file descriptor 1
+ * printUsage(cout, usage);        // an ostream&
+ * printUsage(fwrite, stdout, usage);  // fwrite() to stdout
+ * ostringstream sstr;
+ * printUsage(sstr, usage);        // an ostringstream&
+ *
+ * @endcode
+ *
+ * @par Notes:
+ * @li the @c write() method of a class that is to be passed as a temporary
+ *     as @c MyWriter() is in the example, must be a @c const method, because
+ *     temporary objects are passed as const reference. This only applies to
+ *     temporary objects that are created and destroyed in the same statement.
+ *     If you create an object like @c writer in the example, this restriction
+ *     does not apply.
+ * @li a functor like @c MyWriteFunctor in the example must be passed as a pointer.
+ *     This differs from the way functors are passed to e.g. the STL algorithms.
+ * @li All printUsage() templates are tiny wrappers around a shared non-template implementation.
+ *     So there's no penalty for using different versions in the same program.
+ * @li printUsage() always interprets Descriptor::help as UTF-8 and always produces UTF-8-encoded
+ *     output. If your system uses a different charset, you must do your own conversion. You
+ *     may also need to change the font of the console to see non-ASCII characters properly.
+ *     This is particularly true for Windows.
+ * @li @b Security @b warning: Do not insert untrusted strings (such as user-supplied arguments)
+ *     into the usage. printUsage() has no protection against malicious UTF-8 sequences.
+ *
+ * @param prn The output method to use. See the examples above.
+ * @param usage the Descriptor[] array whose @c help texts will be formatted.
+ * @param width the maximum number of characters per output line. Note that this number is
+ *        in actual characters, not bytes. printUsage() supports UTF-8 in @c help and will
+ *        count multi-byte UTF-8 sequences properly. Asian wide characters are counted
+ *        as 2 characters.
+ * @param last_column_min_percent (0-100) The minimum percentage of @c width that should be available
+ *        for the last column (which typically contains the textual explanation of an option).
+ *        If less space is available, the last column will be printed on its own line, indented
+ *        according to @c last_column_own_line_max_percent.
+ * @param last_column_own_line_max_percent (0-100) If the last column is printed on its own line due to
+ *        less than @c last_column_min_percent of the width being available, then only
+ *        @c last_column_own_line_max_percent of the extra line(s) will be used for the
+ *        last column's text. This ensures an indentation. See example below.
+ *
+ * @code
+ * // width=20, last_column_min_percent=50 (i.e. last col. min. width=10)
+ * --3456789 1234567890
+ *           1234567890
+ *
+ * // width=20, last_column_min_percent=75 (i.e. last col. min. width=15)
+ * // last_column_own_line_max_percent=75
+ * --3456789
+ *      123456789012345
+ *      67890
+ *
+ * // width=20, last_column_min_percent=75 (i.e. last col. min. width=15)
+ * // last_column_own_line_max_percent=33 (i.e. max. 5)
+ * --3456789
+ *                12345
+ *                67890
+ *                12345
+ *                67890
+ * @endcode
+ */
+template<typename OStream>
+void printUsage(OStream& prn, const Descriptor usage[], int width = 80, int last_column_min_percent = 50,
+                int last_column_own_line_max_percent = 75)
+{
+  PrintUsageImplementation::OStreamWriter<OStream> write(prn);
+  PrintUsageImplementation::printUsage(write, usage, width, last_column_min_percent, last_column_own_line_max_percent);
+}
+
+template<typename Function>
+void printUsage(Function* prn, const Descriptor usage[], int width = 80, int last_column_min_percent = 50,
+                int last_column_own_line_max_percent = 75)
+{
+  PrintUsageImplementation::FunctionWriter<Function> write(prn);
+  PrintUsageImplementation::printUsage(write, usage, width, last_column_min_percent, last_column_own_line_max_percent);
+}
+
+template<typename Temporary>
+void printUsage(const Temporary& prn, const Descriptor usage[], int width = 80, int last_column_min_percent = 50,
+                int last_column_own_line_max_percent = 75)
+{
+  PrintUsageImplementation::TemporaryWriter<Temporary> write(prn);
+  PrintUsageImplementation::printUsage(write, usage, width, last_column_min_percent, last_column_own_line_max_percent);
+}
+
+template<typename Syscall>
+void printUsage(Syscall* prn, int fd, const Descriptor usage[], int width = 80, int last_column_min_percent = 50,
+                int last_column_own_line_max_percent = 75)
+{
+  PrintUsageImplementation::SyscallWriter<Syscall> write(prn, fd);
+  PrintUsageImplementation::printUsage(write, usage, width, last_column_min_percent, last_column_own_line_max_percent);
+}
+
+template<typename Function, typename Stream>
+void printUsage(Function* prn, Stream* stream, const Descriptor usage[], int width = 80, int last_column_min_percent =
+                    50,
+                int last_column_own_line_max_percent = 75)
+{
+  PrintUsageImplementation::StreamWriter<Function, Stream> write(prn, stream);
+  PrintUsageImplementation::printUsage(write, usage, width, last_column_min_percent, last_column_own_line_max_percent);
+}
+
+}
+// namespace option
+
+#endif /* OPTIONPARSER_H_ */
diff --git a/pasn1/parser.i b/pasn1/parser.i
new file mode 100644 (file)
index 0000000..52fdbfa
--- /dev/null
@@ -0,0 +1,47 @@
+
+%module pasn1
+%{
+#include "asn1_parser.h"
+%}
+
+%include <std_vector.i>
+%include <std_list.i>
+
+namespace ans1 {
+
+/* 
+%rename(ASN1Parser) parser
+%nodefaultctor
+*/
+class module ;
+
+
+class parser
+{
+  public:  
+    typedef std::vector<asn1::module *> modules_type;
+
+    typedef std::vector<asn1::module *>::iterator iterator;
+
+    typedef std::list<asn1::parser_listener *> listener_list;
+
+    typedef std::list<std::string>        string_list;
+
+    modules_type &modules() { return m_modules;};
+    
+    static parser *instance();
+    
+    inline string_list &includes();
+    
+    inline string_list &files(); 
+    
+    inline bool         file_mode();
+
+    inline void set_file_mode(bool fm);
+    
+    private:
+      parser();
+};
+
+
+}
diff --git a/pkix/CMakeLists.txt b/pkix/CMakeLists.txt
new file mode 100644 (file)
index 0000000..192e828
--- /dev/null
@@ -0,0 +1,35 @@
+PROJECT(test-pkix)
+# Libraries first
+
+INCLUDE(${rules_SOURCE_DIR}/flex.cmake)
+
+
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils)
+
+SET(PKIX  PKIX1Explicit88)
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT 
+      ${CMAKE_CURRENT_BINARY_DIR}/PKIX1Explicit88.cpp
+      ${CMAKE_CURRENT_BINARY_DIR}/PKIX1Explicit88.h
+    COMMAND ${asn1p_EXE}
+    ARGS -I ${asn1-data-models_SOURCE_DIR}/
+         -d parser=8 
+         -d msg=1 
+         -f rfc3280-PKIX1Explicit88.asn1  
+         -oPKIX1Explicit88
+    DEPENDS ${asn1p_EXE}
+    COMMENT "Build PKIX1Explicit88.h and .cpp"
+    )
+
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${PKIX}.h GENERATED)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${PKIX}.cpp GENERATED)
+
+ADD_EXECUTABLE(pkix_test
+    main_pkix.cpp
+    ${CMAKE_CURRENT_BINARY_DIR}/${PKIX}.cpp
+    )
+TARGET_LINK_LIBRARIES(pkix_test asn1)
diff --git a/pkix/main_pkix.cpp b/pkix/main_pkix.cpp
new file mode 100644 (file)
index 0000000..5dfb804
--- /dev/null
@@ -0,0 +1,62 @@
+#include <iostream>
+#include <fstream>
+#include "rtasn1/asn1_config.h"
+#include "rtasn1/asn1.h"
+#include "PKIX1Explicit88.h"
+//#include "PKIX1Explicit88.cpp"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+using namespace PKIX1Explicit88;
+
+int main(int argc,char **argv)
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::Integer i(1);
+  PKIX1Explicit88::Certificate cert,read_cert;
+  PKIX1Explicit88::Name name(PKIX1Explicit88::Name::typeof_rdnSequence,MAKE_TAG(0,0,16));
+  AttributeTypeAndValue issuer_t;
+  PKIX1Explicit88::TBSCertificate tb;
+  issuer_t.type = id_domainComponent();
+  PKIX1Explicit88::AttributeTypeAndValue issuer = issuer_t;
+  RelativeDistinguishedName rdn= issuer;
+  asn1::PrintableString str(asn1::prim::types::String("Andre EBERSOLD "));
+  PDSParameter pd;
+  pd.printable_string = str;
+  
+  OBJECT_IDENTIFIER pk = pkcs_9();
+  //name.get_rdnSequence() = rdn;
+  name.get_rdnSequence().push_back(rdn);
+  std::cout<<"Hello world"<<std::endl;
+  tb.version = i;
+  tb.serialNumber = 123;
+  tb.issuer = name;
+  std::cout<<"Set Version="<<tb.version<<std::endl;
+  cert.tbsCertificate = PKIX1Explicit88::TBSCertificate(tb);
+  cert.signature[0] = 0x23;
+  PKIX1Explicit88::Certificate certs = PKIX1Explicit88::Certificate(cert);
+  //certs.codec(ctx,certs ,asn1::CODEC_ENCODE);
+  certs.encode(ctx);
+  std::cout<<"-- pkcs-9 is :"<<pk<<std::endl;
+  if (argc > 1)
+  {
+    std::cout<<"Try to read file given as parameter : "<<argv[1]<<std::endl;
+    std::ifstream pkix_file;
+    pkix_file.open(argv[1]);
+    pkix_file.seekg(0,std::ios::end);
+    int len = pkix_file.tellg();
+    pkix_file.seekg(0,std::ios::beg);
+    unsigned char *b = (unsigned char *)malloc(len+1);
+    pkix_file.read((char *)b,len);
+    asn1::streams::ber cr(b,len);
+    //asn1::context cr(b,len);
+
+    asn1::types::debug_level = 7;
+    int result = read_cert.decode(cr);
+    std::cout<<"See how it looks like "<<result<<": "<<std::endl;
+    std::cout<<read_cert<<std::endl;;
+    pkix_file.close();
+  }
+}
diff --git a/pkix/result.txt b/pkix/result.txt
new file mode 100644 (file)
index 0000000..a399e1a
--- /dev/null
@@ -0,0 +1,226 @@
+<Certificate>
+    <tbsCertificate>
+        <version>2</version>
+        <serialNumber>44:BE:0C:8B:50:00:24:B4:11:D3:36:30:4B:C0:33:77</serialNumber>
+        <signature>
+            <algorithm>1.2.840.113549.1.1.5</algorithm>
+            <parameters>05 00</parameters>
+        </signature>
+        <issuer>
+            <rdnSequence>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.6</type>
+                        <value>13 02 55 53</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.8</type>
+                        <value>13 02 55 54</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.7</type>
+                        <value>13 0E 53 61 6C 74 20 4C 61 6B 65 20 43 69 74 79</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.10</type>
+                        <value>
+                            13 15 54 68 65 20 55 53 45 52 54 52 55 53 54 20
+                            4E 65 74 77 6F 72 6B
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.11</type>
+                        <value>
+                            13 18 68 74 74 70 3A 2F 2F 77 77 77 2E 75 73 65
+                            72 74 72 75 73 74 2E 63 6F 6D
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.3</type>
+                        <value>
+                            13 22 55 54 4E 2D 55 53 45 52 46 69 72 73 74 2D
+                            4E 65 74 77 6F 72 6B 20 41 70 70 6C 69 63 61 74
+                            69 6F 6E 73
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+            </rdnSequence>
+        </issuer>
+        <validity>
+            <notBefore>
+                <utcTime>990709184839Z</utcTime>
+            </notBefore>
+            <notAfter>
+                <utcTime>190709185749Z</utcTime>
+            </notAfter>
+        </validity>
+        <subject>
+            <rdnSequence>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.6</type>
+                        <value>13 02 55 53</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.8</type>
+                        <value>13 02 55 54</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.7</type>
+                        <value>13 0E 53 61 6C 74 20 4C 61 6B 65 20 43 69 74 79</value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.10</type>
+                        <value>
+                            13 15 54 68 65 20 55 53 45 52 54 52 55 53 54 20
+                            4E 65 74 77 6F 72 6B
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.11</type>
+                        <value>
+                            13 18 68 74 74 70 3A 2F 2F 77 77 77 2E 75 73 65
+                            72 74 72 75 73 74 2E 63 6F 6D
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+                <RelativeDistinguishedName>
+                    <AttributeTypeAndValue>
+                        <type>2.5.4.3</type>
+                        <value>
+                            13 22 55 54 4E 2D 55 53 45 52 46 69 72 73 74 2D
+                            4E 65 74 77 6F 72 6B 20 41 70 70 6C 69 63 61 74
+                            69 6F 6E 73
+                        </value>
+                    </AttributeTypeAndValue>
+                </RelativeDistinguishedName>
+            </rdnSequence>
+        </subject>
+        <subjectPublicKeyInfo>
+            <algorithm>
+                <algorithm>1.2.840.113549.1.1.1</algorithm>
+                <parameters>05 00</parameters>
+            </algorithm>
+            <subjectPublicKey>
+                0011000010000010000000010000101000000010100000100000000100000001
+                0000000010110011111110111001000110100001111001000011011001010101
+                1000010110101100000001100011010001011011101000001001101001011000
+                1011001011111000101101010000111100000101011101111000001110101110
+                0011001010110001011101101001001001101000111011000010001101001010
+                1100100101110110001111111110001110011100101101100011011101111001
+                0000001110111001101010110110100110001101000001110010010110110110
+                0001100101100111111001001011000000011011000110000111001101100001
+                0100101011101000011111101100110111010011001011110110010011100011
+                1010011001111100000011001111101000010111100000001010001100001101
+                0100011110001001010011110101000101110001001011111110111011111100
+                0011111111111001101110000001011010000000100001111000100110010011
+                0010010100100000100110100100001110000010011010010010010001110110
+                0010100001011001001101011010000100011101110000000111111110000011
+                0000011001100100000101100010000000101100110100110100100110100100
+                1000010110110100110000000110000101111111010100010000100011111000
+                0110100000010101100100011000000011001011101001011101010111101110
+                0011101100111010111101001000010000000100010111100110000001011001
+                1010011110001100001101000111001011101110101110000111100011000101
+                1101000100111011000100100100101001101111011111100110010100100111
+                1011100110100100010101011100010110111001011011110100001110100100
+                1100010100011101001011001001100111000000010100101010010001111000
+                0100110000010101101100110100000010011000000010000110101101000011
+                1100011000000001101100000111101001111011111101010110101100011100
+                0010001000111111110010111110111111111111101010001101000000111010
+                0100101101110110000101011001111011010010110100011100011000101110
+                1110001111011011010101110001101100110010101000101011100001101111
+                1110100010000110101001100011111101110000101010111110010101110000
+                1001001010101011010001000001111001000000010100001111101110011100
+                1010001101100010111001000110110001101110101000001100100011011110
+                1110001010000000010000101111101011101001001011111110100011001110
+                0011001000000100100011110111110010001101101101110001110010100011
+                0011010100111100000101011101110110011110110000111010111010010111
+                101001010000001000000011000000010000000000000001
+            </subjectPublicKey>
+        </subjectPublicKeyInfo>
+        <extensions>
+            <Extension>
+                <extnID>2.5.29.15</extnID>
+                <extnValue>03 02 01 C6</extnValue>
+            </Extension>
+            <Extension>
+                <extnID>2.5.29.19</extnID>
+                <critical><true/></critical>
+                <extnValue>30 03 01 01 FF</extnValue>
+            </Extension>
+            <Extension>
+                <extnID>2.5.29.14</extnID>
+                <extnValue>
+                    04 14 FA 86 C9 DB E0 BA E9 78 F5 4B A8 D6 15 DF
+                    F0 D3 E1 6A 14 3C
+                </extnValue>
+            </Extension>
+            <Extension>
+                <extnID>2.5.29.31</extnID>
+                <extnValue>
+                    30 46 30 44 A0 42 A0 40 86 3E 68 74 74 70 3A 2F
+                    2F 63 72 6C 2E 75 73 65 72 74 72 75 73 74 2E 63
+                    6F 6D 2F 55 54 4E 2D 55 53 45 52 46 69 72 73 74
+                    2D 4E 65 74 77 6F 72 6B 41 70 70 6C 69 63 61 74
+                    69 6F 6E 73 2E 63 72 6C
+                </extnValue>
+            </Extension>
+        </extensions>
+    </tbsCertificate>
+    <signatureAlgorithm>
+        <algorithm>1.2.840.113549.1.1.5</algorithm>
+        <parameters>05 00</parameters>
+    </signatureAlgorithm>
+    <signature>
+        1010010011110011001001011100110011010001110101001001000110000011
+        0010001011010000110011000011001010101011100110111001011001001110
+        0011010010010001010101000010000000100101001101000110000101011111
+        0010101000000010000101011110000110001011101010101111111101111101
+        0110010001010001110011110000101011111111101111000111110111011000
+        0010000101101010011110001100101100101111010100010110111111111000
+        0100001000011101001100111011110111101011101101010111101110010100
+        1100001111000011101010011010000000101101110111111101000100101001
+        0001111100011101111111101000111100111111101110111010100001000101
+        0010101001111111110100010110111001010101001001001110001010111011
+        0000001011111011001100010011111110111110111010001011110011101100
+        0100000000101011111110000000000111010100010101100011100011100100
+        1100101001000100100000101011010101100001001000000010000101100111
+        0110010111110110111100000000101111100111001101001111100010100101
+        1100001010011100101000110101110001000000000111111000010110010011
+        1001010100000110110111100100111111010100001001111010100110110110
+        1010010111111100000101101100110101110011001100010011111110111000
+        0110010100100111110011111101010001010011000110101111000010101100
+        0110111010011111010011110000010100001100000000111000000110100111
+        1000010000101001110001000101101010111101011001000101011101110010
+        1010110100111011110011110011011100011000101001101001100011000110
+        1010110100000110101101001101110000001000101000110000010011010101
+        0010100110100100100101101001101000010010011001110100101010001100
+        0110000001000101100111011111000100100011100110101011000000000000
+        1001110001101000101101011001100001010000110100111110111110001110
+        0010111010010010011001011011000101001000001111100010000110111110
+        0001010100110000001010100000110110110101000011001010001101101011
+        0011111110101110011111110101011111110101000111111001011001111100
+        1101111101101111110111011000001000110000001011000110010100011011
+        0100000001001010110011010110100010111001011100101110110001110001
+        0111011011101100010101001000111000011111100001010000110000000001
+        0110101011111010101001100011100010101100000111111100010010000100
+    </signature>
+</Certificate>
diff --git a/pkix/sample-Certificate-1.der b/pkix/sample-Certificate-1.der
new file mode 100644 (file)
index 0000000..e82877d
Binary files /dev/null and b/pkix/sample-Certificate-1.der differ
diff --git a/rtasn1/CMakeLists.txt b/rtasn1/CMakeLists.txt
new file mode 100644 (file)
index 0000000..340d926
--- /dev/null
@@ -0,0 +1,71 @@
+PROJECT(libasn1)
+SUBDIRS(cpp)
+
+CONFIGURE_FILE(asn1_config.h.in asn1_config.h)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/asn1_config.h GENERATED)
+
+ADD_LIBRARY(asn1
+    asn1_context.cpp
+    asn1_codec_ber.cpp
+    asn1_codec_jer.cpp
+    asn1_codec_oer.cpp
+    asn1_codec_per.cpp
+    prim_types.cpp
+    asn1_types.cpp
+    cpp/prim_oid.cpp
+    cjson/cJSON.c
+    )
+#
+#  Install stuff
+#
+IF(APPLE)
+  INSTALL(TARGETS asn1 
+    COMPONENT RuntimeLibraries
+    LIBRARY DESTINATION Smartasn1.app/Contents/lib/
+    ARCHIVE DESTINATION Smartasn1.app/Contents/lib/
+  )
+  INSTALL(FILES 
+    asn1.h
+    ${CMAKE_CURRENT_BINARY_DIR}/asn1_config.h
+    asn1_types.h
+    asn1_context.h
+    asn1_errors.h
+    asn1_codec.h
+    asn1_tag.h
+    prim_types.h
+    asn1_types.inc
+    asn1_rose.h
+    asn1_types.hpp  
+    asn1_codec_ber.h
+    asn1_codec_jer.h
+    asn1_codec_oer.h
+    asn1_codec_per.h
+    asn1_debug.h
+    COMPONENT Asn1Headers
+    DESTINATION Smartasn1.app/Contents/include/asn1/)
+ELSE(APPLE)
+  INSTALL(TARGETS asn1 
+    COMPONENT RuntimeLibraries
+    LIBRARY DESTINATION lib/
+    ARCHIVE DESTINATION lib/
+  )
+  INSTALL(FILES 
+    asn1.h
+    asn1_types.h
+    asn1_types.inc
+    asn1_context.h
+    asn1_errors.h
+    asn1_codec.h
+    asn1_tag.h
+    prim_types.h
+    asn1_rose.h
+    asn1_types.hpp  
+    asn1_codec_ber.h
+    asn1_codec_jer.h
+    asn1_codec_oer.h
+    asn1_codec_per.h
+    asn1_debug.h
+    COMPONENT Asn1Headers
+    DESTINATION include/asn1/)
+
+ENDIF(APPLE)
diff --git a/rtasn1/asn1.h b/rtasn1/asn1.h
new file mode 100644 (file)
index 0000000..a582a3c
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef ASN1_H__
+#define ASN1_H__
+
+#include "rtasn1/asn1_config.h"
+#include "rtasn1/asn1_debug.h"
+#include "rtasn1/asn1_errors.h"
+#include "rtasn1/asn1_tag.h"
+#include "rtasn1/prim_types.h"
+namespace asn1 { class context; };
+namespace asn1 { namespace streams { class ber;} };
+#include "rtasn1/asn1_types.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_context.h"
+#include "rtasn1/asn1_rose.h"
+#include "rtasn1/asn1_types.hpp"
+#include <typeinfo>
+#if defined(__GNUC__) ||defined(_WIN32)
+#include <bitset>
+#endif
+
+#if defined (ASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER)
+// ASN1_OPTIONAL_AS_SHARED_POINTER
+#  define  ASN1_ATTRIBUTE_OPTIONAL(x) asn1::intrusive_ptr<x >
+
+#  define  ASN1_ATTRIBUTE_OPTIONAL_ENCODE(x) do { \
+               if( !(x.is_nul() ) ) { \
+                 (x)->encode(ctx); \
+               }  \
+          } while (0)
+
+#  define  ASN1_ATTRIBUTE_OPTIONAL_DECODE(x) do { \
+               if(  ! x.is_nul() ) { \
+                 x->decode(ctx); \
+               } else { \
+                 x.create(); \
+           if (x->decode(ctx) != asn1::ok) { \
+         x.release(); \
+      }\
+               } \
+          } while(0)
+
+#  define  ASN1_ATTRIBUTE_OPTIONAL_DECODE_IMPLICIT(x,tg) do { \
+               if(  ! c.x.is_nul() ) { \
+                  c.x->set_tag(tg); \
+                 if (c.x->decode(ctx) != asn1::ok) { \
+                    c.x.release(); \
+                  }\
+               } else { \
+                 c.x.create(tg); \
+                 if (c.x->decode(ctx) != asn1::ok) { \
+                   c.x.release(); \
+                  }\
+               } \
+          } while(0)
+
+
+#elif defined (ASN1_ATTRIBUTE_OPTIONA_AS_POINTER)
+// ASN1_OPTIONAL_AS_POINTER
+#  define  ASN1_ATTRIBUTE_OPTIONAL(x) x *
+#  define  ASN1_ATTRIBUTE_OPTIONAL_ENCODE(x) x
+#  define  ASN1_ATTRIBUTE_OPTIONAL_DECODE(x) x
+#else
+// ASN1_OPTIONAL_AS_NOT_SUPPORTED
+#  define  ASN1_ATTRIBUTE_OPTIONAL(x) x
+#  define  ASN1_ATTRIBUTE_OPTIONAL_ENCODE(x)  { \
+     x.encode(ctx); \
+   }
+#  define  ASN1_ATTRIBUTE_OPTIONAL_DECODE(x) do { \
+     x.decode(ctx); \
+   } while(0)
+
+#  define  ASN1_ATTRIBUTE_OPTIONAL_DECODE_IMPLICIT(x,tg) do { \
+     x.set_tag(tg);\
+     x.decode(ctx); \
+   } while(0)
+#endif
+
+namespace asn1 {
+namespace types {
+}
+}
+
+/*
+vim:et:sw=2:ts=2:
+ */
+#endif
diff --git a/rtasn1/asn1_codec.h b/rtasn1/asn1_codec.h
new file mode 100644 (file)
index 0000000..70e867c
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef ASN1_CODEC_H__
+#define ASN1_CODEC_H__
+#include <string.h>
+#include "rtasn1/asn1.h"
+namespace asn1 {
+  namespace types {
+    extern int debug_level;
+  }
+  namespace codecs {
+    class ber;
+  }
+};
+
+//
+namespace asn1
+{
+
+    
+class context_base;
+
+/**
+ *
+ * @brief Base class to Implement encode and docode 
+ * functions related to ASN1 types.
+ * 
+ * put in this class methods that are common to all
+ * type of encoders / decoders BER,JER,OER,PER,XER
+ * Eventual parameters, allocator 
+ */ 
+  class codec
+  {
+    public:
+      codec( ) {};
+  };
+
+};
+#endif
+/*
+ * vim: et sw=2 ts=2 list:
+ */ 
diff --git a/rtasn1/asn1_codec_ber.cpp b/rtasn1/asn1_codec_ber.cpp
new file mode 100644 (file)
index 0000000..63c10f3
--- /dev/null
@@ -0,0 +1,1126 @@
+#include <iostream>
+#include <string>
+#include <typeinfo>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_context.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+/*
+vim:et:sw=2:ts=2
+ */
+namespace asn1 {
+
+
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)                 \
+      template <>                                                       \
+      void codecBER::encode(streams::ber &ctx, const asn1::Asn1Type &t) \
+      {                                                                 \
+         encode_ber(ctx,t);                                             \
+      }                                                                 \
+      template <>                                                       \
+      int                                                               \
+      codecBER::decode(streams::ber &ctx, asn1::Asn1Type &t)            \
+      {                                                                 \
+         return decode_ber(ctx,t);                                      \
+      }
+
+ASN1_TYPE_CLS(asn1::prim::types::ObjectIdentifier,asn1::types::UNIVERSAL,6,ObjectIdentifier)
+
+#include "rtasn1/asn1_types.inc"
+
+# if 0
+         std::cerr<<"codecBER::"<<__FUNCTION__<<"  good ";              \
+         std::cerr<<#Asn1Type<<std::endl;                               \
+         std::cerr<<"codecBER::"<<__FUNCTION__<<" good ";               \
+         std::cerr<<#Asn1Type<<std::endl;                               \
+
+#endif
+
+
+
+/**
+ * Why not providing the real implementation directly.
+ * I could save an inderection between the template function
+ * and the code.
+ *
+ */
+#define ASN1_CODEC_IMPL(Type,Encode,Decode) \
+void codecBER::encode_ber(streams::ber &ctx,const asn1::Type &t) \
+Encode \
+int codecBER::decode_ber(streams::ber &ctx,asn1::Type &t) \
+Decode
+       
+ASN1_CODEC_IMPL(BOOLEAN,
+{
+  ctx.encode_boolean(t);
+},
+{
+  return ctx.decode_boolean(t);
+})
+ASN1_CODEC_IMPL(INTEGER,
+{
+  ctx.encode_integer(t);
+},
+{
+  return  ctx.decode_integer(t);
+})
+ASN1_CODEC_IMPL(Int8,
+{
+  ctx.encode_integer(t);
+},
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  //return  ctx.decode_integer(t);
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int16,
+{
+  ctx.encode_integer(t);
+},
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  //return  ctx.decode_integer(t);
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int32,
+{
+  ctx.encode_integer(t);
+},
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  //return  ctx.decode_integer(t);
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int64,
+{
+  ctx.encode_integer(t);
+},
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  //return  ctx.decode_integer(t);
+  return asn1::ok;
+})
+
+
+ASN1_CODEC_IMPL(UInt8,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt16,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt32,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+ASN1_CODEC_IMPL(UInt64,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  ctx.encode_integer(t);
+},
+{
+  return ctx.decode_integer(t);
+  //return asn1::ok;
+})
+
+ASN1_CODEC_IMPL(BIT_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  ctx.encode_bitstring(t);
+},
+{
+  return ctx.decode_bitstring(t);
+})
+ASN1_CODEC_IMPL(OCTET_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Null,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#if 0
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#else
+ASN1_CODEC_IMPL(ObjectIdentifier,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER_NG,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#endif
+ASN1_CODEC_IMPL(EXTERNAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralizedTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UTCTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(REAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(ENUMERATED,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+// typedef asn1::types::any_type ANY;
+ASN1_CODEC_IMPL(UTF8String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(NumericString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(PrintableString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(TeletexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VideotexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(IA5String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+  ctx.encode_string(t);
+},
+{
+  return ctx.decode_string(t);
+})
+ASN1_CODEC_IMPL(GraphicString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VisibleString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UniversalString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(BMPString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+
+
+//
+void 
+codecBER::encode_header(streams::ber &ctx,const asn1::types::type &obj,const size_t len)
+{
+  asn1::tag       t(obj.tag());
+  unsigned long pos      = ctx.bytes();
+  unsigned char *b       = ctx.buffer();
+  size_t         i       = 0;
+  long         required = 1;
+
+  ASN1_BER_LOG_DEBUG("codecBER::encode_header code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+  b[pos] = ((t.get_class() & 0x03)<<6 )| ( (t.get_id() < 31) ? t.get_id() : 0x1F);
+  if ( ! obj.primitive() ) 
+    b[pos] |= 0x20;
+  long tgv = t.get_id();
+
+  if ( t.get_id() > 31 )
+  {
+    //required = (types::count_bits(tgv) + 6 ) / 7 ;
+    // Compute required size for id > 31
+    for ( required = 1, i = 7 ; i < sizeof(long) * 8 ; i+=7)
+    {
+      if (t.get_id() >> i )
+      {
+        required++;
+      } else
+        break;
+    }
+  // Encode id ...
+    unsigned char * end = b + required  ;
+    for ( i-= 7, ++pos;  &b[pos] < end; i-=7 , pos++)
+    {
+      b[pos] = 0x80 | (( tgv >> i) & 0x7F);
+    }
+    b[pos] =  (( tgv >> i) & 0x7F);
+    required++;
+  }
+
+  // Get Length of underlying data objects length, and encode length. 
+  size_t data_len = obj.get_data_length();
+  ASN1_BER_LOG_DEBUG("codecBER::encode_header data_length = %ld len=%ld",data_len,len);
+  if (data_len < 128)
+  {  // Don't know how to do this for now 
+    b[++pos] = data_len;
+    ctx.nb_bits(8 + ((required)<<3));
+  } else
+  {
+    int count = (types::count_bits(data_len +1)+7)/8;
+    b[++pos] = count | 0x80;
+    while (count-- > 0)
+    { 
+      b[++pos] = (len >> (count+8));
+    }
+  }
+}
+//
+void 
+codecBER::encode_tag(streams::ber &ctx,const asn1::tag &t,const size_t data_len)
+{
+  unsigned long pos      = ctx.bytes();
+  unsigned char *b       = ctx.buffer();
+  size_t         i       = 0;
+  long         required = 1;
+
+  ASN1_BER_LOG_DEBUG("ber::encode_tag code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+  b[pos] = ((t.get_class() & 0x03)<<6 )| ( (t.get_id() < 31) ? t.get_id() : 0x1F);
+  if (  t.get_constructed() ) 
+    b[pos] |= 0x20;
+  long tgv = t.get_id();
+
+  if ( t.get_id() > 31 )
+  {
+    //required = (types::count_bits(tgv) + 6 ) / 7 ;
+    // Compute required size for id > 31
+    for ( required = 1, i = 7 ; i < sizeof(long) * 8 ; i+=7)
+    {
+      if (t.get_id() >> i )
+      {
+        required++;
+      } else
+        break;
+    }
+  // Encode id ...
+    unsigned char * end = b + required  ;
+    for ( i-= 7, ++pos;  &b[pos] < end; i-=7 , pos++)
+    {
+      b[pos] = 0x80 | (( tgv >> i) & 0x7F);
+    }
+    b[pos] =  (( tgv >> i) & 0x7F);
+    required++;
+  }
+
+  // Get Length of underlying data objects length, and encode length. 
+  ASN1_BER_LOG_DEBUG("ber::encode_header data_length = %ld ",data_len);
+  if (data_len < 128)
+  {  // Don't know how to do this for now 
+    b[++pos] = data_len;
+    ctx.nb_bits(8 + ((required)<<3));
+  } else
+  {
+    int count = (types::count_bits(data_len +1)+7)/8;
+    b[++pos] = count | 0x80;
+    while (count-- > 0)
+    { 
+      b[++pos] = (data_len >> (count+8));
+    }
+  }
+}
+    
+
+
+
+namespace streams {
+
+
+
+ber::ber(int sz) : asn1::context(sz)
+{
+  ASN1_BER_LOG_DEBUG("ber::ber  %d ",sz);
+}
+
+ber::ber(const ber &_codec) : asn1::context()
+{
+  ASN1_BER_LOG_DEBUG("ber::ber(const ber &_codec )  ");
+}
+
+long ber::decode_length(unsigned char *buf, long *readed)
+{
+  long result = 0;
+  long nb_octet =  *buf & 0x7f;
+
+  *readed = 1;
+  if ((*buf & 0x80) && (*buf & 0x7F)) {
+      // Long form number ...
+      *readed = (*buf & 0x7F) + 1;
+      buf++;
+      while (nb_octet-- ) {
+        result = (result<<8) | (*buf);
+        buf++;
+      }
+      ASN1_BER_LOG_DEBUG("asn1::codec::ber::length  long form value=%ld readed=%ld",result,*readed);
+      return result;
+  } else if (!(*buf & 0x80) && (*buf & 0x7F)){
+      result = *buf & 0x7F;
+      // Short one byte
+      *readed = 1;
+      ASN1_BER_LOG_DEBUG("ans1::codec::ber::length short form result=%ld ",result);
+      return result;
+  } else if (*buf == 0) {
+      *readed = 1;
+      ASN1_BER_LOG_DEBUG("ber::length: 0 ");
+      return 0;
+  }else {
+      // Indefinit form
+      std::cout<<"ber::length indefinit form not yet supported  TO BE CODED"<<std::endl;
+  }
+  return 0;
+}
+
+void
+ber::encode_byte(unsigned char c)
+{
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  nb_bits(8);
+  b[pos] = c;
+}
+
+unsigned char 
+ber::decode_byte()
+{
+  unsigned long pos = bytes();
+  nb_bits(8);
+  return buffer()[pos] ;
+}
+
+
+// Null
+// 5
+void ber::encode_null(const asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::encode Null tag=%d  ",b.tag().byte());
+  encode_header(b,len);
+}
+
+int ber::decode_null(asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::decode Null  ");
+  if (decode_header(b.tag(),len)) {
+    return asn1::ok;
+  } else
+    return asn1::unknown;
+}
+
+
+// Bool
+//
+void ber::encode_boolean(const asn1::BOOLEAN &b) 
+{
+  int len = 1;
+  ASN1_BER_LOG_DEBUG("ber::encode boolean tag=%d",b.tag().byte());
+  encode_header(b,len);
+  encode_byte((b == true)?0xFF:0x00);
+}
+
+int ber::decode_boolean(asn1::BOOLEAN &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::decode boolean tag=%d",b.tag().byte());
+  if (decode_header(b.tag(),len))
+  {
+    unsigned long pos = bytes();
+    unsigned char *bu = buffer();
+    nb_bits(1<<3);
+    b.get_value() = bu[pos];
+    return asn1::ok;
+  } else
+    return asn1::unknown;
+}
+
+
+/**
+ * Integer
+ * \brief this function needs to be reviewed in one way or another.
+ * I just wont use rtti to guess the caller.
+ */
+void ber::encode_integer(const asn1::types::type &b) 
+{
+  int len = 0;
+  long long integer = 0;
+  if (const INTEGER *i = dynamic_cast< const INTEGER *>(&b))
+  { 
+     integer = i->get_sys_value();
+  } else if (const UInt64 *i = dynamic_cast< const UInt64 *>(&b))
+  {
+     integer = i->get_sys_value();
+  } else if (const ENUMERATED *i = dynamic_cast< const ENUMERATED *>(&b))
+  {
+     integer = i->get_sys_value();
+  }
+  int intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+  
+  while ( ( ((integer & mask) == 0) || ((integer & mask) == mask)) 
+    && intsize > 1) {
+    intsize--;
+    integer <<=8;
+  }
+  ASN1_BER_LOG_DEBUG("ber::encode integer tag.byte()=%d  value=%lld intsize=%d decale =%d"
+      ,b.tag().byte()
+      ,(long long)integer
+      ,(int)intsize
+      ,(intsize<<3));
+  
+  encode_header(b,intsize);
+  
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  
+  nb_bits(intsize<<3);
+  
+  
+  if ((integer & 0x7F000000)) {
+
+  }
+  while ( (intsize--) > 0) 
+  {
+    bu[pos++] = ( (integer & 0xFF000000)>>24 );
+    integer<<=8;
+  }
+}
+
+/**
+ * Decode Integer 
+ */
+int ber::decode_integer(asn1::INTEGER &t) 
+{
+  int len       = 0;
+  int result    = 0;
+  
+  ASN1_BER_LOG_DEBUG("ber::decode integer tag=%d",t.tag().byte());
+  
+  if ( ! decode_header(t.tag(),len) || ( len == 0 ))
+  {
+    ASN1_BER_LOG_DEBUG("ber::decode_integer WRONG TAG expected=%d",t.tag().byte());
+    return asn1::wrong_tag;
+  }
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  nb_bits(len<<3);
+  // I don't know yet how to handle this case
+  if (len> 16 )
+  {
+    ASN1_BER_LOG_ERROR("ber::decode_integer too long  len = %d",len);
+    return  asn1::wrong_length;
+  }
+
+  ASN1_BER_LOG_DEBUG("ber::decode_integer start result=%d check_tag=%d len =%d",(int)result,check_tag(),len);
+  result = (char) bu[pos]; /* Keep sign */
+  while (--len) 
+  {
+       result = (result<<8) | ((unsigned char)bu[++pos] & 0xFF);
+  }
+  ASN1_BER_LOG_DEBUG("ber::decode_integer end result=%d",(int)result);
+  t.get_value() = result;
+  return asn1::ok;
+}
+
+int ber::decode_integer(asn1::UInt64 &t)
+{
+  int len       = 0;
+  if (! decode_header(t.tag(),len) || (len == 0) )
+    return asn1::wrong_tag;
+  unsigned long acc = decode_byte(); /* No signess */
+  while (--len > 0)
+  {
+    acc = (acc<< 8) | decode_byte();
+  }
+  t = acc;
+  return asn1::ok;
+}
+
+
+// Bit String
+//
+void ber::encode_bitstring(const asn1::BIT_STRING &t) 
+{
+  int len = t.size() + 1;
+  ASN1_BER_LOG_DEBUG("ber::encode bit string len=%d blen=%lu"
+          ,len
+          ,t.get_nb_bits()
+          );
+  encode_header(t,len);
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  
+  if (t.size() > 0)
+  {
+    unsigned char last = t[t.size()-1];
+    unsigned char padding = 0;
+    unsigned char mask = 1;
+    
+    padding = t.get_nb_bits()  % 8;
+    
+    if (padding )
+    {
+      padding = 8 - padding;
+    } else 
+    { // Cannot be 0 there is a problem here
+      while (last)
+      {
+        padding++; last>>=1;
+        mask<<=1; mask |=1;
+      }
+      padding = 8 - padding;
+    }
+    bu[pos++] = padding;
+    len = t.size() - 1;
+    
+    nb_bits(((1+ t.size()) <<3));
+    while (len > 0)
+    {
+      bu[pos++] = t[len]<<padding | (t[len-1] & ~mask)>>(8-padding);
+      len--;
+    }
+    bu[pos] = t[0]<<padding;
+  } else 
+  {
+    bu[pos++] = 0;
+    nb_bits(8);
+  }
+}
+
+int ber::decode_bitstring(asn1::BIT_STRING &t) 
+{
+  ASN1_BER_LOG_DEBUG("ber::decode bit string tag=%d ",t.tag().byte());
+  int len = 0;
+  long nb=0;
+  if ( !decode_header(t.tag(),len) ) {
+    return asn1::wrong_tag;
+  } 
+
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  nb_bits((len<<3));
+  unsigned char padding = bu[pos++]; // add padding
+  std::cerr<<"decode_bitstrring padding "<<(int)padding;
+  std::cerr<<" len="<<len<<std::endl;
+  len --; //remove padding
+  t.set_nb_bits(len*8-padding);
+  if (padding)
+  {
+    nb++;
+  }
+  while ( (len ) > 1)
+  {
+    if (nb)
+    {
+      t[len-2] = (bu[pos]<<(8 - padding)) | (bu[pos + 1]>>padding);
+    } else
+      t[len-1] = bu[pos];
+    len--;pos++;
+  }
+  t[0] |= bu[pos]>>padding ;
+
+  return asn1::ok;
+}
+
+
+// Octet string
+//
+void ber::encode_octetstring(const asn1::OCTET_STRING &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::encode octet string tag=%d",b.tag().byte());
+  len = (b.get_value()).size(); // Length
+  
+  encode_header(b,len);
+   
+  unsigned long pos = bytes();
+  unsigned char *buf  = buffer();
+  
+  for ( int i = 0; i< len ; i++)
+       buf[pos++] =(b.get_value()).c_str()[i];
+  nb_bits(len*8);
+}
+
+int ber::decode_octetstring(asn1::OCTET_STRING &b_) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::decode octet string ");
+  if (decode_header(b_.tag(),len))
+  {
+    unsigned long pos = bytes();
+    unsigned char *b  = buffer();
+    std::string result;
+    result.assign((const char *)&b[pos],len);
+    
+    b_.get_value()= result;
+    nb_bits((len<<3));
+  } else {
+    return asn1::wrong_tag;
+  }
+  return asn1::ok;
+}
+
+void ber::encode_string(const asn1::types::strtype &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::encode string tag=%d",b.tag().get_id());
+  //const asn1::prim::types::String &s = dynamic_cast< const asn1::prim::types::String &>(b); 
+  const asn1::prim::types::String &s = b.get_prim(); 
+  len = s.get_value().size(); // Length
+  
+  encode_header(b,len);
+
+  unsigned long pos = bytes();
+  unsigned char *buf  = buffer();
+  
+  for ( int i = 0; i< len ; i++)
+       buf[pos++] = s.get_value().c_str()[i];
+  nb_bits(len*8);
+}
+
+
+int ber::decode_string(asn1::types::strtype &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::decode  string tag_id=%d",b.tag().get_id());
+  //asn1::prim::types::String &s = dynamic_cast<asn1::prim::types::String &>(b); 
+  asn1::prim::types::String &s = b.get_prim(); 
+  
+  if (decode_header(b.type::tag(),len))
+  {
+    unsigned long pos = bytes();
+    unsigned char *bu = buffer();
+    std::string result;
+    result.assign((const char *)&bu[pos],len);
+    s = asn1::prim::types::String(result);
+    nb_bits((len<<3));
+  } else {
+    return asn1::wrong_tag;
+  }
+  return asn1::ok;
+}
+
+// Any
+//
+void ber::encode_any(const asn1::types::any_type &b)
+{
+  ASN1_BER_LOG_DEBUG("ber::encode_any ");
+}
+
+int ber::decode_any(asn1::types::any_type &b)
+{
+  asn1::tag t(0,0);
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::decode_any ");
+  if (decode_tag(t,len))
+  {
+    nb_bits((len<<3));
+  }
+  std::cerr<<"ber::decode_any len="<<len<<std::endl;
+  return asn1::ok;
+}
+
+
+// Choice
+//
+void ber::encode_choice(asn1::types::choice_type &b) 
+{
+  int len = 0;
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  ASN1_BER_LOG_DEBUG("ber::encode_choice tag.byte=%d get_tag=%ld"
+                    ,b.tag().byte()
+                    ,b.tag().get_tag());
+  // Is This correct ?
+  bu[pos] = b.tag().byte();
+  b.encode_ber(*this);
+}
+
+int ber::decode_choice(asn1::types::choice_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("ber::decode choice b.decode_ber");
+  return b.decode_ber(*this);
+}
+
+
+// Sequence
+void ber::encode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len = 0;
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  ASN1_BER_LOG_DEBUG("ber::encode sequence preamble tag=%d",b.tag().byte());
+  b.encode_preamble_ber(*this);
+}
+void ber::encode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  b.encode_epilogue_ber(*this);
+}
+
+void ber::encode_sequence_preamble(const asn1::types::sequence_type &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("ber::encode sequence preamble tag=%d const ",b.tag().byte());
+  //const_cast<asn1::types::sequence_type &>(b).encode_preamble_ber(*this);
+  encode_header(b,len);
+}
+void ber::encode_sequence_epilogue(const asn1::types::sequence_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("ber::encode_sequence_epilogue tag=%d const ",b.tag().byte());
+  //b.encode_epilogue_ber(*this);
+}
+
+
+
+int ber::decode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len;
+  std::string n = typeid(b).name();
+  ASN1_BER_LOG_DEBUG("ber::decode sequence preamble %s",n.c_str());
+  if (decode_header(b.tag(),len))
+  {
+    return b.decode_preamble_ber(*this);
+  } else
+  {
+    return asn1::unknown;
+  }
+}
+
+int ber::decode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  return b.decode_epilogue_ber(*this);
+}
+   
+
+//
+void ber::encode_header(const asn1::types::type &obj, int &len)
+{
+  asn1::tag t = obj.tag();
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  size_t         i = 0;
+  long         required = 1;
+
+  ASN1_BER_LOG_DEBUG("ber::encode_header code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+  b[pos] = ((t.get_class() & 0x03)<<6 )| ( (t.get_id() < 31) ? t.get_id() : 0x1F);
+  if ( ! obj.primitive() ) 
+    b[pos] |= 0x20;
+  long tgv = t.get_id();
+
+  if ( t.get_id() > 31 )
+  {
+    //required = (types::count_bits(tgv) + 6 ) / 7 ;
+    // Compute required size for id > 31
+    for ( required = 1, i = 7 ; i < sizeof(long) * 8 ; i+=7)
+    {
+      if (t.get_id() >> i )
+      {
+        required++;
+      } else
+        break;
+    }
+  // Encode id ...
+    unsigned char * end = b + required  ;
+    for ( i-= 7, ++pos;  &b[pos] < end; i-=7 , pos++)
+    {
+      b[pos] = 0x80 | (( tgv >> i) & 0x7F);
+    }
+    b[pos] =  (( tgv >> i) & 0x7F);
+    required++;
+  }
+
+  // Get Length of underlying data objects length, and encode length. 
+  size_t data_len = obj.get_data_length();
+  ASN1_BER_LOG_DEBUG("ber::encode_header data_length = %ld len=%d",data_len,len);
+  if (data_len < 128)
+  {  // Don't know how to do this for now 
+    b[++pos] = data_len;
+    nb_bits(8 + ((required)<<3));
+  } else
+  {
+    int count = (types::count_bits(data_len +1)+7)/8;
+    b[++pos] = count | 0x80;
+    while (count-- > 0)
+    { 
+      b[++pos] = (len >> (count+8));
+    }
+  }
+}
+//
+void ber::encode_tag(const asn1::tag &t,const int &len)
+{
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  size_t         i = 0;
+  long         required = 1;
+
+  ASN1_BER_LOG_DEBUG("ber::encode_tag code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+  b[pos] = ((t.get_class() & 0x03)<<6 )| ( (t.get_id() < 31) ? t.get_id() : 0x1F);
+  if (  t.get_constructed() ) 
+    b[pos] |= 0x20;
+  long tgv = t.get_id();
+
+  if ( t.get_id() > 31 )
+  {
+    //required = (types::count_bits(tgv) + 6 ) / 7 ;
+    // Compute required size for id > 31
+    for ( required = 1, i = 7 ; i < sizeof(long) * 8 ; i+=7)
+    {
+      if (t.get_id() >> i )
+      {
+        required++;
+      } else
+        break;
+    }
+  // Encode id ...
+    unsigned char * end = b + required  ;
+    for ( i-= 7, ++pos;  &b[pos] < end; i-=7 , pos++)
+    {
+      b[pos] = 0x80 | (( tgv >> i) & 0x7F);
+    }
+    b[pos] =  (( tgv >> i) & 0x7F);
+    required++;
+  }
+
+  // Get Length of underlying data objects length, and encode length. 
+  size_t data_len = len;
+  ASN1_BER_LOG_DEBUG("ber::encode_header data_length = %ld len=%d",data_len,len);
+  if (data_len < 128)
+  {  // Don't know how to do this for now 
+    b[++pos] = data_len;
+    nb_bits(8 + ((required)<<3));
+  } else
+  {
+    int count = (types::count_bits(data_len +1)+7)/8;
+    b[++pos] = count | 0x80;
+    while (count-- > 0)
+    { 
+      b[++pos] = (len >> (count+8));
+    }
+  }
+}
+    
+    
+/**
+ *
+ */
+int ber::decode_tag(asn1::tag &t) 
+{
+  int len;
+  return decode_header(t,len); 
+}
+/**
+ * @brief Decodes tag and length without any check
+ */
+bool ber::decode_tag(asn1::tag &tag,int &len)
+{
+  long nb = 0;
+  long nbt  = 1;
+  long tval = 0;
+
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  ASN1_BER_LOG_DEBUG("ber::decode_tag tag : cls=%d id=%d pos=%ld have tag in stream=%d"
+                    , tag.get_class()
+                    , tag.get_id()
+                    , pos
+                    , b[pos]);
+  int tcls = (b[pos] >> 6);
+  tval = b[pos];
+  tag.byte(tval);
+  if ((tval &= 0x1F) != 0x1F)
+  {
+    len = decode_length(&b[pos+1],&nb);
+    nb_bits( (nb + 1)<<3);
+    ASN1_BER_LOG_DEBUG("ber::decode_tag sf tag : cls=%d id=%d tval=%ld nbt=%ld pos=%lu"
+                    , tag.get_class()
+                    , tag.get_id()
+                    , tval,nbt,pos);
+    return true;
+  }
+  // Long Form... be sure not to read too far....
+  for (pos++, tval = 0; /* Stop Before end of buffer*/ nbt < 3
+      ;pos++ , nbt++)
+  {
+    if ( b[pos] & 0x80 )
+    {
+      tval = tval<<7 | (b[pos] & 0x7F);
+    } else 
+    { // Last 7 bits
+      tval = tval<<7 | b[pos] ;
+      break;
+    }
+  }
+  ASN1_BER_LOG_DEBUG("ber::decode_tag lf tag : cls=%d id=%d tval=%ld nbt=%ld pos=%lu"
+                    , tag.get_class()
+                    , tag.get_id()
+                    , tval,nbt,pos);
+  len = decode_length(&b[pos+1],&nb);
+  tag.byte(tval);
+  nb_bits( (nb + nbt + 1)<<3);
+  return true;
+}
+
+/**
+ * @brief Decode header 
+ * @param tag
+ * @len   TODO should be of type size_t len cannot be negatif
+ * @return return true if tag matches decoded tag false otherwise
+ *  Buffer position changed to data position if function returns true.
+ */ 
+bool ber::decode_header(const asn1::tag &tag,int &len,bool check)
+{
+  long nb   = 0;
+  long nbt  = 1;
+  long tval = 0;
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  ASN1_BER_LOG_DEBUG("ber::decode_header tag : cls=%d id=%d pos=%ld expected=%d stream has=%d "
+                    , tag.get_class()
+                    , tag.get_id()
+                    , pos
+                    , tag.byte(),b[pos]);
+  int tcls = (b[pos] >> 6);
+  tval = b[pos];
+  if ((tval &= 0x1F) != 0x1F)
+  {
+    // Short From
+    if ( b[pos] != tag.byte() ) 
+      return false;
+
+    len = decode_length(&b[pos+1],&nb);
+
+    nb_bits( (nb + 1)<<3);
+    return true;
+  }
+  // Long Form... be sure not to read too far....
+  for (pos++, tval = 0; /* Stop Before end of buffer*/ nbt < 3
+       ;pos++ , nbt++)
+  {
+    if ( b[pos] & 0x80 )
+    {
+      tval = tval<<7 | (b[pos] & 0x7F);
+    } else 
+    { // Last 7 bits
+      tval = tval<<7 | b[pos] ;
+      break;
+    }
+  }
+  ASN1_BER_LOG_DEBUG("ber::decode_header lf tag : cls=%d id=%d tval=%ld nbt=%ld pos=%lu"
+                    , tag.get_class()
+                    , tag.get_id()
+                    , tval,nbt,pos);
+  if (tag.get_id() != tval)
+    return false;
+  len = decode_length(&b[pos+1],&nb);
+  nb_bits( (nb + nbt + 1)<<3);
+  return true;
+}
+
+
+
+
+
+/**
+ :vim et sw=2 ts=2:
+ */
+}
+}
diff --git a/rtasn1/asn1_codec_ber.h b/rtasn1/asn1_codec_ber.h
new file mode 100644 (file)
index 0000000..7891adc
--- /dev/null
@@ -0,0 +1,239 @@
+#ifndef CODEC_BER_H
+#define CODEC_BER_H
+#include <iostream>
+#if 0
+#if defined(__GNUC__) && defined(DEBUG) & not(defined(ASN1_BER_LOG_DEBUG))
+#define ASN1_BER_LOG_DEBUG(fmt,args...) do {\
+  fprintf(stderr,fmt,##args);\
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\
+} while (0)
+#elseif not(defined(ASN1_BER_LOG_DEBUG)) 
+  static inline void ASN1_BER_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+#endif
+
+#else
+#include "rtasn1/asn1_debug.h"
+#endif
+namespace asn1 {
+class context;
+class codecBER;
+namespace streams {
+//#define DEBUG
+/**
+ *
+ */
+
+class ber  : public asn1::context
+{
+    public:
+    ber( int sz = 512) ;
+    ber(unsigned char *b,size_t size)
+      : asn1::context(b,size) {};
+    ber(const ber &c) ;
+    ~ber() {}
+    
+    virtual int decode_tag(asn1::tag &t) ;
+
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) ;
+    virtual int decode_null(asn1::Null &b) ;
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) ;
+    virtual int decode_boolean(asn1::BOOLEAN &b) ;
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) ;
+    virtual int decode_integer(asn1::INTEGER &b) ;
+    int decode_integer(asn1::UInt64 &b) ;
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) ;
+    virtual int decode_bitstring(asn1::BIT_STRING &b) ;
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) ;
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) ;
+    
+    virtual void encode_string(const asn1::types::strtype &b) ;
+    virtual int decode_string(asn1::types::strtype &b) ;
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) ;
+    virtual int decode_choice(asn1::types::choice_type &b) ;
+
+    // Sequence
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) ;
+    void encode_sequence_preamble(const asn1::types::sequence_type &b) ;
+    void encode_sequence_epilogue(const asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) ;
+       
+    // Any
+    //
+    virtual void encode_any(const asn1::types::any_type &b);
+    virtual int decode_any(asn1::types::any_type &b);
+    /**
+     * When reading ber, we need to be able to decode the length 
+     */
+    long decode_length(unsigned char *buf, long *readed);
+    /**
+     * decode tag without cheking value
+     */
+    bool decode_tag( asn1::tag &t, int &len);
+    
+    bool decode_header(const asn1::tag &tag,int &len,bool check_tag=true);
+
+    friend class asn1::codecBER;
+    protected:
+      /* deprecated */
+      void encode_header(const asn1::types::type &obj, int &len);
+      /* deprecated */
+      void encode_tag(const asn1::tag &obj,const int &len);
+      /* encode simple byte */
+      void encode_byte(unsigned char c);
+      
+      unsigned char decode_byte();
+
+};
+
+// End namesape codecs
+}
+
+/**
+ * @brief This class is responsible for all BER encoding
+ * and decoding. 
+ * 
+ */
+  class codecBER : public codec
+  {
+    protected:
+      codecBER(const codecBER &c) {};
+    public:
+      codecBER() {}
+
+      template <class T>
+      void encode(streams::ber &ctx,const T &t) ;
+      
+      /*  New encoding .... deprecates the one in streams::ber*/
+      void encode_header(streams::ber &ctx, const asn1::types::type &obj, const size_t len);
+      /*  New encoding that deprecates the one in ber class */
+      void encode_tag(streams::ber &ctx,const asn1::tag &obj,const size_t len);
+#if 0
+      /* Will this work ? I don't think it will. Need to think about it 
+       * a bit more
+       */
+      size_t get_length(const asn1::types::type &obj) const;
+
+      template <class T>
+      size_t get_data_length(const T &t) const
+      { return 0; };
+#endif
+      template <class T>
+      int decode(streams::ber &ctx, T &t) ;
+      /* Special case for Sequence OF */
+      template <class T>
+      void encode(streams::ber &ctx,const asn1::Seq<T> &t)
+      {
+        typename asn1::Seq<T>::const_iterator mit = t.begin();
+        int dlen = t.get_data_length();
+        ctx.encode_header(t.tag(),dlen);
+        for (; mit != t.end() ; ++mit)
+        {
+          if (mit != t.begin()) 
+          encode(ctx,(*mit));
+        }
+      }
+      template <class T>
+      int decode(streams::ber &ctx,asn1::Seq<T> &t)
+      {
+        T element;
+        int ret;
+        int len = 0;
+        std::cout<<"TODO decode Seq<T>"<<std::endl;
+        if ( ! ctx.decode_header(t.tag(),len))
+        {
+          std::cerr<<"decode sequenceof failed wrong tag"<<std::endl;
+          return asn1::wrong_type;
+        }
+        do {
+          if ((ret = decode(ctx,element)) == asn1::ok)
+          {
+            t.push_back(element);
+//            For debug purpose
+//            std::cout<<"decode added 1 element "<<typeid(element).name()<<"Seq <T> size ="<<t.size()<<std::endl;
+          } else
+          {
+            break;
+          }
+        } while (ret == asn1::ok);
+        return asn1::ok;
+      }
+
+
+      /* handle optional types */
+      template <class T>
+      void encode(streams::ber &ctx,const asn1::intrusive_ptr<T> &t)
+      {
+        int len;
+        /* If it's a choice, several options are available ! do I create
+         * the object to check if it works or not ?
+         */
+        std::cout<<"codecBER::encode optional ! how do I do this ?"<<std::endl;
+        if (!t.is_nul())
+        {
+          encode(ctx,t.get());
+        }
+      }
+      template <class T>
+      int decode(streams::ber &ctx,asn1::intrusive_ptr<T> &t)
+      {
+        int len;
+        /* If it's a choice, several options are available ! do I create
+         * the object to check if it works or not ?
+         */
+        std::cout<<"codecBER::decode optional ! how do I do this ?"<<std::endl;
+        if (ctx.decode_header(t.tag(),len))
+        {
+          return decode(ctx,t.get());
+        } else
+        return asn1::wrong_tag;
+      }
+      // Need to provide implementation
+      // For base Types, INTEGER, BOOLEAN...
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      void encode_ber(streams::ber &ctx, const asn1::Asn1Type &t); \
+      int \
+      decode_ber(streams::ber &ctx, asn1::Asn1Type &t);
+
+ASN1_TYPE_CLS(asn1::prim::types::ObjectIdentifier,asn1::types::UNIVERSAL,6,ObjectIdentifier)
+
+#include "rtasn1/asn1_types.inc"
+
+
+  };
+
+/*
+ *  encode / decode specialization declaration
+ */
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecBER::encode(streams::ber &ctx, const asn1::Asn1Type &t) \
+      ; \
+      template <> \
+      int \
+      codecBER::decode(streams::ber &ctx, asn1::Asn1Type &t) \
+      ;
+#include "rtasn1/asn1_types.inc"
+
+
+// End namespace ans1
+}
+
+#endif
diff --git a/rtasn1/asn1_codec_jer.cpp b/rtasn1/asn1_codec_jer.cpp
new file mode 100644 (file)
index 0000000..28b35ef
--- /dev/null
@@ -0,0 +1,1259 @@
+#include <iostream>
+#include <string>
+#include <typeinfo>
+#include <assert.h>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_context.h"
+#include "rtasn1/cjson/cJSON.h"
+
+#include "rtasn1/asn1_codec_jer.h"
+
+
+/* a lookup table which lets us quickly determine three things:
+ * VEC - valid escaped control char
+ * note.  the solidus '/' may be escaped or not.
+ * IJC - invalid json char
+ * VHC - valid hex char
+ * NFP - needs further processing (from a string scanning perspective)
+ * NUC - needs utf8 checking when enabled (from a string scanning perspective)
+ */
+#define VEC 0x01
+#define IJC 0x02
+#define VHC 0x04
+#define NFP 0x08
+#define NUC 0x10
+
+static const char charLookupTable[256] =
+{
+  /*00*/ IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    ,
+  /*08*/ IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    ,
+  /*10*/ IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    ,
+  /*18*/ IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    , IJC    ,
+
+  /*20*/ 0      , 0      , NFP|VEC|IJC, 0      , 0      , 0      , 0      , 0      ,
+  /*28*/ 0      , 0      , 0      , 0      , 0      , 0      , 0      , VEC    ,
+  /*30*/ VHC    , VHC    , VHC    , VHC    , VHC    , VHC    , VHC    , VHC    ,
+  /*38*/ VHC    , VHC    , 0      , 0      , 0      , 0      , 0      , 0      ,
+
+  /*40*/ 0      , VHC    , VHC    , VHC    , VHC    , VHC    , VHC    , 0      ,
+  /*48*/ 0      , 0      , 0      , 0      , 0      , 0      , 0      , 0      ,
+  /*50*/ 0      , 0      , 0      , 0      , 0      , 0      , 0      , 0      ,
+  /*58*/ 0      , 0      , 0      , 0      , NFP|VEC|IJC, 0      , 0      , 0      ,
+
+  /*60*/ 0      , VHC    , VEC|VHC, VHC    , VHC    , VHC    , VEC|VHC, 0      ,
+  /*68*/ 0      , 0      , 0      , 0      , 0      , 0      , VEC    , 0      ,
+  /*70*/ 0      , 0      , VEC    , 0      , VEC    , 0      , 0      , 0      ,
+  /*78*/ 0      , 0      , 0      , 0      , 0      , 0      , 0      , 0      ,
+
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    ,
+         NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC    , NUC
+};
+
+
+
+/*
+vim:et:sw=2:ts=2
+ */
+namespace asn1 {
+
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)                 \
+      template <>                                                       \
+      void codecJER::encode(streams::jer &ctx, const asn1::Asn1Type &t) \
+      {                                                                 \
+         encode_jer(ctx,t);                                             \
+      }                                                                 \
+      template <>                                                       \
+      int                                                               \
+      codecJER::decode(streams::jer &ctx, asn1::Asn1Type &t)            \
+      {                                                                 \
+         return decode_jer(ctx,t);                                      \
+      }
+#if 0 
+/* comments for debuging purpose. */
+         std::cerr<<"codecJER::"<<__FUNCTION__<<"  good ";              \
+         std::cerr<<#Asn1Type<<std::endl;                               \
+         std::cerr<<"codecJER::"<<__FUNCTION__<<" good ";               \
+         std::cerr<<#Asn1Type<<std::endl;                               \
+
+#endif
+#include "rtasn1/asn1_types.inc"
+      
+template <> 
+void codecJER::encode(streams::jer &ctx, const asn1::ObjectIdentifier &t) 
+{  
+  std::cerr<<"codecJER::"<<__FUNCTION__<<"  good "; 
+  std::cerr<<"asn1::ObjectIdentifier "<<std::endl; 
+  //encode_jer(ctx,t);
+} 
+template <> 
+int 
+codecJER::decode(streams::jer &ctx, asn1::ObjectIdentifier &t) 
+{
+  std::cerr<<"codecJER::"<<__FUNCTION__<<" good ";    
+  std::cerr<<"asn1::ObjectIdentifier"<<std::endl;
+  return asn1::ok;
+  //
+  //return decode_jer(ctx,t);
+}
+
+
+
+#define ASN1_CODEC_IMPL(Type,Encode,Decode) \
+void codecJER::encode_jer(streams::jer &ctx,const asn1::Type &t) \
+Encode \
+int codecJER::decode_jer(streams::jer &ctx,asn1::Type &t) \
+Decode
+       
+ASN1_CODEC_IMPL(BOOLEAN,
+{
+  ctx.encode_boolean(t);
+},
+{
+  return ctx.decode_boolean(t);
+})
+ASN1_CODEC_IMPL(INTEGER,
+{
+  ctx.encode_integer(t);
+},
+{
+  return ctx.decode_integer(t);
+})
+ASN1_CODEC_IMPL(Int8,
+{
+  std::cout<<__FUNCTION__<<" Int8 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int16,
+{
+  std::cout<<__FUNCTION__<<" Int16 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int32,
+{
+  std::cout<<__FUNCTION__<<" Int32 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int64,
+{
+  std::cout<<__FUNCTION__<<" Int64 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt8,
+{
+  std::cout<<__FUNCTION__<<" UInt 8 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt16,
+{
+  std::cout<<__FUNCTION__<<" UInt 16 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+//
+ASN1_CODEC_IMPL(UInt32,
+{
+  std::cout<<__FUNCTION__<<" UInt 32 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+//
+ASN1_CODEC_IMPL(UInt64,
+{
+  std::cout<<__FUNCTION__<<" UInt64 TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(BIT_STRING,
+{
+  ctx.encode_bitstring(t);
+},
+{
+  return ctx.decode_bitstring(t);
+})
+ASN1_CODEC_IMPL(OCTET_STRING,
+{
+  ctx.encode_octetstring(t);
+},
+{
+  return ctx.decode_octetstring(t);
+})
+ASN1_CODEC_IMPL(STRING,
+{
+  std::cout<<__FUNCTION__<<" STRING TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Null,
+{
+  std::cout<<__FUNCTION__<<" NUll TODO"<<std::endl;
+  ctx.encode_null(t);
+},
+{
+  return asn1::ok;
+})
+#if 0
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER,
+{
+  std::cout<<__FUNCTION__<<" oid TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#else
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER_NG,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#endif
+ASN1_CODEC_IMPL(EXTERNAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralizedTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UTCTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(REAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(ENUMERATED,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  std::cout<<__FUNCTION__<<" NOT SURE IF I should ENTER HERE! TODO"<<std::endl;
+  return asn1::wrong_type;
+})
+// typedef asn1::types::any_type ANY;
+ASN1_CODEC_IMPL(UTF8String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(NumericString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(PrintableString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(TeletexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VideotexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(IA5String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GraphicString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VisibleString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UniversalString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(BMPString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+
+
+namespace streams {
+
+bool 
+jer::get_token(const char *s)
+{
+  size_t         _len;
+  unsigned char *_buf;
+  size_t         _curOff = m_bufOff;
+
+  if (json_lex(m_bufOff,&_buf,_len) == jer_tok_string)
+  {
+    if ( ! strncmp(s,(const char *)_buf,_len))
+    {
+      return true ;
+    } else
+    {
+      m_bufOff = _curOff;
+      return false;
+    }
+  } else
+  {
+    m_bufOff = _curOff;
+    return false;
+  }
+}
+
+bool 
+jer::get_token(jer::jer_token tok)
+{
+  size_t         _len = 0;
+  unsigned char *_buf = NULL;
+  size_t         _curOff = m_bufOff;
+  int res;  
+  if ((res = json_lex(m_bufOff,&_buf,_len)) == tok)
+  {
+    return true ;
+  } else
+  {
+    std::string s((const char * )_buf,_len);
+    m_bufOff = _curOff;
+    return false;
+  }
+}
+
+bool 
+jer::get_token(std::string &s)
+{
+  size_t         _len;
+  unsigned char *_buf;
+  size_t         _curOff = m_bufOff;
+  int res;  
+  if ((res = json_lex(m_bufOff,&_buf,_len)) == jer_tok_string)
+  {
+    s.assign((const char * )_buf,_len);
+    return true ;
+  } else
+  {
+    std::string s((const char * )_buf,_len);
+    m_bufOff = _curOff;
+    return false;
+  }
+}
+
+
+void jer::put_string(const std::string &s)
+{
+  if (s.size() > (m_size - m_bufOff))
+  {
+    std::cerr<<"jer::put_string Failed\n"<<std::endl;
+  } else { 
+    strncpy((char *)(m_buffer+m_bufOff),(char *)s.c_str(),s.size());
+    m_bufOff += s.size();
+  }
+}
+
+/**
+ * @brief copy the message into the buffer. We need
+ * to return an error or realocate the buffer in cas
+ * of missing space.
+ */
+void jer::put_char(const unsigned char *_s,size_t len)
+{
+  if ( (m_bufOff + len) < get_size())
+  {
+    strncpy((char *)(m_buffer+m_bufOff),(char *)_s,len);
+    m_bufOff+=len;
+  } else
+  {
+    std::cerr<<"jer::put_char out of space.";
+  }
+}
+
+/**
+ * @brief copy the message into the buffer. We need
+ * to return an error or realocate the buffer in cas
+ * of missing space.
+ */
+void jer::put_char(const char *_s,size_t len)
+{
+  if ( m_bufOff + len < get_size())
+  {
+    strncpy((char *)(m_buffer+m_bufOff),(char *)_s,len);
+    m_bufOff+=len;
+  } else
+  {
+    std::cerr<<"jer::put_char out of space.";
+  }
+}
+
+const char *
+jer::error_to_string(int i) const
+{
+  switch (i)
+  {
+    default: ;
+  };
+  return "unknown";
+}
+    
+const char * 
+jer::tok2str(int tok) const
+{
+  switch (tok)
+  {
+    default: ;
+  };
+  return "unknown";
+}
+
+
+jer::jer(int sz) : asn1::context(sz)
+    , m_lineOff(0)
+    , m_charOff(0)
+    , m_bufOff(0)
+{
+  ASN1_BER_LOG_DEBUG("jer::jer  %d ",sz);
+}
+
+jer::jer(unsigned char *buf,int sz)
+: asn1::context(buf,sz)
+    , m_lineOff(0)
+    , m_charOff(0)
+    , m_bufOff(0)
+{
+  ASN1_BER_LOG_DEBUG("jer::jer  %d ",sz);
+}
+
+
+jer::jer(const jer &_codec) : asn1::context()
+    , m_lineOff(_codec.m_lineOff)
+    , m_charOff(_codec.m_charOff)
+    , m_bufOff(_codec.m_bufOff)
+{
+  ASN1_BER_LOG_DEBUG("jer::jer(const ber &_codec )  ");
+}
+
+
+// Null
+// 5
+void jer::encode_null(const asn1::Null &b) 
+{
+  int len = 0;
+  put_char("null",4);
+  ASN1_BER_LOG_DEBUG("jer::encode Null tag=%d  ",b.tag().byte());
+}
+
+int jer::decode_null(asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("jer::decode Null  ");
+    
+  return asn1::ok;
+}
+
+
+// Bool
+//
+void jer::encode_boolean(const asn1::BOOLEAN &b) 
+{
+  int len = 1;
+  ASN1_BER_LOG_DEBUG("jer::encode boolean tag=%d",b.tag().byte());
+  if (b == true)
+  { 
+    put_char("true",4); 
+  } else
+    put_char("false",5);
+}
+
+int jer::decode_boolean(asn1::BOOLEAN &b) 
+{
+  size_t         _len = 0;
+  unsigned char *_buf = NULL;
+  size_t         _curOff = m_bufOff;
+  ASN1_BER_LOG_DEBUG("jer::decode boolean tag=%d",b.tag().byte());
+
+  if (json_lex(m_bufOff,&_buf,_len) == jer_tok_bool)
+  {
+    if ( ( _len == 4 ) && ! strncmp("true",(const char *)_buf,_len))
+    {
+      b = true;
+    } else if ( ( _len == 5 ) && ! strncmp("false",(const char *)_buf,_len))
+    {
+      b = false;
+    } 
+  } else
+  {
+    m_bufOff = _curOff;
+    return false;
+  }
+  return asn1::ok;
+}
+
+
+// Integer
+//
+void jer::encode_integer(const asn1::types::type &b) 
+{
+  int  len = 0; size_t base  = 10;
+  long tmp = 0; size_t count = 0;
+  long t   = 0; long   res   = 0;
+  long long  integer = 0;
+  
+  if (const asn1::prim::types::Integer *i = dynamic_cast< const asn1::prim::types::Integer *>(&b))
+  { 
+     integer = i->get_value();
+  } else if (const asn1::prim::types::UInt64 *i = dynamic_cast< const asn1::prim::types::UInt64 *>(&b))
+  {
+     integer = i->get_value();
+  }
+  
+  char  *ptr = (char *)buffer(); ptr+=m_bufOff;
+  tmp = integer;
+
+  if (tmp == 0)
+    count++;
+
+  while ((unsigned long)tmp > 0 )
+  {
+    tmp = tmp/base; count++;
+  }
+
+  if (m_bufOff + count > get_size())
+  {
+    std::cout<<"Issue with jer::encode_integer buffer overflow"<<std::endl;
+    return ; 
+  }
+  ptr += count;
+  *ptr = '\0';
+  do
+  {
+    res = integer - base * (t = integer / base);
+    if (res < 10)
+    {
+      * --ptr = '0' + (char)res;
+    } else if ( res >= 10 && (res < 16 ))
+    {
+      * --ptr = 'A' - 10 + (char)res;
+    }
+  } while ((integer = t ) != 0);
+  m_bufOff += count;
+  ASN1_BER_LOG_DEBUG("jer::encode integer tag=%d  value=%ld "
+                    , b.tag().byte()
+                    ,(long)integer
+                    );
+}
+
+/**
+ * Decode Integer 
+ */
+int jer::decode_integer(asn1::INTEGER &t) 
+{
+  size_t len         = 0;
+  unsigned char *buf = NULL;
+  int result         = 0;
+  ASN1_BER_LOG_DEBUG("jer::decode integer tag=%d",t.tag().byte());
+  switch( json_lex(m_bufOff,&buf,len))
+  {
+    case jer_tok_integer:
+    {
+      std::string b((char *)buf,len);
+      t = atol(b.c_str());
+    }
+    break;
+    default:
+      std::cout<<"jer::decode_integer error"<<std::endl;
+      return asn1::wrong_type;
+  }
+  return asn1::ok;
+}
+
+
+int 
+jer::decode_integer(asn1::UInt64 &t)
+{
+  size_t len         = 0;
+  unsigned char *buf = NULL;
+  int result         = 0;
+  ASN1_BER_LOG_DEBUG("jer::decode unsigned integer tag=%d",t.tag().byte());
+  switch( json_lex(m_bufOff,&buf,len))
+  {
+    case jer_tok_integer:
+    {
+      std::string b((char *)buf,len);
+      t = strtoul(b.c_str(),NULL,10);
+    }
+    break;
+    default:
+      std::cout<<"jer::decode_integer error"<<std::endl;
+      return asn1::wrong_type;
+  }
+  return asn1::ok;
+}
+
+
+// Bit String
+//
+void jer::encode_bitstring(const asn1::BIT_STRING &t) 
+{
+  int len = t.size() + 1;
+  ASN1_BER_LOG_DEBUG("jer::encode bit string len=%d ",len);
+}
+
+int jer::decode_bitstring(asn1::BIT_STRING &t) 
+{
+  ASN1_BER_LOG_DEBUG("jer::decode bit string tag=%d ",t.tag().byte());
+
+  return asn1::ok;
+}
+
+
+static char gAlpha[]= {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+// Octet string
+//
+void jer::encode_octetstring(const asn1::OCTET_STRING &b) 
+{
+  size_t      len = (b.get_value()).size(); // Length
+  const char *ptr = (b.get_value()).c_str();
+  put_char("\"",1);
+  char       *buf = (char *)buffer() + m_bufOff;  
+  m_bufOff+=len*2;
+  //std::cerr<<"encode_octet_string:"<<len<<" "<<m_bufOff<<" "<<ptr<<std::endl;
+  ASN1_BER_LOG_DEBUG("jer::encode octet string tag=%d",b.tag().byte());
+  do
+  {
+    *buf++ = gAlpha[( (*ptr)>>4 ) & 0x0F];
+    *buf++ = gAlpha[( *ptr++  ) & 0x0F];
+  } while (--len);
+  put_char("\"",1);
+}
+
+int jer::decode_octetstring(asn1::OCTET_STRING &b_) 
+{
+  int len = 0;
+  std::string field;
+  ASN1_BER_LOG_DEBUG("jer::decode octet string TODO ");
+  if (! get_token(field))
+  {
+    ASN1_BER_LOG_ERROR("jer::decode octerstring tag_id=%d no field",b_.tag().get_id());
+    return asn1::wrong_type;
+  }
+  std::string &result = b_.get_value().get_value();
+  result.resize(0,'\0');
+  for (std::string::iterator it = field.begin() ; it!= field.end()
+      ; ++it) 
+  {
+    char c1 = *it; ++it;
+    char c2 = *it;
+    char r = ((c1 - '0')<<4 & 0xF0 ) | ((c2 - '0') & 0x0F );
+    result.push_back(r);
+
+  }
+  return asn1::ok;
+}
+
+void jer::encode_string(const asn1::types::type &b)
+{
+  int len = 0;
+  const asn1::prim::types::String &s = dynamic_cast< const asn1::prim::types::String &>(b); 
+  len = s.get_value().size(); // Length
+  ASN1_BER_LOG_DEBUG( "jer::encode string tag=%d len=%d"
+                    , b.tag().get_id()
+                    , len
+                    );
+  put_field(s.get_value().c_str(),len);
+}
+
+
+int jer::decode_string(asn1::types::type &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("jer::decode  string tag_id=%d",b.tag().get_id());
+  asn1::prim::types::String &s = dynamic_cast<asn1::prim::types::String &>(b); 
+  
+  return asn1::ok;
+}
+
+
+// Choice
+//
+void jer::encode_choice(asn1::types::choice_type &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("jer::encode choice ");
+}
+
+int jer::decode_choice(asn1::types::choice_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("jer::decode choice ");
+  return asn1::ok;
+}
+
+
+// Sequence
+void jer::encode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len = 0;
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  ASN1_BER_LOG_DEBUG("jer::encode sequence preamble tag=%d",b.tag().byte());
+}
+void jer::encode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("jer::encode sequence epilogue tag=%d",b.tag().byte());
+}
+
+
+int jer::decode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  if ( get_token(jer_tok_left_bracket))
+  {
+    return asn1::ok;
+  } else  
+    return asn1::wrong_type;
+}
+
+int jer::decode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  if ( get_token(jer_tok_right_bracket))
+  {
+    return asn1::ok;
+  } else  
+    return asn1::wrong_type;
+}
+   
+
+//
+void jer::encode_header(const asn1::types::type &obj, int &len)
+{
+  asn1::tag t = obj.tag();
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  
+  ASN1_BER_LOG_DEBUG("jer::encode_header code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+}
+    
+int jer::decode_tag(asn1::tag &t) 
+{
+  int len;
+  return decode_header(t,len); 
+}
+/**
+ *
+ */
+bool jer::decode_tag(asn1::tag &tag,int &len)
+{
+  return true;
+}
+
+bool jer::decode_header(const asn1::tag &tag,int &len)
+{
+  return true;
+}
+
+/*  */
+#define STR_CHECK_EOF \
+if (offset >= jsonTextLen) { \
+   tok = jer_tok_eof; \
+   goto finish_string_lex; \
+}
+
+jer::jer_token
+jer::lex_string( const unsigned char * jsonText,
+                size_t jsonTextLen, size_t & offset)
+{
+    jer_token tok = jer_tok_error;
+    int hasEscapes = 0;
+
+    for (;;) {
+        unsigned char curChar;
+#if 0
+        /* now jump into a faster scanning routine to skip as much
+         * of the buffers as possible */
+        {
+            const unsigned char * p;
+            size_t len;
+
+            if ((lexer->bufInUse && yajl_buf_len(lexer->buf) &&
+                 lexer->bufOff < yajl_buf_len(lexer->buf)))
+            {
+                p = ((const unsigned char *) yajl_buf_data(lexer->buf) +
+                     (lexer->bufOff));
+                len = yajl_buf_len(lexer->buf) - lexer->bufOff;
+                lexer->bufOff += yajl_string_scan(p, len, lexer->validateUTF8);
+            }
+            else if (*offset < jsonTextLen)
+            {
+                p = jsonText + *offset;
+                len = jsonTextLen - *offset;
+                *offset += yajl_string_scan(p, len, lexer->validateUTF8);
+            }
+        }
+#endif
+        STR_CHECK_EOF;
+
+        curChar = readChar( jsonText, offset);
+
+        /* quote terminates */
+        if (curChar == '"') {
+            tok = jer_tok_string;
+            break;
+        }
+        /* backslash escapes a set of control chars, */
+        else if (curChar == '\\') {
+            hasEscapes = 1;
+            STR_CHECK_EOF;
+
+            /* special case \u */
+            curChar = readChar( jsonText, offset);
+            if (curChar == 'u') {
+                unsigned int i = 0;
+
+                for (i=0;i<4;i++) {
+                    STR_CHECK_EOF;
+                    curChar = readChar( jsonText, offset);
+                    if (!(charLookupTable[curChar] & VHC)) {
+                        /* back up to offending char */
+                        unreadChar( offset);
+                        m_error = jer_err_string_invalid_hex_char;
+                        goto finish_string_lex;
+                    }
+                }
+            } else if (!(charLookupTable[curChar] & VEC)) {
+                /* back up to offending char */
+                unreadChar(offset);
+                m_error = jer_err_string_invalid_escaped_char;
+                goto finish_string_lex;
+            }
+        }
+        /* when not validating UTF8 it's a simple table lookup to determine
+         * if the present character is invalid */
+        else if(charLookupTable[curChar] & IJC) {
+            /* back up to offending char */
+            unreadChar(offset);
+            m_error = jer_err_string_invalid_json_char;
+            goto finish_string_lex;
+        }
+#if 0
+        /* when in validate UTF8 mode we need to do some extra work */
+        else if (lexer->validateUTF8) {
+            yajl_tok t = yajl_lex_utf8_char(lexer, jsonText, jsonTextLen,
+                                            offset, curChar);
+
+            if (t == yajl_tok_eof) {
+                tok = yajl_tok_eof;
+                goto finish_string_lex;
+            } else if (t == yajl_tok_error) {
+                lexer->error = yajl_lex_string_invalid_utf8;
+                goto finish_string_lex;
+            }
+        }
+#endif
+        /* accept it, and move on */
+    }
+  finish_string_lex:
+    /* tell our buddy, the parser, wether he needs to process this string
+     * again */
+    if (hasEscapes && tok == jer_tok_string) {
+        tok = jer_tok_string_with_escapes;
+    }
+
+    return tok;
+  return jer_tok_error;
+}
+
+#define RETURN_IF_EOF if (offset >= jsonTextLen) return jer_tok_eof;
+jer::jer_token
+jer::lex_number( const unsigned char * jsonText,
+                size_t jsonTextLen, size_t & offset)
+{
+    unsigned char c;
+
+    jer_token tok = jer_tok_integer;
+
+    RETURN_IF_EOF;
+    c = readChar( jsonText, offset);
+
+    /* optional leading minus */
+    if (c == '-') {
+        RETURN_IF_EOF;
+        c = readChar( jsonText, offset);
+    }
+
+    /* a single zero, or a series of integers */
+    if (c == '0') {
+        RETURN_IF_EOF;
+        c = readChar( jsonText, offset);
+    } else if (c >= '1' && c <= '9') {
+        do {
+            RETURN_IF_EOF;
+            c = readChar( jsonText, offset);
+        } while (c >= '0' && c <= '9');
+    } else {
+        unreadChar( offset);
+        m_error = jer_err_missing_integer_after_minus;
+        return jer_tok_error;
+    }
+
+    /* optional fraction (indicates this is floating point) */
+    if (c == '.') {
+        int numRd = 0;
+
+        RETURN_IF_EOF;
+        c = readChar( jsonText, offset);
+
+        while (c >= '0' && c <= '9') {
+            numRd++;
+            RETURN_IF_EOF;
+            c = readChar( jsonText, offset);
+        }
+
+        if (!numRd) {
+            unreadChar( offset);
+            m_error = jer_err_missing_integer_after_decimal;
+            return jer_tok_error;
+        }
+        tok = jer_tok_double;
+    }
+
+    /* optional exponent (indicates this is floating point) */
+    if (c == 'e' || c == 'E') {
+        RETURN_IF_EOF;
+        c = readChar( jsonText, offset);
+
+        /* optional sign */
+        if (c == '+' || c == '-') {
+            RETURN_IF_EOF;
+            c = readChar( jsonText, offset);
+        }
+
+        if (c >= '0' && c <= '9') {
+            do {
+                RETURN_IF_EOF;
+                c = readChar( jsonText, offset);
+            } while (c >= '0' && c <= '9');
+        } else {
+            unreadChar( offset);
+            m_error = jer_err_missing_integer_after_exponent;
+            return jer_tok_error;
+        }
+        tok = jer_tok_double;
+    }
+
+    /* we always go "one too far" */
+    unreadChar( offset);
+
+    return tok;
+}
+
+jer::jer_token
+jer::lex_comment(const unsigned char * jsonText,
+                size_t jsonTextLen, size_t & offset)
+{
+  return jer_tok_error;
+}
+
+int 
+jer::json_lex(size_t &offset,unsigned char **outBuf, size_t &outLen)
+{
+    unsigned char *  jsonText = m_buffer;
+    size_t jsonTextLen        = m_size;
+    size_t startOffset        = offset;
+    int    tok                = jer_tok_error;
+    unsigned char c;
+
+    *outBuf = NULL;
+    outLen = 0;
+#if 1
+    for (;;) {
+        assert(offset <= jsonTextLen);
+
+        if (offset >= jsonTextLen) {
+            tok = jer_tok_eof;
+            goto lexed;
+        }
+
+        //c = readChar(lexer, jsonText, offset);
+        c = readChar();
+
+        switch (c) {
+            case '{':
+                tok = jer_tok_left_bracket;
+                goto lexed;
+            case '}':
+                tok = jer_tok_right_bracket;
+                goto lexed;
+            case '[':
+                tok = jer_tok_left_brace;
+                goto lexed;
+            case ']':
+                tok = jer_tok_right_brace;
+                goto lexed;
+            case ',':
+                tok = jer_tok_comma;
+                goto lexed;
+            case ':':
+                tok = jer_tok_colon;
+                goto lexed;
+            case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
+                startOffset++;
+                break;
+            case 't': {
+                const char * want = "rue";
+                do {
+                    if (offset >= jsonTextLen) {
+                        tok = jer_tok_eof;
+                        goto lexed;
+                    }
+                    //c = readChar(lexer, jsonText, offset);
+                    c = readChar();
+                    if (c != *want) {
+                        //unreadChar(lexer, offset);
+                        unreadChar(offset);
+                        m_error = jer_err_invalid_string;
+                        tok = jer_tok_error;
+                        goto lexed;
+                    }
+                } while (*(++want));
+                tok = jer_tok_bool;
+                goto lexed;
+            }
+            case 'f': {
+                const char * want = "alse";
+                do {
+                    if (offset >= jsonTextLen) {
+                        tok = jer_tok_eof;
+                        goto lexed;
+                    }
+                    //c = readChar(lexer, jsonText, offset);
+                    c = readChar();
+                    if (c != *want) {
+                        //unreadChar(lexer, offset);
+                        unreadChar(offset);
+                        m_error = jer_err_invalid_string;
+                        tok = jer_tok_error;
+                        goto lexed;
+                    }
+                } while (*(++want));
+                tok = jer_tok_bool;
+                goto lexed;
+            }
+            case 'n': {
+                const char * want = "ull";
+                do {
+                    if (offset >= jsonTextLen) {
+                        tok = jer_tok_eof;
+                        goto lexed;
+                    }
+                    //c = readChar(lexer, jsonText, offset);
+                    c = readChar();
+                    if (c != *want) {
+                        //unreadChar(lexer, offset);
+                        unreadChar(offset);
+                        m_error = jer_err_invalid_string;
+                        tok = jer_tok_error;
+                        goto lexed;
+                    }
+                } while (*(++want));
+                tok = jer_tok_null;
+                goto lexed;
+            }
+            case '"': {
+                tok = lex_string( (const unsigned char *) jsonText,
+                                      jsonTextLen, offset);
+                goto lexed;
+            }
+            case '-':
+            case '0': case '1': case '2': case '3': case '4':
+            case '5': case '6': case '7': case '8': case '9': {
+                /* integer parsing wants to start from the beginning */
+                //unreadChar(lexer, offset);
+                unreadChar(offset);
+                tok = lex_number((const unsigned char *) jsonText,
+                                      jsonTextLen, offset);
+                goto lexed;
+            }
+            case '/':
+                /* hey, look, a probable comment!  If comments are disabled
+                 * it's an error. */
+                if (!m_allowComments) {
+                    //unreadChar(lexer, offset);
+                    unreadChar( offset);
+                    m_error = jer_err_unallowed_comment;
+                    tok = jer_tok_error;
+                    goto lexed;
+                }
+                /* if comments are enabled, then we should try to lex
+                 * the thing.  possible outcomes are
+                 * - successful lex (tok_comment, which means continue),
+                 * - malformed comment opening (slash not followed by
+                 *   '*' or '/') (tok_error)
+                 * - eof hit. (tok_eof) */
+                tok = lex_comment((const unsigned char *) jsonText,
+                                       jsonTextLen, offset);
+                if (tok == jer_tok_comment) {
+                    /* "error" is silly, but that's the initial
+                     * state of tok.  guilty until proven innocent. */
+                    tok = jer_tok_error;
+#if 0
+                    yajl_buf_clear(lexer->buf);
+                    bufInUse = 0;
+#endif
+                    startOffset = offset;
+                    break;
+                }
+                /* hit error or eof, bail */
+                goto lexed;
+            default:
+                m_error = jer_err_invalid_char;
+                tok = jer_tok_error;
+                goto lexed;
+        }
+    }
+
+
+  lexed:
+    /* need to append to buffer if the buffer is in use or
+     * if it's an EOF token */
+#if 0
+    if (tok == jer_tok_eof || lexer->bufInUse) {
+        if (!lexer->bufInUse) yajl_buf_clear(lexer->buf);
+        lexer->bufInUse = 1;
+        yajl_buf_append(lexer->buf, jsonText + startOffset, offset - startOffset);
+        lexer->bufOff = 0;
+
+        if (tok != jer_tok_eof) {
+            *outBuf = yajl_buf_data(lexer->buf);
+            *outLen = yajl_buf_len(lexer->buf);
+            lexer->bufInUse = 0;
+        }
+    } else 
+#endif
+      if (tok != jer_tok_error) {
+        *outBuf = jsonText + startOffset;
+        outLen = offset - startOffset;
+    }
+
+    /* special case for strings. skip the quotes. */
+    if (tok == jer_tok_string || tok == jer_tok_string_with_escapes)
+    {
+        assert(outLen >= 2);
+        (*outBuf)++;
+        outLen -= 2;
+    }
+
+
+#ifdef YAJL_LEXER_DEBUG
+    if (tok == jer_tok_error) {
+        printf("lexical error: %s\n",
+               yajl_lex_error_to_string(yajl_lex_get_error(lexer)));
+    } else if (tok == jer_tok_eof) {
+        printf("EOF hit\n");
+    } else {
+        printf("lexed %s: '", tokToStr(tok));
+        fwrite(*outBuf, 1, *outLen, stdout);
+        printf("'\n");
+    }
+#endif
+#endif
+    return tok;
+}
+/**
+ * question the next token but don't move lexer forward
+ */
+int 
+jer::json_lex_peek(size_t &offset,const unsigned char **outbuf, size_t &outlen)
+{
+  return 1;
+}
+
+
+/* 
+ * vim:et:sw=2:ts=2
+ */
+/* end of namespace */
+}
+}
diff --git a/rtasn1/asn1_codec_jer.h b/rtasn1/asn1_codec_jer.h
new file mode 100644 (file)
index 0000000..8f20263
--- /dev/null
@@ -0,0 +1,275 @@
+#ifndef CODEC_JER_H
+#define CODEC_JER_H
+#include <iostream>
+
+#if defined(__GNUC__) && defined(DEBUG) & not(defined(ASN1_BER_LOG_DEBUG))
+#define ASN1_BER_LOG_DEBUG(fmt,args...) do {\
+  fprintf(stderr,fmt,##args);\
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\
+} while (0)
+#elseif not(defined(ASN1_BER_LOG_DEBUG)) 
+  static inline void ASN1_BER_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+#endif
+
+namespace asn1 {
+class context;
+
+
+
+
+namespace streams {
+
+/**
+ * Should not be in codecs namespace.
+ * It's a jer context used by the jer codec. 
+ */
+class jer  : public asn1::context
+{
+  public:
+    enum jer_token { 
+        jer_tok_bool
+      , jer_tok_colon
+      , jer_tok_comma
+      , jer_tok_eof
+      , jer_tok_error
+      , jer_tok_left_brace
+      , jer_tok_left_bracket
+      , jer_tok_null
+      , jer_tok_right_brace
+      , jer_tok_right_bracket
+      /* */
+      , jer_tok_integer 
+      , jer_tok_double 
+      , jer_tok_string 
+      , jer_tok_string_with_escapes 
+      , jer_tok_comment
+    };
+
+    enum jer_lex_error {
+       jer_err_ok = 0
+      ,jer_err_string_invalid_utf8
+      ,jer_err_string_invalid_escaped_char
+      ,jer_err_string_invalid_json_char
+      ,jer_err_string_invalid_hex_char
+      ,jer_err_invalid_string
+      ,jer_err_invalid_char
+      /* Missing error codes for numbers*/
+      ,jer_err_unallowed_comment
+      ,jer_err_missing_integer_after_minus
+      ,jer_err_missing_integer_after_decimal
+      ,jer_err_missing_integer_after_exponent
+    };
+
+    jer( int sz = 512) ;
+    jer(unsigned char *buf, int sz = 512) ;
+    jer(const jer &c) ;
+    ~jer() {}
+    
+    virtual int decode_tag(asn1::tag &t) ;
+
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) ;
+    virtual int decode_null(asn1::Null &b) ;
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) ;
+    virtual int decode_boolean(asn1::BOOLEAN &b) ;
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) ;
+    virtual int decode_integer(asn1::INTEGER &b) ;
+    int decode_integer(asn1::UInt64 &b) ;
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) ;
+    virtual int decode_bitstring(asn1::BIT_STRING &b) ;
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) ;
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) ;
+    
+    virtual void encode_string(const asn1::types::type &b) ;
+    virtual int decode_string(asn1::types::type &b) ;
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) ;
+    virtual int decode_choice(asn1::types::choice_type &b) ;
+
+    // Sequence
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) ;
+       
+    /**
+     * When reading jer, we need to be able to decode the length 
+     */
+    bool decode_tag( asn1::tag &t, int &len);
+    
+    bool decode_header(const asn1::tag &tag,int &len);
+    /**/
+    void put_string(const std::string &s);
+    /**/
+    void put_char(const unsigned char *s,size_t len);
+    
+    void put_char(const char *s,size_t len);
+
+    /**
+     * retrieve token. If the lexer parses token
+     *  return true or else return false and leave
+     *  m_bufOff unchanged.
+     */
+    bool get_token(const char *);
+    bool get_token(jer_token tok);
+    bool get_token(std::string &s);
+
+    inline void put_field(const char *s,size_t len)
+    { put_char("\"",1); put_char(s,len); put_char("\"",1); };
+    /* json specifique functions code */
+    const char *error_to_string(int i) const;
+    /* get current offset into the most recently lexed json string */
+    inline size_t current_offset() const  { return m_bufOff;  };
+    /* number of char lexed  */
+    inline size_t current_char()   const  { return m_charOff; };
+    /* number of lines lexed */
+    inline size_t current_line()   const  { return m_lineOff; };
+
+    friend std::ostream &operator<<(std::ostream &os,const jer &_jer)
+    {
+      os<<(char *)const_cast< jer &>(_jer).buffer(); return os;
+    }
+  protected:
+    /* To be reviewed */
+    inline unsigned char readChar()
+    {return (m_bufOff < get_size() ? *(m_buffer + m_bufOff++) : *m_buffer); };
+    /* To be reviewed */
+    inline unsigned char readChar(const unsigned char *c,size_t &offset)
+    {return c[offset++]; };
+
+    inline size_t unreadChar(size_t &off)          { return (off>0)?off--:m_bufOff--; };
+    /**
+     * do i need encode_header for jer ?
+     */
+    void encode_header(const asn1::types::type &obj, int &len);
+
+    const char * tok2str(int tok) const;
+    /**
+     * analyse,lex buffer and return appropriate token
+     * this function can be invoked several times until eof.
+     */ 
+    int json_lex(size_t &offset,unsigned char **outbuf, size_t &outlen);
+    /**
+     * question the next token but don't move lexer forward
+     */
+    int json_lex_peek(size_t &offset,const unsigned char **outbuf, size_t &outlen);
+    
+    jer_token lex_string(const unsigned char *,size_t,size_t &offset);
+    
+    jer_token lex_number(const unsigned char *,size_t,size_t &offset);
+    
+    jer_token lex_comment(const unsigned char *,size_t,size_t &offset);
+    /* Offset local variables */
+    size_t m_lineOff;
+    size_t m_charOff;
+    /** Current offset into lex buffer */
+    size_t m_bufOff;
+    bool   m_allowComments;
+    // There is no way to get parent so may use a stack to push/pop parent element
+    jer_lex_error m_error;
+}; /* end jer class */
+
+} /* end streams  namespace */
+
+/**
+ * 
+ * How will codecJER look like ?
+ */
+  
+  class codecJER : public codec
+  {
+    protected:
+
+    public:
+      codecJER() {}
+
+      template <class T>
+      void encode(streams::jer &ctx,const T &t) ;
+      
+      template <class T>
+      int decode(streams::jer &ctx, T &t) ;
+
+      /* Special case for Sequence OF */
+      template <class T>
+      void encode(streams::jer &ctx,const asn1::Seq<T> &t)
+      {
+        typename asn1::Seq<T>::const_iterator mit = t.begin();
+        for (; mit != t.end() ; ++mit)
+        {
+          if (mit != t.begin()) 
+            ctx.put_char(", ",2);
+          encode(ctx,(*mit));
+        }
+      }
+
+      template <class T>
+      int decode(streams::jer &ctx,asn1::Seq<T> &t)
+      {
+        T element;
+        int ret;
+        if ( ! ctx.get_token(streams::jer::jer_tok_left_brace))
+        {
+
+          std::cerr<<"decode sequenceof non left brace aiee"<<std::endl;
+          return asn1::wrong_type;
+        }
+        do {
+          if ((ret = decode(ctx,element)) == asn1::ok)
+          {
+            t.push_back(element);
+//            For debug purpose
+//            std::cout<<"decode added 1 element "<<typeid(element).name()<<"Seq <T> size ="<<t.size()<<std::endl;
+          } else
+          {
+            break;
+          }
+        } while (ctx.get_token(streams::jer::jer_tok_comma));
+        if ( ! ctx.get_token(streams::jer::jer_tok_right_brace))
+        {
+          std::cerr<<"decode sequenceof non right brace aiee"<<std::endl;
+          return asn1::wrong_type;
+        }
+        return asn1::ok;
+      }
+
+      // Need to provide implementation
+      // For base Types, INTEGER, BOOLEAN...
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      void encode_jer(::asn1::streams::jer &ctx, const asn1::Asn1Type &t); \
+      int \
+      decode_jer(::asn1::streams::jer &ctx, asn1::Asn1Type &t);
+#include "rtasn1/asn1_types.inc"
+  }; /* end codecJER */ 
+
+/* encode / decode specialization declaration */
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecJER::encode(streams::jer &ctx, const asn1::Asn1Type &t) \
+      ; \
+      template <> \
+      int \
+      codecJER::decode(streams::jer &ctx, asn1::Asn1Type &t) \
+      ;
+#include "rtasn1/asn1_types.inc"
+
+
+}
+
+#endif
+/*
+ * vim: et sw=2 ts=2 :
+ */ 
diff --git a/rtasn1/asn1_codec_oer.cpp b/rtasn1/asn1_codec_oer.cpp
new file mode 100644 (file)
index 0000000..2122429
--- /dev/null
@@ -0,0 +1,456 @@
+#include <iostream>
+#include <string>
+#include <typeinfo>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_context.h"
+
+#include "rtasn1/asn1_codec_oer.h"
+
+/*
+vim:et:sw=2:ts=2
+ */
+namespace asn1 {
+
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecOER::encode(streams::oer &ctx, const asn1::Asn1Type &t) \
+      {  std::cerr<<"codecOER::"<<__FUNCTION__<<"  good "; \
+         std::cerr<<#Asn1Type<<std::endl; \
+         encode_oer(ctx,t);\
+      } \
+      template <> \
+      int \
+      codecOER::decode(streams::oer &ctx, asn1::Asn1Type &t) \
+      {  std::cerr<<"codecOER::"<<__FUNCTION__<<" good ";    \
+         std::cerr<<#Asn1Type<<std::endl;\
+         return decode_oer(ctx,t);\
+      }
+#include "rtasn1/asn1_types.inc"
+
+
+#define ASN1_CODEC_IMPL(Type,Encode,Decode) \
+void codecOER::encode_oer(streams::oer &ctx,const asn1::Type &t) \
+Encode \
+int codecOER::decode_oer(streams::oer &ctx,asn1::Type &t) \
+Decode
+       
+ASN1_CODEC_IMPL(BOOLEAN,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(INTEGER,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int8,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int16,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Int32,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt8,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt16,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UInt32,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(BIT_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(OCTET_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(Null,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#if 0
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+#else
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER_NG,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+#endif
+ASN1_CODEC_IMPL(EXTERNAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralizedTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UTCTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(REAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(ENUMERATED,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+// typedef asn1::types::any_type ANY;
+ASN1_CODEC_IMPL(UTF8String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(NumericString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(PrintableString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(TeletexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VideotexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(IA5String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GraphicString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(VisibleString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(GeneralString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(UniversalString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+ASN1_CODEC_IMPL(BMPString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return asn1::ok;
+})
+
+
+
+namespace streams {
+
+
+
+oer::oer(int sz) : asn1::context(sz)
+{
+  ASN1_BER_LOG_DEBUG("oer::oer  %d ",sz);
+}
+
+oer::oer(const oer &_codec) : asn1::context()
+{
+  ASN1_BER_LOG_DEBUG("oer::oer(const ber &_codec )  ");
+}
+
+
+// Null
+// 5
+void oer::encode_null(const asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::encode Null tag=%d  ",b.tag().byte());
+}
+
+int oer::decode_null(asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::decode Null  ");
+    
+  return asn1::ok;
+}
+
+
+// Bool
+//
+void oer::encode_boolean(const asn1::BOOLEAN &b) 
+{
+  int len = 1;
+  ASN1_BER_LOG_DEBUG("oer::encode boolean tag=%d",b.tag().byte());
+}
+
+int oer::decode_boolean(asn1::BOOLEAN &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::decode boolean tag=%d",b.tag().byte());
+  return asn1::ok;
+}
+
+
+// Integer
+//
+void oer::encode_integer(const asn1::types::type &b) 
+{
+  int len = 0;
+
+  const asn1::prim::types::Integer &i = dynamic_cast< const asn1::prim::types::Integer &>(b); 
+  long  integer = i.get_value();
+  int intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+  
+  ASN1_BER_LOG_DEBUG("oer::encode integer tag=%d  value=%ld intsize=%d decale =%d",b.tag().byte(),(long)i.get_value(),(int)intsize,(intsize<<3));
+  
+}
+
+/**
+ * Decode Integer 
+ */
+int oer::decode_integer(asn1::INTEGER &t) 
+{
+  int len       = 0;
+  int result    = 0;
+  
+  ASN1_BER_LOG_DEBUG("oer::decode integer tag=%d",t.tag().byte());
+  return asn1::ok;
+}
+
+
+// Bit String
+//
+void oer::encode_bitstring(const asn1::BIT_STRING &t) 
+{
+  int len = t.size() + 1;
+  ASN1_BER_LOG_DEBUG("oer::encode bit string len=%d ",len);
+}
+
+int oer::decode_bitstring(asn1::BIT_STRING &t) 
+{
+  ASN1_BER_LOG_DEBUG("oer::decode bit string tag=%d ",t.tag().byte());
+  return asn1::ok;
+}
+
+
+// Octet string
+//
+void oer::encode_octetstring(const asn1::OCTET_STRING &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::encode octet string tag=%d",b.tag().byte());
+}
+
+int oer::decode_octetstring(asn1::OCTET_STRING &b_) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::decode octet string TODO ");
+  return asn1::ok;
+}
+
+void oer::encode_string(const asn1::types::type &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::encode string tag=%d",b.tag().get_id());
+  const asn1::prim::types::String &s = dynamic_cast< const asn1::prim::types::String &>(b); 
+  len = ((std::string)s.get_value()).size(); // Length
+  //encode_header(b.type::tag(),len);
+
+  unsigned long pos = bytes();
+  unsigned char *buf  = buffer();
+  
+}
+
+
+int oer::decode_string(asn1::types::type &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::decode  string tag_id=%d",b.tag().get_id());
+  asn1::prim::types::String &s = dynamic_cast<asn1::prim::types::String &>(b); 
+  
+  return asn1::ok;
+}
+
+
+// Choice
+//
+void oer::encode_choice(asn1::types::choice_type &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("oer::encode choice ");
+}
+
+int oer::decode_choice(asn1::types::choice_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("oer::decode choice ");
+  return asn1::ok;
+}
+
+
+// Sequence
+void oer::encode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len = 0;
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  ASN1_BER_LOG_DEBUG("oer::encode sequence preamble tag=%d",b.tag().byte());
+}
+void oer::encode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("oer::encode sequence epilogue tag=%d",b.tag().byte());
+}
+
+
+int oer::decode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len;
+  std::string n = typeid(b).name();
+  ASN1_BER_LOG_DEBUG("oer::decode sequence preable %s",n.c_str());
+    
+  //return b.decode_preamble_ber(*this);
+  return asn1::ok;
+}
+
+int oer::decode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  //return b.decode_epilogue_ber(*this);
+  return asn1::ok;
+}
+   
+
+//
+void oer::encode_header(const asn1::types::type &obj, int &len)
+{
+  asn1::tag t = obj.tag();
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  
+  ASN1_BER_LOG_DEBUG("oer::encode_header code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+}
+    
+
+bool oer::decode_header(const asn1::tag &tag,int &len)
+{
+  return true;
+}
+
+
+
+/* 
+ * vim:et:sw=2:ts=2
+ */
+/* end of namespace */
+}
+}
diff --git a/rtasn1/asn1_codec_oer.h b/rtasn1/asn1_codec_oer.h
new file mode 100644 (file)
index 0000000..dffe72e
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef CODEC_OER_H
+#define CODEC_OER_H
+#include <iostream>
+
+#if defined(__GNUC__) && defined(DEBUG) & not(defined(ASN1_BER_LOG_DEBUG))
+#define ASN1_BER_LOG_DEBUG(fmt,args...) do {\
+  fprintf(stderr,fmt,##args);\
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\
+} while (0)
+#elseif not(defined(ASN1_BER_LOG_DEBUG)) 
+  static inline void ASN1_BER_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+#endif
+
+namespace asn1 {
+class context;
+
+
+
+
+namespace streams {
+//#define DEBUG
+/**
+ *
+ */
+
+class oer  : public asn1::context
+{
+  public:
+    oer( int sz = 512) ;
+    oer(const oer &c) ;
+    ~oer() {}
+    
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) ;
+    virtual int decode_null(asn1::Null &b) ;
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) ;
+    virtual int decode_boolean(asn1::BOOLEAN &b) ;
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) ;
+    virtual int decode_integer(asn1::INTEGER &b) ;
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) ;
+    virtual int decode_bitstring(asn1::BIT_STRING &b) ;
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) ;
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) ;
+    
+    virtual void encode_string(const asn1::types::type &b) ;
+    virtual int decode_string(asn1::types::type &b) ;
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) ;
+    virtual int decode_choice(asn1::types::choice_type &b) ;
+
+    // Sequence
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) ;
+       
+    /**
+     * When reading ber, we need to be able to decode the length 
+     */
+    bool decode_tag( asn1::tag &t, int &len);
+    
+    bool decode_header(const asn1::tag &tag,int &len);
+  protected:
+    void encode_header(const asn1::types::type &obj, int &len);
+    // There is no way to get parent so may use a stack to push/pop parent element
+};
+
+}
+
+/**
+ * 
+ * How will codecBER look like ?
+ */
+  
+  class codecOER : public codec
+  {
+    protected:
+
+    public:
+      codecOER() {}
+
+      template <class T>
+      void encode(streams::oer &ctx,const T &t) ;
+
+      template <class T>
+      int decode(streams::oer &ctx, T &t) ;
+      // Need to provide implementation
+      // For base Types, INTEGER, BOOLEAN...
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      void encode_oer(streams::oer &ctx, const asn1::Asn1Type &t); \
+      int \
+      decode_oer(streams::oer &ctx, asn1::Asn1Type &t);
+#include "rtasn1/asn1_types.inc"
+  }; 
+
+/* encode / decode specialization declaration */
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecOER::encode(streams::oer &ctx, const asn1::Asn1Type &t) \
+      ; \
+      template <> \
+      int \
+      codecOER::decode(streams::oer &ctx, asn1::Asn1Type &t) \
+      ;
+#include "rtasn1/asn1_types.inc"
+
+
+}
+
+#endif
+/*
+ * vim: et sw=2 ts=2 :
+ */ 
diff --git a/rtasn1/asn1_codec_per.cpp b/rtasn1/asn1_codec_per.cpp
new file mode 100644 (file)
index 0000000..3cbb2b0
--- /dev/null
@@ -0,0 +1,469 @@
+#include <iostream>
+#include <string>
+#include <typeinfo>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_context.h"
+
+#include "rtasn1/asn1_codec_per.h"
+
+/*
+vim:et:sw=2:ts=2
+ */
+namespace asn1 {
+
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecPER::encode(codecs::per &ctx, const asn1::Asn1Type &t) \
+      {  std::cerr<<"codecPER::"<<__FUNCTION__<<"  good "; \
+         std::cerr<<#Asn1Type<<std::endl; \
+         encode_per(ctx,t);\
+      } \
+      template <> \
+      asn1::Asn1Type & \
+      codecPER::decode(codecs::per &ctx, asn1::Asn1Type &t) \
+      {  std::cerr<<"codecPER::"<<__FUNCTION__<<" good ";    \
+         std::cerr<<#Asn1Type<<std::endl;\
+         return decode_per(ctx,t);\
+      }
+#include "rtasn1/asn1_types.inc"
+
+
+#define ASN1_CODEC_IMPL(Type,Encode,Decode) \
+void codecPER::encode_per(codecs::per &ctx,const asn1::Type &t) \
+Encode \
+asn1::Type &codecPER::decode_per(codecs::per &ctx,asn1::Type &t) \
+Decode
+       
+ASN1_CODEC_IMPL(BOOLEAN,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(INTEGER,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(Int8,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(Int16,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(Int32,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+//
+ASN1_CODEC_IMPL(Int64,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UInt8,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UInt16,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UInt32,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UInt64,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(BIT_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(OCTET_STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(STRING,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(Null,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+#if 0
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+#else
+ASN1_CODEC_IMPL(OBJECT_IDENTIFIER_NG,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+#endif
+ASN1_CODEC_IMPL(EXTERNAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(GeneralizedTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UTCTime,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(REAL,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(ENUMERATED,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+// typedef asn1::types::any_type ANY;
+ASN1_CODEC_IMPL(UTF8String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(NumericString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(PrintableString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(TeletexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(VideotexString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(IA5String,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(GraphicString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(VisibleString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(GeneralString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(UniversalString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+ASN1_CODEC_IMPL(BMPString,
+{
+  std::cout<<__FUNCTION__<<" TODO"<<std::endl;
+},
+{
+  return t;
+})
+
+
+
+namespace codecs {
+
+
+
+per::per(int sz) : asn1::context(sz)
+{
+  ASN1_BER_LOG_DEBUG("per::per  %d ",sz);
+}
+
+per::per(const per &_codec) : asn1::context()
+{
+  ASN1_BER_LOG_DEBUG("per::per(const ber &_codec )  ");
+}
+
+
+// Null
+// 5
+void per::encode_null(const asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::encode Null tag=%d  ",b.tag().byte());
+}
+
+int per::decode_null(asn1::Null &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::decode Null  ");
+    
+  return asn1::ok;
+}
+
+
+// Bool
+//
+void per::encode_boolean(const asn1::BOOLEAN &b) 
+{
+  int len = 1;
+  ASN1_BER_LOG_DEBUG("per::encode boolean tag=%d",b.tag().byte());
+}
+
+int per::decode_boolean(asn1::BOOLEAN &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::decode boolean tag=%d",b.tag().byte());
+  return asn1::ok;
+}
+
+
+// Integer
+//
+void per::encode_integer(const asn1::types::type &b) 
+{
+  int len = 0;
+
+  const asn1::prim::types::Integer &i = dynamic_cast< const asn1::prim::types::Integer &>(b); 
+  long  integer = i.get_value();
+  int intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+  
+  ASN1_BER_LOG_DEBUG("per::encode integer tag=%d  value=%ld intsize=%d decale =%d",b.tag().byte(),(long)i.get_value(),(int)intsize,(intsize<<3));
+  
+}
+
+/**
+ * Decode Integer 
+ */
+int per::decode_integer(asn1::INTEGER &t) 
+{
+  int len       = 0;
+  int result    = 0;
+  
+  ASN1_BER_LOG_DEBUG("per::decode integer tag=%d",t.tag().byte());
+  return asn1::ok;
+}
+
+
+// Bit String
+//
+void per::encode_bitstring(const asn1::BIT_STRING &t) 
+{
+  int len = t.size() + 1;
+  ASN1_BER_LOG_DEBUG("per::encode bit string len=%d ",len);
+}
+
+int per::decode_bitstring(asn1::BIT_STRING &t) 
+{
+  ASN1_BER_LOG_DEBUG("per::decode bit string tag=%d ",t.tag().byte());
+  return asn1::ok;
+}
+
+
+// Octet string
+//
+void per::encode_octetstring(const asn1::OCTET_STRING &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::encode octet string tag=%d",b.tag().byte());
+}
+
+int per::decode_octetstring(asn1::OCTET_STRING &b_) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::decode octet string TODO ");
+  return asn1::ok;
+}
+
+void per::encode_string(const asn1::types::type &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::encode string tag=%d",b.tag().get_id());
+  const asn1::prim::types::String &s = dynamic_cast< const asn1::prim::types::String &>(b); 
+  len = ((std::string)s.get_value()).size(); // Length
+  //encode_header(b.type::tag(),len);
+
+  unsigned long pos = bytes();
+  unsigned char *buf  = buffer();
+  
+}
+
+
+int per::decode_string(asn1::types::type &b)
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::decode  string tag_id=%d",b.tag().get_id());
+  asn1::prim::types::String &s = dynamic_cast<asn1::prim::types::String &>(b); 
+  
+  return asn1::ok;
+}
+
+
+// Choice
+//
+void per::encode_choice(asn1::types::choice_type &b) 
+{
+  int len = 0;
+  ASN1_BER_LOG_DEBUG("per::encode choice ");
+}
+
+int per::decode_choice(asn1::types::choice_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("per::decode choice ");
+  return asn1::ok;
+}
+
+
+// Sequence
+void per::encode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len = 0;
+  unsigned long pos = bytes();
+  unsigned char *bu = buffer();
+  ASN1_BER_LOG_DEBUG("per::encode sequence preamble tag=%d",b.tag().byte());
+}
+void per::encode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  ASN1_BER_LOG_DEBUG("per::encode sequence epilogue tag=%d",b.tag().byte());
+}
+
+
+int per::decode_sequence_preamble(asn1::types::sequence_type &b) 
+{
+  int len;
+  std::string n = typeid(b).name();
+  ASN1_BER_LOG_DEBUG("per::decode sequence preable %s",n.c_str());
+    
+  //return b.decode_preamble_ber(*this);
+  return asn1::ok;
+}
+
+int per::decode_sequence_epilogue(asn1::types::sequence_type &b) 
+{
+  //return b.decode_epilogue_ber(*this);
+  return asn1::ok;
+}
+   
+
+//
+void per::encode_header(const asn1::types::type &obj, int &len)
+{
+  asn1::tag t = obj.tag();
+  unsigned long pos = bytes();
+  unsigned char *b  = buffer();
+  
+  ASN1_BER_LOG_DEBUG("per::encode_header code tag: cls=%d id=%d ",t.get_class(),t.get_id());
+  // Encode Tag, check the tag value ....
+}
+    
+bool per::decode_header(const asn1::tag &tag,int &len)
+{
+  return true;
+}
+
+
+
+/* 
+ * vim:et:sw=2:ts=2
+ */
+/* end of namespace */
+}
+}
diff --git a/rtasn1/asn1_codec_per.h b/rtasn1/asn1_codec_per.h
new file mode 100644 (file)
index 0000000..292c408
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef CODEC_PER_H
+#define CODEC_PER_H
+#include <iostream>
+
+#if defined(__GNUC__) && defined(DEBUG) & not(defined(ASN1_BER_LOG_DEBUG))
+#define ASN1_BER_LOG_DEBUG(fmt,args...) do {\
+  fprintf(stderr,fmt,##args);\
+  fprintf(stderr," (asn1.y : %d)\n",__LINE__);\
+} while (0)
+#elseif not(defined(ASN1_BER_LOG_DEBUG)) 
+  static inline void ASN1_BER_LOG_DEBUG(const char *fmt,...) {(void)fmt;};
+#endif
+
+namespace asn1 {
+class context;
+
+
+
+
+namespace codecs {
+//#define DEBUG
+/**
+ *
+ */
+
+class per  : public asn1::context
+{
+    public:
+    per( int sz = 512) ;
+    per(const per &c) ;
+    ~per() {}
+    
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) ;
+    virtual int decode_null(asn1::Null &b) ;
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) ;
+    virtual int decode_boolean(asn1::BOOLEAN &b) ;
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) ;
+    virtual int decode_integer(asn1::INTEGER &b) ;
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) ;
+    virtual int decode_bitstring(asn1::BIT_STRING &b) ;
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) ;
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) ;
+    
+    virtual void encode_string(const asn1::types::type &b) ;
+    virtual int decode_string(asn1::types::type &b) ;
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) ;
+    virtual int decode_choice(asn1::types::choice_type &b) ;
+
+    // Sequence
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) ;
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) ;
+       
+    /**
+     * When reading ber, we need to be able to decode the length 
+     */
+    
+    bool decode_header(const asn1::tag &tag,int &len);
+    protected:
+    void encode_header(const asn1::types::type &obj, int &len);
+    // There is no way to get parent so may use a stack to push/pop parent element
+};
+
+}
+
+/**
+ * 
+ * How will codecPER look like ?
+ */
+  
+  class codecPER : public codec
+  {
+    protected:
+
+    public:
+      codecPER() {}
+
+      template <class T>
+      void encode(codecs::per &ctx,const T &t) ;
+
+      template <class T>
+      T& decode(codecs::per &ctx, T &t) ;
+      // Need to provide implementation
+      // For base Types, INTEGER, BOOLEAN...
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      void encode_per(codecs::per &ctx, const asn1::Asn1Type &t); \
+      asn1::Asn1Type & \
+      decode_per(codecs::per &ctx, asn1::Asn1Type &t);
+#include "rtasn1/asn1_types.inc"
+  }; 
+
+/* encode / decode specialization declaration */
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)       \
+      template <> \
+      void codecPER::encode(codecs::per &ctx, const asn1::Asn1Type &t) \
+      ; \
+      template <> \
+      asn1::Asn1Type & \
+      codecPER::decode(codecs::per &ctx, asn1::Asn1Type &t) \
+      ;
+#include "rtasn1/asn1_types.inc"
+
+
+}
+
+#endif
+/*
+ * vim: et sw=2 ts=2 :
+ */ 
diff --git a/rtasn1/asn1_config.h.in b/rtasn1/asn1_config.h.in
new file mode 100644 (file)
index 0000000..880afc4
--- /dev/null
@@ -0,0 +1,20 @@
+#cmakedefine HAVE_UNISTD_H
+#cmakedefine HAVE_STDLIB_H
+#cmakedefine HAVE_PTHREAD_H
+#cmakedefine HAVE_DIRECT_H
+#cmakedefine HAVE_STDINT_H
+/* system function check*/
+#cmakedefine HAVE_GETCWD
+#cmakedefine HAVE_MKDIR
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
diff --git a/rtasn1/asn1_context.cpp b/rtasn1/asn1_context.cpp
new file mode 100644 (file)
index 0000000..f706106
--- /dev/null
@@ -0,0 +1,125 @@
+#include <iostream>
+#include <string>
+
+#include "rtasn1/asn1_errors.h"
+#include "asn1.h"
+#include "asn1_codec.h"
+#include "asn1_context.h"
+/*
+ * ** Translation Table as described in RFC1113
+ * */
+static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*
+ * ** Translation Table to decode (created by author)
+ * */
+static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+
+namespace asn1 {
+
+/**
+ * Default constructor
+ */
+context::context(size_t size) : m_bits(0),m_check_tag(true),m_managed(true) 
+ , m_size(size)
+#ifdef WITH_CODEC
+ , asn1::context_base()
+#endif
+
+{
+       m_buffer = (unsigned  char *)malloc(size);
+       memset(m_buffer,0x00,size);
+};
+
+context::context(unsigned char *b,size_t size) : m_bits(0),m_buffer(b),m_check_tag(true),m_managed(false) 
+ , m_size(size)
+#ifdef WITH_CODEC
+ , asn1::context_base()
+#endif
+{
+};
+
+context::context(const context &c) 
+#ifdef WITH_CODEC
+ : asn1::context_base()
+#endif
+{
+       ;
+}
+
+context::~context() 
+{
+  if (types::debug_level> 6) 
+  {
+    if (m_bits != 0)
+    {
+      std::cout<<" context::"<<__FUNCTION__<<" coded: "<<m_bits<<" bits "<<std::endl;
+      for (int i = 0 ; i< m_bits/ 8 ;i++)
+      {
+        printf("%02x ",m_buffer[i]);
+        if ( ( (i % 32) == 0 ) && ( i != 0))
+          std::cout<<std::endl;
+      }
+      std::cout<<std::endl;
+    }
+  }   
+  if (m_managed)
+    free(m_buffer);
+}
+
+// Decode base 64 buffer and assign it internally for further 
+// asn1 decoding
+void 
+context::set_base64(const std::string &str)
+{
+    long size = str.size()/4 * 3 + 1;
+}
+
+// Encode the encoded buffer into asn1
+void 
+context::get_base64(std::string &str)
+{
+    int count = 0;
+    unsigned char *p = buffer();
+    unsigned char *end = buffer()+bytes();
+
+    long size = ( (bytes() - 1) /3) * 4 + 4;
+    
+    str.resize(size);
+    unsigned char *out = (unsigned char *)(const_cast<char *>(str.c_str()));
+    while (p < end)
+    {
+       if (p+3 < end) {
+         encode_base64_block(p,out,0);
+         p+=3; out+=4;
+       } else
+       {
+         encode_base64_block(p,out,end-p);
+         p+= (end-p);
+       }
+    }
+
+
+}
+    
+void 
+context::encode_base64_block(unsigned char *in,unsigned char *out,int len)
+{
+    out[0] = (unsigned char) cb64[ (int)(in[0] >> 2) ];
+    out[1] = (unsigned char) cb64[ (int)(((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) ];
+    out[2] = (unsigned char) (len > 1 ? cb64[ (int)(((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) ] : '=');
+    out[3] = (unsigned char) (len > 2 ? cb64[ (int)(in[2] & 0x3f) ] : '=');
+    ;
+}
+    
+    
+void 
+context::decode_base64_block(unsigned char *in,unsigned char *out,int len)
+{
+    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
+    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
+    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
+}
+
+}
diff --git a/rtasn1/asn1_context.h b/rtasn1/asn1_context.h
new file mode 100644 (file)
index 0000000..10528fb
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef ASN1_CONTEXT_H__
+#define ASN1_CONTEXT_H__
+#include <stdio.h>
+#include <iostream>
+# include <string.h>
+#if defined (__APPLE_CC__)
+# include <stdlib.h>
+#else
+# include "malloc.h"
+#endif
+#include "rtasn1/asn1.h"
+
+namespace asn1 {
+  namespace types {
+extern int debug_level;
+  }
+};
+
+namespace asn1 {
+
+/**
+ *
+ * Futur Abstract Class to decode/encode primitive types 
+ *
+ */
+class context_base {
+
+  public:
+    context_base()  {};
+    
+    virtual int decode_tag(asn1::tag &t) = 0;
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) = 0;
+    virtual int decode_null(asn1::Null &b) = 0;
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) = 0;
+    virtual int decode_boolean(asn1::BOOLEAN &b) = 0;
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) = 0;
+    virtual int decode_integer(asn1::INTEGER &b) = 0;
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) = 0;
+    virtual int decode_bitstring(asn1::BIT_STRING &b) = 0;
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) = 0;
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) = 0;
+    
+    virtual void encode_string(const asn1::types::strtype &b) = 0;
+    virtual int decode_string(asn1::types::strtype &b) = 0;
+    
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) = 0;
+    virtual int decode_choice(asn1::types::choice_type &b) = 0;
+
+    // Sequence
+    //
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) = 0;
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) = 0;
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) = 0;
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) = 0;
+
+    // Any
+    //
+    virtual void encode_any(const asn1::types::any_type &b) = 0;
+    virtual int decode_any(asn1::types::any_type &b) = 0;
+
+  private:
+    context_base(const context_base &c) {};
+
+  protected:
+};
+
+
+#define WITH_CODEC
+/**
+ * context object provides an enviromnent to codec function for reading
+ * and writing data.
+ * It must be able to provide the position in the buffer, the number for
+ * bits written.
+ *
+ *
+ */
+class context 
+#ifdef WITH_CODEC
+       : public ::asn1::context_base
+#endif
+{
+  private:
+    context(const context &c) ;
+    bool    m_managed; // Flag that helps to decide wether the buffer shall be deleted or not.
+  public:
+    
+    // Constructors
+    context(size_t size=512) ;
+    
+    context(unsigned char *b,size_t size);
+    
+
+    ~context() ;
+    
+    // base 64 set and get for fast ws usage
+    void set_base64(const std::string &str);
+
+    void get_base64(std::string &str);
+    //
+    inline bool check_tag() const {return m_check_tag;};
+    
+    inline void check_tag(bool _t)  {m_check_tag = _t;};
+
+
+    inline void nb_bits( long b) {m_bits+=b;} ;
+   
+    inline size_t get_size() const { return m_size; };
+
+    inline unsigned long nb_read_bits() {return m_bits;} ;
+    // This is something like get_position, set_position.    
+    inline unsigned long bytes() {return m_bits / 8;};
+
+    void bytes(unsigned long l) { m_bits = l * 8;};
+
+    inline unsigned char * buffer() {return m_buffer;};
+
+    inline void reset() { m_bits = 0 ;} ;
+#ifdef WITH_CODEC
+    virtual int decode_tag(asn1::tag &t) {return true;};
+    // Null
+    // 5
+    virtual void encode_null(const asn1::Null &b) { ; };
+    virtual int decode_null(asn1::Null &b) { return false; };
+
+    // Bool
+    //
+    virtual void encode_boolean(const asn1::BOOLEAN &b) { ; };
+    virtual int decode_boolean(asn1::BOOLEAN &b) { return asn1::unknown; };
+
+    // Integer
+    //
+    virtual void encode_integer(const asn1::types::type &b) { ; };
+    virtual int decode_integer(asn1::INTEGER &b) { return asn1::unknown; };
+    virtual int decode_integer(asn1::UInt64 &b) { return asn1::unknown; };
+
+    // Bit String
+    //
+    virtual void encode_bitstring(const asn1::BIT_STRING &b) { ; };
+    virtual int decode_bitstring(asn1::BIT_STRING &b) { return asn1::unknown; };
+    
+    // Octet string
+    //
+    virtual void encode_octetstring(const asn1::OCTET_STRING &b) { ; };
+    virtual int decode_octetstring(asn1::OCTET_STRING &b) { return asn1::unknown; };
+    virtual void encode_string(const asn1::types::strtype &b)  {};
+    virtual int decode_string(asn1::types::strtype &b) {return asn1::unknown;};
+    // Choice
+    //
+    virtual void encode_choice(asn1::types::choice_type &b) { ; };
+    virtual int decode_choice(asn1::types::choice_type &b) { return asn1::unknown; };
+    // Sequence
+    //
+    virtual void encode_sequence_preamble(asn1::types::sequence_type &b) { ; };
+    virtual void encode_sequence_epilogue(asn1::types::sequence_type &b) { ; };
+    virtual int decode_sequence_preamble(asn1::types::sequence_type &b) { return asn1::unknown; };
+    virtual int decode_sequence_epilogue(asn1::types::sequence_type &b) { return asn1::unknown; };
+
+
+    // Any
+    //
+    virtual void encode_any(const asn1::types::any_type &b) {};
+    virtual int decode_any(asn1::types::any_type &b) {return asn1::unknown;};
+#endif
+  protected:
+    void encode_base64_block(unsigned char *in,unsigned char *out,int len);
+    
+    void decode_base64_block(unsigned char *in,unsigned char *out,int len);
+
+  protected:
+    bool            m_check_tag;
+    long            m_bits;
+    unsigned char * m_buffer;
+    size_t          m_size;
+};
+
+
+}
+
+/*
+vim:et:sw=2:ts=2:
+ */
+#endif
diff --git a/rtasn1/asn1_debug.h b/rtasn1/asn1_debug.h
new file mode 100644 (file)
index 0000000..0b7efde
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef ASN1_DEBUG_H__
+#define ASN1_DEBUG_H__
+
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ *10000 \
+                     + __GNUC_MINOR__ * 100 \
+                     + __GNUC_PATCHLEVEL__ )
+#endif
+
+#if  defined(__APPLE__) || (GCC_VERSION > 40800)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+#if defined(_WIN32)
+# include <io.h>
+#endif
+
+
+namespace asn1 {
+  namespace types {
+       extern int debug_level;
+  }
+};
+
+#if defined(__GNUC__) && defined(DEBUG) && !defined(ASN1_BER_LOG_DEBUG)
+
+#define __MYFILE__ (strrchr(__FILE__,'/')?strrchr(__FILE__,'/')+1 : __FILE__)
+
+# define ASN1_BER_LOG_DEBUG(fmt,args...) do {\
+   if (::asn1::types::debug_level >= 7)  \
+   {   fprintf(stderr,fmt,##args);\
+        fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__); \
+   }  \
+} while (0);
+
+# define ASN1_BER_LOG_INFO(fmt,args...) do {\
+   if (::asn1::types::debug_level >= 3)  \
+   {  fprintf(stderr,fmt,##args);\
+     fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+   } \
+} while (0);
+
+# define ASN1_BER_LOG_ERROR(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+#elif defined(_WIN32) || defined(_WINDOWS)
+
+#define __MYFILE__ (strrchr(__FILE__,'/')?strrchr(__FILE__,'/')+1 : __FILE__)
+
+# define ASN1_BER_LOG_DEBUG(fmt,...) do {\
+   if (::asn1::types::debug_level >= 7)  \
+   {   fprintf(stderr,fmt,__VA_ARGS__);\
+        fprintf(stderr," (%s : %d)\n",__MYFILE__,__LINE__); \
+   }  \
+  } while (0);
+# define ASN1_BER_LOG_INFO(fmt,...) do {\
+  } while (0);
+# define ASN1_BER_LOG_ERROR(fmt,...) do {\
+   fprintf(stderr,fmt,__VA_ARGS__);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+  } while (0);
+#else
+// Not debug 
+# if not(defined(ASN1_BER_LOG_DEBUG))
+#   define ASN1_BER_LOG_DEBUG(fmt,...) \
+    do { } while (0); 
+# else
+  static inline void ASN1_BER_LOG_DEBUG(const char *fmt,...)
+  { 
+    (void)fmt;
+  };
+# endif
+
+#define ASN1_BER_LOG_INFO(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+# define ASN1_BER_LOG_ERROR(fmt,args...) do {\
+   fprintf(stderr,fmt,##args);\
+   fprintf(stderr," (%s : %d)\n",__FILE__,__LINE__);\
+} while (0);
+
+#endif
+
+#endif
diff --git a/rtasn1/asn1_errors.h b/rtasn1/asn1_errors.h
new file mode 100644 (file)
index 0000000..cf74d81
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef ASN1_ERRORS_H__
+#define ASN1_ERRORS_H__
+
+/**
+ * Liste the errors that can occur during parsing
+ */
+
+namespace asn1 {
+
+enum errors {
+  ok                = 0,
+  wrong_tag         = 1,
+  wrong_type        = 2,
+  wrong_length      = 3,
+  constraint_size   = 4,
+  incomplet         = 5,
+  unknown           = 6
+
+};
+
+};
+
+#endif
diff --git a/rtasn1/asn1_rose.h b/rtasn1/asn1_rose.h
new file mode 100644 (file)
index 0000000..22c1ff3
--- /dev/null
@@ -0,0 +1,239 @@
+#ifndef ASN1_ROSE_H__
+#define ASN1_ROSE_H__
+
+#include <typeinfo>
+#include <assert.h>
+namespace asn1 {
+
+
+// classes using intrusive pointers
+// must provide the folowing methodes
+//
+//   add_ref
+//   release
+//
+template <typename T>
+class intrusive_ptr
+{ 
+  public:
+    typedef T *   pointer;
+    typedef T &   reference;
+    intrusive_ptr(const asn1::tag &t = asn1::tag(0,0))
+       : m_ptr(NULL) , m_tag(t)
+    {
+//      ASN1_BER_LOG_DEBUG("intrusive_ptr<>::construct   tag= %d",m_tag.byte());
+    };
+    
+    intrusive_ptr( T* h)
+       : m_ptr(h) ,m_tag(h->tag())
+    {if (m_ptr != NULL) m_ptr->add_ref();};
+    
+    intrusive_ptr(const intrusive_ptr<T> & ht)
+       : m_tag(ht.m_tag) ,m_ptr(NULL)
+    {
+      ASN1_BER_LOG_DEBUG("intrusive_ptr<> copy  tag= %d <- %d ht.m_ptr=%0lx"
+                         , m_tag.byte()
+                         , ht.m_tag.byte()
+                         , (long)ht.m_ptr);
+      if (ht.m_ptr)
+      {
+        std::string name = typeid(*ht.m_ptr).name(); 
+        ASN1_BER_LOG_DEBUG("intrusive_ptr<> copied  %s",name.c_str());
+        m_ptr = ht.m_ptr;
+        m_ptr->add_ref();
+        m_tag = ht.m_tag;
+      }
+    };
+    pointer clone()
+    {
+       T *tp = new T(m_tag);
+       return tp;
+    }
+    void set_tag(const asn1::tag &t) { m_tag =t;}; 
+    inline void create(asn1::tag t = asn1::tag(0,0))
+    { 
+      if ( ! is_nul() )
+            m_ptr->release(); 
+      m_ptr =  new T();
+      if (t.byte() > 0 )
+      {
+        m_ptr->set_tag(t);
+      } else {
+        // This does not work at all with csta_insigth !!
+        // m_ptr->set_tag(m_tag);
+      }
+      m_ptr->add_ref();  
+    } ;
+
+    inline void release()
+    {
+       if (!is_nul() )
+       {
+            m_ptr->release();
+            m_ptr = NULL;
+       }
+    }
+    inline bool is_nul() const {return m_ptr == NULL;};
+    
+    intrusive_ptr<T> & operator =(const intrusive_ptr<T> &ht) 
+    {
+      if (m_ptr) m_ptr->release();
+      if (ht.m_ptr)
+      {
+          m_ptr = ht.m_ptr;
+          m_ptr->add_ref();
+      }
+      return *this;
+    };
+    
+    virtual ~intrusive_ptr() 
+    {
+       if (m_ptr)
+            m_ptr->release();
+        m_ptr = NULL;
+    };
+  
+    const asn1::tag &tag() const
+    {
+      static asn1::tag t(0,0);
+      if (m_ptr)
+        m_ptr->tag();
+      return t;
+    }
+    
+    bool primitive() const
+    {
+      if (m_ptr)
+        return m_ptr->primitive();
+      return false;
+    }
+
+    size_t get_length() const
+    {
+      if (m_ptr)
+        return m_ptr->get_length();
+      return 0;
+    }
+    void encode(asn1::context &ctx)
+    {
+      if (m_ptr)
+        m_ptr->encode(ctx);
+    }
+
+    int decode(asn1::context &ctx) 
+    {
+      ASN1_BER_LOG_DEBUG("intrusive_ptr<>::decode DECODE m_ptr=%ld",(long)m_ptr);
+      if (m_ptr)
+      {
+        int ret =  m_ptr->decode(ctx); 
+        if ( ret != asn1::ok)
+                release();
+        return ret;
+      } else
+      {
+        std::string name;
+        if (m_tag.byte() > 0) 
+        { 
+          m_ptr = new T(m_tag);
+        } else 
+          m_ptr = new T();
+        m_ptr->add_ref();
+        name = typeid(*m_ptr).name();
+        
+        int ret = this->m_ptr->decode(ctx);
+        if ( ret != asn1::ok)
+                release();
+        return ret;
+      }
+      return asn1::unknown;
+    }
+    //
+    pointer operator *( ) { return m_ptr;};
+    const pointer operator *( ) const{ return m_ptr;};
+    // cast operator
+    operator T *( ) { return m_ptr;};
+
+    reference get() 
+    { if (m_ptr == NULL ) create(m_tag); return *m_ptr; }
+
+    reference get()  const
+    { if (m_ptr == NULL ) assert(0); return *m_ptr; }
+    //
+    T* operator ->() {return m_ptr;};
+    const T* operator ->() const {return m_ptr;};
+
+    friend std::ostream & operator<<(std::ostream &os,const intrusive_ptr<T> &t)
+    {
+      if (! t.is_nul())
+      {
+        os<<"OPT"<<(*t.m_ptr);
+      } else
+        os<<" null ";
+      return os;
+    }
+  protected:
+   pointer m_ptr;
+   asn1::tag m_tag;
+};
+
+
+
+  // Generic class for object handling.
+// Not yet clear about how this will work.
+struct Object {
+  public:
+    typedef  asn1::intrusive_ptr<Object> ptr;
+    
+    Object() : m_ref(0) {/*std::cout<<"Build Object"<<std::endl;*/};
+    Object(const Object &_o) { /*std::cout<<"Build Object"<<std::endl;*/};
+    virtual ~Object() { };
+    
+    inline  void add_ref() {m_ref++;} 
+    inline  void release() {if (--m_ref == 0) delete this;}
+
+    inline 
+    Object &operator =(const Object &_o) {
+      std::cerr<<"Object operator = "<<typeid(_o).name()<<std::endl;
+      return *_o.clone();
+    };
+    // clone operation that will support covariant feature
+    virtual Object * clone()  const {
+      std::cout<<"Object::clone()"<<std::endl; 
+      return new Object(*this);
+    };
+
+    virtual void printf(std::ostream &os) const {};
+    
+    virtual void encode(asn1::context &ctx)
+    { }
+    
+    virtual int decode(asn1::context &ctx)
+    {
+      std::cout<<"Object::decode not good"<<std::endl;
+      return asn1::unknown;
+    };  
+    // To be checked if it will work
+    template <typename T>
+    void to_type(T &_t)
+    {_t = dynamic_cast<T &>(*this); };
+    
+    template <typename T>
+    void to_type(T *_t)
+    {_t = dynamic_cast<T *>(this); };
+  private:
+    int m_ref; // Ref counting
+};
+
+struct ObjectSetEntry
+{
+  ObjectSetEntry *m_next;
+  Object         *m_object;
+};
+
+
+}
+/*
+vim:et:sw=2:ts=2:
+ */
+#endif
diff --git a/rtasn1/asn1_tag.h b/rtasn1/asn1_tag.h
new file mode 100644 (file)
index 0000000..7494778
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef ASN1_TAG_H__
+#define ASN1_TAG_H__
+#include <iostream>
+namespace asn1
+{
+
+#define MAKE_TAG(CLS,C,ID ) ( (((CLS) & 0x03)<<6) |((C & 0x01)<<5) |((ID)&0x1F) )
+/* Don't use constructed info for tag comparisen */
+#define MAKE_LONG_TAG(CLS,C,ID ) ( (((CLS) & 0x03)) |((ID)<<2) )
+    /**
+     *
+     * The form below is the BER encoding.
+     *  8   7    6    5   4   3   2    1 
+     *  class | P/C | Tag Identifier
+     */
+struct  tag
+{
+  public:
+    inline void set_constructed() { m_constructed = true;};
+    
+    tag(int cls,int id,bool _c = false) : m_class(cls), m_id(id) ,m_constructed(_c)  {};
+    tag(unsigned char c) : m_class(0),m_id(0),m_constructed(false) { byte(c);};
+    tag(const tag &_t) : m_class(_t.m_class), m_id(_t.m_id) ,m_constructed(_t.m_constructed)  {};
+  
+    inline int get_class() const {return m_class; };
+    
+    inline int get_id() const {return m_id; };
+    
+    inline long get_tag() const {return ((m_id<<2) | m_class); };
+
+    inline bool get_constructed() const {return m_constructed; };
+
+    bool operator ==(const tag & t) const
+    { return m_id == t.m_id && m_class == t.m_class;}
+
+    bool operator ==(long l) const
+    {
+      return (m_id == (l>>2)) && (m_class == (l & 0x03));
+    } 
+
+    inline void byte(const unsigned char c) {
+        m_class = (0xC0 & c)>>6;
+        m_id    = (0x1F & c);
+        m_constructed = ((0x20&c)>>5) > 0;
+    };
+
+    // Don't use this function to be able to process tag numbers > 30
+    inline unsigned char byte() const 
+    { return MAKE_TAG(m_class,m_constructed,m_id); };
+  protected:
+    int     m_class;
+    int     m_id;
+    bool    m_constructed;
+};
+
+}
+
+#endif
diff --git a/rtasn1/asn1_types.cpp b/rtasn1/asn1_types.cpp
new file mode 100644 (file)
index 0000000..3a05922
--- /dev/null
@@ -0,0 +1,1164 @@
+#include <string>
+#include <typeinfo>
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_errors.h"
+#include "asn1_types.h"
+#include "rtasn1/asn1_context.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include <cassert>
+namespace asn1 {
+
+
+// Object Identifier
+std::ostream & operator << (std::ostream &os,const ObjectIdentifier &o)
+{
+  os<<"{"<<static_cast<const asn1::prim::types::ObjectIdentifier &>(o)<<"}";
+  return os;
+}
+
+} /* end namespace */
+/**
+ * REAL BEGIN 
+ */ 
+namespace asn1 {
+namespace types {
+
+int debug_level = 1;
+
+// Local static functions
+// computes the number of bits required for the given number (positive)
+size_t count_bits(unsigned range)
+{
+  switch (range)
+  {
+    case 0 :
+      return sizeof(unsigned)*8;
+    case 1:
+      return 1;
+  }
+  size_t _bits = 0;
+  while (_bits < (sizeof(unsigned)*8) && range > (unsigned)(1 << _bits))
+    _bits++;
+  return _bits;
+}
+/* test */
+const tag gTags[] = {
+    tag(1,1)
+  , tag(2,0)
+};     
+
+///////////////////////////////////////////////////////////////////////////////
+// CLASS type implementation
+///////////////////////////////////////////////////////////////////////////////
+
+
+type::type(int c ,int tid) 
+    : m_ref(0) , m_tag(c,tid) 
+{
+}
+
+type::type(const asn1::tag &t)
+  : m_ref(0) , m_tag(t) 
+{
+}
+
+type::type(const type &t)
+ : m_ref(0), m_tag(t.m_tag)    
+{
+    ;
+}
+
+type::~type()
+{
+}
+#if 0 
+  inline  void add_ref() {m_ref++;} 
+  
+  inline  void  release() {if (--m_ref == 0) delete this;}
+#endif 
+bool  type::primitive() const 
+{
+    return true;
+}
+#if 0
+int   
+type::get_data_length() const
+{
+    return 0;
+}
+#endif
+void  type::set_tag(const asn1::tag &t)
+{
+  if (!this->primitive())
+  {
+      m_tag = asn1::tag(t.get_class(),t.get_id(),true);
+  } else 
+      m_tag = t;
+}
+
+type  *
+type::clone()
+{
+  std::cerr<<"asn1::types::type::clone ERROR type here not good "<<std::endl;
+  return NULL;
+} // Needed for copy constructor choice
+
+
+// New encoding / decoding mechanism. I think codec is to bad
+void 
+type::encode(asn1::context &ctx)
+{
+  std::cerr<<"types::encode(ctx) BIG Issue"<<std::endl;
+};
+
+int  
+type::decode(asn1::context &ctx)
+{
+  std::cerr<<"types::decode(ctx) BIG Issue"<<std::endl;
+  return asn1::unknown;
+};
+
+const asn1::tag &
+type::tag() const 
+{
+  static asn1::tag t = asn1::tag(0,0)/*(C,I)*/;
+  if (m_tag.byte() > 0)
+  {
+    return m_tag;
+  } 
+  else 
+    return t;
+}
+
+void
+type::printf(std::ostream &os) const
+{
+    os<<"type::printf TODO";
+}
+
+size_t
+type::get_length() const
+{
+  size_t len = 1;
+  if (m_tag.get_id() > 31)
+         len += (count_bits(m_tag.get_id())+6)/7;
+   // add data_len field
+   size_t data_len = get_data_length();
+  if (data_len < 128)
+    len+= 1;
+  else
+    len+= (count_bits(data_len)+7)/8 + 1;
+  // return tag + len + data_len
+  return len + data_len;
+}
+
+
+/**
+ * used by decode functions
+ *
+ */
+long length(unsigned char *buf, long *readed)
+{
+        long result = 0;
+        long nb_octet =  *buf & 0x7f;
+        *readed = 1;
+        if ((*buf & 0x80) && (*buf & 0x7F)) {
+            // Long form number ...
+            *readed = (*buf & 0x7F) + 1;
+            buf++;
+       //     ASN1_BER_LOG_DEBUG("ber::length  nb_octet %d form :result = %ld readed=%ld buf-1=%02x buf=%02x",nb_octet,result,*readed,*(buf-1),*buf);
+            while (nb_octet-- ) {
+                result = (result<<8) | (*buf) ;
+                buf++;
+            }
+            ASN1_BER_LOG_DEBUG("asn1::types::length long form : value=%ld readed=%ld ",result,*readed);
+            return result;
+        } else if (!(*buf & 0x80) && (*buf & 0x7F)){
+            result = *buf & 0x7F;
+            // Short one byte
+            *readed = 1;
+            ASN1_BER_LOG_DEBUG("asn1::types::length short form :result=%ld readed=%ld",result,*readed);
+            return result;
+        } else if (*buf == 0) {
+            *readed = 1;
+            ASN1_BER_LOG_DEBUG("asn1::types::length: 0 ");
+            return 0;
+        }else {
+            // Indefinit form
+            std::cerr<<"asn1::types::length indefinit form not yet supported  TO BE CODED"<<std::endl;
+        }
+        return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// any_type implementation
+///////////////////////////////////////////////////////////////////////////////
+
+//
+//
+any_type::any_type(asn1::types::type *v )
+  : m_any(v)
+{
+}
+
+//
+//
+any_type::any_type(const asn1::types::type &v)
+  : m_any(NULL)
+{
+}
+
+//
+//
+any_type::~any_type()
+{
+}
+
+//
+//
+void
+any_type::encode(asn1::context &ctx)
+{
+  if (m_any ) 
+    m_any->encode(ctx);
+  ctx.encode_any(*this);
+}
+
+//
+//
+int
+any_type::decode(asn1::context &ctx)
+{
+  if (m_any ) 
+    return m_any->decode(ctx);
+  std::cerr<<"any_type::decode  TOBE CODED"<<std::endl;
+  ctx.decode_any(*this);
+  return asn1::ok;
+}
+
+//
+//
+bool 
+any_type::operator == (const any_type &_c) const
+{
+  std::cerr<<"any_type == TOBE CODED"<<std::endl;
+  return false;
+}
+
+//
+//
+const asn1::tag &
+any_type::tag() const
+{
+  if (m_any != NULL) 
+  {
+    return m_any->tag();
+  } else 
+    return m_tag;
+}
+
+} // end of namespace types
+
+///////////////////////////////////////////////////////////////////////////////
+// prim encode/decode specialized implementations
+///////////////////////////////////////////////////////////////////////////////
+
+// Boolean
+//
+static tag BOOLEAN_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,1)
+};
+const asn1::types::descriptor asn1::BOOLEAN::_meta = {
+    BOOLEAN_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+
+void BOOLEAN::encode(asn1::context &ctx) 
+{
+    ctx.encode_boolean(*this);
+}
+
+
+int BOOLEAN::decode(asn1::context &ctx) 
+{
+    return ctx.decode_boolean(*this);
+}
+
+// Integer
+static tag INTEGER_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,2)
+};
+const asn1::types::descriptor asn1::INTEGER::_meta = {
+    INTEGER_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+size_t INTEGER::get_data_length() const
+{
+  long value = m_Prim.get_value();
+  int shift = (sizeof(value)-1)*8-1;
+
+  // remove all sequences of nine 0's or 1's at the start of the value
+  while (shift > 0 && ((value >> shift)&0x1ff) == (value < 0 ? 0x1ff : 0))
+         shift -= 8;
+  
+   return (shift+9)/8;  
+}
+
+void INTEGER::encode(asn1::context &ctx) 
+{
+    ctx.encode_integer(*this);
+}
+int INTEGER::decode(asn1::context &ctx) 
+{
+    return ctx.decode_integer(*this);
+}
+
+// UInt64
+static tag UInt64_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,2)
+};
+const asn1::types::descriptor asn1::UInt64::_meta = {
+    UInt64_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+/**
+ * I have an issue when running tests on 64Bits architecture. 
+ * For limits DWORD eg 0xFFFFFFFF the number of bytes is 5! 
+ * I need to figure out what's wrong
+ * anyway, there is an issue. Both methods return the same value. 
+ */ 
+size_t UInt64::get_data_length() const
+{
+#if 1
+  long long value = m_Prim.get_value();
+  int intsize     = sizeof(value);
+  //int intsize     = 4;
+  long long  mask       =   ((long long)0x1FF << ((intsize -1 )*8 - 1)); // Shift 8 *3 - 1 ? 0xFF800000
+  std::cerr<<"value="<<value<<" intsize="<<intsize<<" mask="<<mask<<std::endl;
+  while ( ( ((value & mask) == 0) || ((value & mask) == mask)) 
+    && intsize > 1) {
+    intsize--;
+    value <<=8;
+  }
+  return intsize;
+#else
+  long long value = get_value();
+  long shift = (sizeof(value)-1)*8-1;
+
+  // remove all sequences of nine 0's or 1's at the start of the value
+  while (shift > 0 && ((value >> shift)&0x1ff) == (value < 0 ? 0x1ff : 0))
+         shift -= 8;
+  
+   return (shift+9)/8; 
+#endif 
+}
+
+void UInt64::encode(asn1::context &ctx) 
+{
+    ctx.encode_integer(*this);
+}
+
+int UInt64::decode(asn1::context &ctx) 
+{
+    return ctx.decode_integer(*this);
+}
+
+
+// BitString
+static tag BIT_STRING_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,3)
+};
+const asn1::types::descriptor asn1::BIT_STRING::_meta = {
+    BIT_STRING_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+size_t BIT_STRING::get_data_length() const
+{
+  return size() + 1;
+}
+
+void BIT_STRING::encode(asn1::context &ctx) 
+{
+    ctx.encode_bitstring(*this);
+}
+int BIT_STRING::decode(asn1::context &ctx) 
+{
+    return ctx.decode_bitstring(*this);
+}
+
+// OCTET String
+static tag OCTET_STRING_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,4)
+};
+const asn1::types::descriptor asn1::OCTET_STRING::_meta = {
+    OCTET_STRING_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+size_t OCTET_STRING::get_data_length() const
+{
+  return get_value().size();
+}
+void OCTET_STRING::encode(asn1::context &ctx) 
+{
+    ctx.encode_octetstring(*this);
+}
+int OCTET_STRING::decode(asn1::context &ctx) 
+{
+    return ctx.decode_octetstring(*this);
+}
+
+// Null
+static tag Null_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,5)
+};
+const asn1::types::descriptor asn1::Null::_meta = {
+    Null_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+void Null::encode(asn1::context &ctx) 
+{
+    ctx.encode_null(*this);
+}
+
+int Null::decode(asn1::context &ctx) 
+{
+    return ctx.decode_null(*this);
+}
+
+//
+// OBJECT IDENTIFIER
+ObjectIdentifier::ObjectIdentifier(int len ,const char *buf)
+  : asn1::types::type(
+       asn1::tag(asn1::types::UNIVERSAL,6)
+                 )
+  , asn1::prim::types::ObjectIdentifier(len,buf)
+{
+}
+
+ObjectIdentifier::ObjectIdentifier(const asn1::tag &t)
+  : asn1::types::type( t )
+  , asn1::prim::types::ObjectIdentifier()
+{
+}
+
+ObjectIdentifier &
+ObjectIdentifier::operator =(const ObjectIdentifier &c )
+{
+  if ( &c != this)
+  {
+    asn1::prim::types::ObjectIdentifier::operator=(c);
+  }
+  return *this;
+}
+
+
+bool ObjectIdentifier::operator ==(const ObjectIdentifier &o)
+{
+  return asn1::prim::types::ObjectIdentifier::operator ==(o);
+}
+
+void ObjectIdentifier::encode(asn1::context &ctx)
+{
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  asn1::tag  &tg= const_cast<asn1::tag &>(this->tag());
+  b[pos] = tg.byte();
+  ctx.nb_bits(8);            
+      
+  ASN1_BER_LOG_DEBUG("OID encode size=%zu",m_len);
+  unsigned long ipos = pos;
+  b[++pos] = m_len;
+  for (int it =  0 ; it < m_len ;it++)
+  {
+         b[++pos] = m_oid[it];
+  }
+  ctx.nb_bits((m_len + 1)<<3); 
+}
+
+int ObjectIdentifier::decode(asn1::context &ctx)
+{
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  asn1::tag tg(0,0);
+  tg.byte(b[pos]);
+  pos++;
+  long nb = 0;
+  if (tg.get_id() == this->tag().get_id() )
+  {
+      m_len = types::length(&b[pos],&nb);
+      ASN1_BER_LOG_DEBUG("OID decode len=%ld nb=%ld",m_len,nb);
+      ctx.nb_bits((m_len<<3)+ (nb<<3)+8);
+      if (m_len > MAX_OID_LEN)
+      {
+        ASN1_BER_LOG_ERROR(" ObjectIdentifier::decode len_exceed max %ld",m_len); 
+      }
+      memcpy(m_oid,&b[pos+nb],(m_len>MAX_OID_LEN)?MAX_OID_LEN:m_len);
+  } else 
+  {
+    ASN1_BER_LOG_DEBUG("ObjectIdentifier::decode FAILED bad tag %d expected 6 check_tag=%d" ,tg.get_id(),ctx.check_tag());
+    return asn1::wrong_tag;
+  }
+  return asn1::ok;
+}
+
+
+// OBJECT IDENTIFIER_NG
+void OBJECT_IDENTIFIER_NG::encode(asn1::context &ctx)
+{
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  asn1::tag  &tg= const_cast<asn1::tag &>(tag());
+  b[pos] = tg.byte();
+  ctx.nb_bits(8);            
+      
+  ASN1_BER_LOG_DEBUG("OID encode size=%zu",m_Prim.get_oid_length());
+  unsigned long ipos = pos;
+  b[++pos] = m_Prim.get_oid_length();
+  for (int it =  0 ; it < m_Prim.get_oid_length() ;it++)
+  {
+         b[++pos] = m_Prim.get_value()[it];
+  }
+  ctx.nb_bits((pos-ipos+1)<<3); // * 8  
+}
+
+int OBJECT_IDENTIFIER_NG::decode(asn1::context &ctx)
+{
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  asn1::tag tg(0,0);
+  tg.byte(b[pos]);
+  pos++;
+  long nb = 0;
+  if (tg.get_id() == this->tag().get_id() )
+  {
+      int m_len = types::length(&b[pos],&nb);
+      ASN1_BER_LOG_DEBUG("OID decode len=%ld nb=%ld"
+                       , m_Prim.get_oid_length(),nb);
+      ctx.nb_bits((m_Prim.get_oid_length()<<3) + (nb<<3) + 8);
+      m_Prim.from_string(m_len,(char *)&b[pos+nb]);
+  } else 
+  {
+    ASN1_BER_LOG_DEBUG("DECODE OID FAILED bad tag %d expected 6 check_tag=%d" ,tg.get_id(),ctx.check_tag());
+    return asn1::wrong_tag;
+  }
+  return asn1::ok;
+}
+
+
+
+// Enumeration
+static tag ENUMERATED_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,10)
+};
+const asn1::types::descriptor asn1::ENUMERATED::_meta = {
+    ENUMERATED_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+size_t ENUMERATED::get_data_length() const
+{
+  return 1;
+}
+
+void ENUMERATED::encode(asn1::context &ctx) 
+{
+    ASN1_BER_LOG_DEBUG("prim<0,10,Integer>(ENUMERARED)::encode tag=%d",tag().byte());
+    ctx.encode_integer(*this);
+}
+
+int ENUMERATED::decode(asn1::context &ctx) 
+{
+    INTEGER i(this->tag());
+    ASN1_BER_LOG_DEBUG("prim<0,10,Integer>(ENUMERARED)::decode");
+    int ret = ctx.decode_integer(i);
+    if (ret == asn1::ok) {
+      ASN1_BER_LOG_DEBUG("prim<0,10,Integer>(ENUMERARED)::decode assign %ld to m_"
+                     ,i.get_value().get_value());
+           m_Prim = i.get_value();
+    }
+    return ret;
+}
+#ifdef ASN1_TYPE_CLS
+#undef ASN1_TYPE_CLS
+#endif
+#define ASN1_TYPE_CLS(p,cls,tg,typ)                      \
+tag typ##_tag_list[] = {                                 \
+       tag(cls,tg)                                      \
+};                                                       \
+const asn1::types::descriptor asn1::typ::_meta = {       \
+    typ##_tag_list                                       \
+  , 1                                                    \
+  , NULL                                                 \
+  , 0                                                    \
+  , NULL                                                 \
+  , 0                                                    \
+};                                                       \
+typ &typ::operator =(const char *s)                      \
+{                                                        \
+  m_Prim = std::string(s);                               \
+  return *this;                                          \
+}                                                        \
+size_t typ::get_data_length() const                      \
+    { return get_value().size() ; }                      \
+void typ::encode(asn1::context &ctx)      \
+{                                         \
+    ctx.encode_string(*this);             \
+}                                         \
+int typ::decode(asn1::context &ctx)       \
+{                                         \
+    return ctx.decode_string(*this);      \
+}
+
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,12,UTF8String)
+// tag 13 is RELATIVE_OID 
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,18,NumericString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,19,PrintableString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,20,TeletexString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,21,VideotexString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,22,IA5String)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,25,GraphicString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,26,VisibleString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,27,GeneralString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,29,UniversalString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,30,BMPString)
+
+// GeneralizedTime
+static tag GeneralizedTime_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,24)
+};
+const asn1::types::descriptor asn1::GeneralizedTime::_meta = {
+    GeneralizedTime_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+void GeneralizedTime::encode(asn1::context &ctx) 
+{
+    //ctx.encode_octetstring(*this);
+}
+int GeneralizedTime::decode(asn1::context &ctx) 
+{
+    return asn1::wrong_tag;
+    //return ctx.decode_string(*this);
+}
+
+// UTCTime
+static tag UTCTime_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,23)
+};
+const asn1::types::descriptor asn1::UTCTime::_meta = {
+    UTCTime_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+void UTCTime::encode(asn1::context &ctx) 
+{
+    //ctx.encode_octetstring(*this);
+}
+int UTCTime::decode(asn1::context &ctx) 
+{
+    return asn1::wrong_tag;
+    //return ctx.decode_string(*this);
+}
+
+
+// Null
+void EXTERNAL::encode(asn1::context &ctx) 
+{
+    ASN1_BER_LOG_DEBUG("EXTERNAL::encode TODO");
+}
+
+int EXTERNAL::decode(asn1::context &ctx) 
+{
+    ASN1_BER_LOG_DEBUG("EXTERNAL::decode TODO");
+    return asn1::wrong_tag;
+}
+///////////////////////////////////////////////////////////////////////////////
+// prim codec specialized implementations
+///////////////////////////////////////////////////////////////////////////////
+
+
+// REAL;
+static tag REAL_tag_list[] = {
+        tag(asn1::types::UNIVERSAL,9)
+};
+const asn1::types::descriptor asn1::REAL::_meta = {
+    REAL_tag_list
+  , 1
+  , NULL
+  , 0
+  , NULL
+  , 0
+};
+void REAL::encode(asn1::context &ctx)
+{
+  ASN1_BER_LOG_DEBUG("REAL::encode TODO");
+  
+}
+
+int REAL::decode(asn1::context &ctx)
+{
+  ASN1_BER_LOG_DEBUG("REAL::decode TODO");
+  return asn1::ok;
+}
+
+//
+//ENUMERATED;
+namespace types {
+
+//////////////////////////////////////////////////////////////////
+
+/**
+ *
+ */
+choice_type::choice_type( unsigned int k
+                        , const asn1::tag &t
+                        , const descriptor *_d
+                        )
+  : m_kind(k), m_choice(NULL)
+  , asn1::types::type(t) 
+  , m_desc(_d)
+{
+//  ASN1_BER_LOG_DEBUG("choice_type(%p)::choice_type(%d)  ",this,m_kind );
+}
+
+choice_type::choice_type(const asn1::tag &t,const descriptor *_d) 
+  : m_kind(t.get_tag()), m_choice(NULL),asn1::types::type(t) 
+  , m_desc(_d)
+{
+//    ASN1_BER_LOG_DEBUG("choice_type::choice_type(%d)  ",m_kind );
+}
+
+choice_type::choice_type(const choice_type &t) : m_kind(t.m_kind) 
+                                               , asn1::types::type(t) 
+                                               , m_choice(NULL)
+                                               , m_desc(t.m_desc)
+{
+    ASN1_BER_LOG_DEBUG("choice_type::choice_type(const choice_type &) t.m_choice=%p m_kind=%d tag=%ld"
+                      ,t.m_choice,t.m_kind,t.m_tag.get_tag() );
+    if (this == &t)
+    {
+      return;  
+    }
+    if (t.m_choice)
+    {
+      m_tag    = t.m_tag;
+      m_choice = t.m_choice->clone();
+    } else 
+    {
+      m_tag    = t.m_tag;
+      m_choice = NULL;
+    }
+
+}
+
+/**
+ *
+ */
+bool choice_type::get_object() 
+{
+    return this->create_object();
+
+}
+
+
+size_t choice_type::get_data_length() const
+{
+  if (m_choice)
+    return m_choice->get_data_length();
+  assert(0 && " choice_type::get_data_length nothing selected") ;
+  return 0;
+}
+
+// Get the current member. NULL if not found
+member_desc *
+choice_type::get_member() const
+{
+  int _count = 0;
+  assert((m_desc != NULL) && "mdesc should always be initialized not NULL.");
+  for ( ; _count < m_desc->m_t2elcount ; _count++)
+  {
+    if (m_tag.get_tag() == m_desc->m_t2el[_count].m_tag )
+    {
+      return &m_desc->m_members[m_desc->m_t2el[_count].m_elidx];
+    }
+  }
+  return NULL;
+}
+
+bool  choice_type::check_create() 
+{
+  ASN1_BER_LOG_DEBUG("choice_type(%p)::check_create kind=%d tag=%ld",this,m_kind,m_tag.get_tag() );
+  if (m_choice != NULL)
+       return true;
+  if ( create_object() )
+  {
+    member_desc *m = get_member() ;
+    if (m  && ( m->m_tmode == 1) )
+    {
+      ASN1_BER_LOG_DEBUG("choice_type(%p)::check_create kind=%d tag=%ld EXPLICIT No tag propagation"
+                        ,this,m_kind,m_tag.get_tag() );
+      return true;
+    }
+    if (m_tag.byte() != 0)
+    {
+       m_choice->set_tag(m_tag);
+    }
+    return true;
+  }
+  std::cerr<<"choice_type::check_create "<<this<<" failed"<<std::endl; 
+  return false;
+}
+/**
+ *
+ */
+choice_type & choice_type::operator =(const choice_type &c)
+{
+#ifdef DEBUG
+  std::string name = typeid(*this).name();
+  std::string nc = typeid(c).name();
+  ASN1_BER_LOG_DEBUG("choice_type::operator =  of %s %s",name.c_str(),nc.c_str() );
+#endif
+  if (this != &c)
+  {
+      if (m_choice) {
+        delete m_choice;
+        m_choice = NULL;
+      }
+      if (c.m_choice)
+      {
+        m_tag       = c.m_tag;
+        m_kind      = c.m_kind;
+        m_choice    = c.m_choice->clone();
+        std::string x = typeid(*m_choice).name();
+        std::string xo = typeid(*c.m_choice).name();
+        ASN1_BER_LOG_DEBUG("choice_type::operator = kind=%d tg=%d m_choice %s = %s"
+                ,m_kind
+                ,m_tag.byte()
+                ,x.c_str()
+                ,xo.c_str());
+      } else
+      {
+#ifdef DEBUG
+        ASN1_BER_LOG_DEBUG("choice_type::operator  = c.m_choice is nul for %s",name.c_str() );
+#endif
+      }
+  } else
+  {
+#ifdef DEBUG
+    ASN1_BER_LOG_DEBUG("choice_type::operator =  copy to myself go awayof %s",name.c_str() );
+#endif
+  }
+  return *this;
+}
+
+/**
+ *
+ */ 
+bool choice_type::operator == (const choice_type &_c) const
+{
+#ifdef DEBUG
+  std::string name = typeid(*this).name();
+  ASN1_BER_LOG_DEBUG("choice_type::operator ==  %s",name.c_str() );
+#endif
+  return false; 
+}
+
+/**
+ *
+ */
+choice_type::~choice_type() {
+//    ASN1_BER_LOG_DEBUG("choice_type::~choice_type delete  %d",m_kind);
+    if (m_choice)
+        delete m_choice;
+}
+  
+/**
+ *
+ */
+bool choice_type::primitive() const
+{
+    if (m_choice)
+        return m_choice->primitive();
+    return true;
+}
+const asn1::tag &choice_type::tag() const 
+{
+    if (m_choice)
+        return m_choice->tag();
+    return type::tag();
+}
+
+void  
+choice_type::set_tag(const asn1::tag &t)
+{
+  ASN1_BER_LOG_DEBUG("choice_type(%p)::set_tag kind=%d class=%d id=%d"
+                    , this
+                    , m_kind
+                    , t.get_class()
+                    , t.get_id() );
+    if (m_choice) 
+        delete m_choice;
+    m_choice = NULL;
+    // Is this always correct ? Most of the time. Don't remove 
+    // Until you come out with a better idea
+    m_kind = t.get_tag( ) ; 
+    asn1::types::type::set_tag(t);
+    if (this->create_object() ) 
+    {
+      member_desc *m = get_member() ;
+      if (m  && ( m->m_tmode == 1) )
+      {
+       ASN1_BER_LOG_DEBUG( "choice_type(%p)::set_tag EXPLICIT dont' propagate"
+                         , this
+                         );
+        return ;
+      }
+      m_choice->set_tag(t);
+    }
+}
+// New way
+void choice_type::encode(asn1::context &ctx)
+{
+  ASN1_BER_LOG_DEBUG("choice_type::encode delegate to ctx " );
+  ctx.encode_choice(*this);
+}
+
+int  choice_type::decode(asn1::context &ctx)
+{
+  std::string name = typeid(*this).name();
+  std::string name1;
+  if ( m_choice != NULL)
+  { 
+    name1 =  typeid(*m_choice).name();
+    delete m_choice ; 
+    m_choice = NULL;
+  } else
+    name1 = "NULL";
+  ASN1_BER_LOG_DEBUG("choice_type::decode %s m_choice is %s (deleted) delegate to ctx",name.c_str(),name1.c_str() );
+  if ( m_choice && (dynamic_cast<choice_type *>(m_choice) == NULL))
+  {
+    ASN1_BER_LOG_DEBUG("choice_type::decode %s delegate to ctx NOT A CHOICE ",name.c_str() );
+    return m_choice->decode(ctx); 
+  }
+  return ctx.decode_choice(*this);
+}
+
+  // New way specific for ber 
+void choice_type::encode_ber(asn1::streams::ber &ctx)
+{
+  unsigned long    m_pos     = ctx.bytes();
+  unsigned char   *m_buffer  = ctx.buffer();
+  if (m_choice)
+        m_choice->encode(ctx);
+  m_buffer[m_pos++] = this->tag().byte();
+}
+
+int  choice_type::decode_ber(asn1::streams::ber &ctx)
+{
+  asn1::tag        t(0,0);
+  std::string      name      = typeid(*this).name();
+  unsigned long    m_pos     = ctx.bytes();
+  unsigned char   *m_buffer  = ctx.buffer();
+  int              len       = 0;
+  ASN1_BER_LOG_DEBUG("choice_type::decode_ber %s stream tag = %d"
+                    , name.c_str()
+                    , m_buffer[m_pos]
+                    );
+
+  if (ctx.decode_tag(t,len) )
+  {
+      set_tag(t);
+      if (check_create())
+      {
+        std::string name = typeid(*this).name();
+        std::string name1 = typeid(*m_choice).name();
+        // Very ugly .... If m_choice is of type Choice
+        // It must be an explicit tag, Should be handled by parser 
+          member_desc *m = get_member() ;
+          if (m  && ( m->m_tmode == 1) )
+          {
+            std::cerr<<"choice_type::"<<__FUNCTION__<<" "<<name;
+            std::cerr<<" m_choice "<<name1<<" tag= "<<t.get_tag();
+            std::cerr<<" Still Buggy with EXPLICIT tag member "<<std::endl;
+          } else
+            ctx.bytes(m_pos);
+        //
+        int res = m_choice->decode(ctx);
+        if (res != asn1::ok)
+        {
+          ASN1_BER_LOG_ERROR("choice_type(%s)::decode_ber m_choice(%s)->decode failed tag = %d pos=%lu but tag was correct %d"
+              ,name.c_str()
+             ,name1.c_str()
+              ,t.byte()
+              , m_pos
+              , m_choice->tag().byte()
+          );
+          ctx.bytes(m_pos);
+        }
+        return res;
+      } else
+      {
+        ASN1_BER_LOG_ERROR("choice_type::decode_ber Failed %s tag=%d check create did not work",name.c_str(),t.byte() );
+      }
+  }
+  ctx.bytes(m_pos);
+  ASN1_BER_LOG_ERROR("choice_type::decode_ber Failed " );
+  return asn1::unknown;
+}
+  
+void choice_type::printf(std::ostream &os) const
+{
+  if (m_choice)
+  {
+    member_desc *m = get_member() ;
+    os<<m->m_name<<" :";
+    m_choice->printf(os);
+  }
+}
+
+/**
+ * implement sequence
+ */
+sequence_type::sequence_type(const asn1::tag &t) : asn1::types::type(t)
+{
+}
+
+
+
+sequence_type::~sequence_type()
+{
+}
+
+
+sequence_type & sequence_type::operator = (const sequence_type &c)
+{
+    return *this;
+}
+
+
+bool 
+sequence_type:: primitive() const 
+{
+    return false;
+}
+
+
+const asn1::tag &sequence_type::tag() const 
+{
+  ASN1_BER_LOG_DEBUG("sequence_type::tag return %d ",type::tag().byte() );
+  return type::tag();
+}
+
+size_t sequence_type::get_data_length() const
+{
+  assert (0) ;
+}
+ // New way
+void sequence_type::encode_preamble(asn1::context &ctx)
+{
+  m_pos     = ctx.bytes();
+  m_buffer  = ctx.buffer();
+  ctx.encode_sequence_preamble(*this);
+}
+
+void sequence_type::encode_preamble_ber(asn1::context &ctx)
+{
+  m_pos     = ctx.bytes();
+  m_buffer  = ctx.buffer();
+  m_buffer[m_pos++] = this->tag().byte();
+  ctx.nb_bits(16); // tag done
+}
+
+void sequence_type::encode_epilogue_ber(asn1::context &ctx)
+{
+    unsigned long len   = ctx.bytes() - m_pos - 1;
+    m_buffer[m_pos]   = len;
+}
+
+int sequence_type::decode_preamble_ber(asn1::streams::ber &ctx)
+{
+  return asn1::ok;
+}
+
+int sequence_type::decode_epilogue_ber(asn1::streams::ber &ctx)
+{
+  return asn1::ok;
+}
+
+/**
+ * Generic encoding decoding
+ */
+void sequence_type::encode_epilogue(asn1::context &ctx)
+{
+  ctx.encode_sequence_epilogue(*this);
+}
+
+
+int sequence_type::decode_preamble(asn1::context &ctx)
+{
+  int len;
+  m_pos     = ctx.bytes();
+  m_buffer  = ctx.buffer();
+  asn1::tag  &tg= const_cast<asn1::tag &>(tag());
+  return ctx.decode_sequence_preamble(*this);
+}
+
+int sequence_type::decode_epilogue(asn1::context &ctx)
+{
+    unsigned long len   = ctx.bytes() - m_pos - 1;
+  return ctx.decode_sequence_epilogue(*this);
+}
+
+
+void sequence_type::encode(asn1::context &ctx) 
+{
+  encode_preamble(ctx);
+}
+
+int sequence_type::decode(asn1::context  &ctx) 
+{
+  return decode_preamble(ctx);
+}
+
+
+
+// End of namespace types
+}
+
+
+};
diff --git a/rtasn1/asn1_types.h b/rtasn1/asn1_types.h
new file mode 100644 (file)
index 0000000..16ac1f7
--- /dev/null
@@ -0,0 +1,1098 @@
+#ifndef ASN1_TYPES_H__
+#define ASN1_TYPES_H__
+#include <iostream>
+#include <list>
+
+#include "rtasn1/asn1_errors.h"
+
+#define MEMBER_OFFSET(cls,mbr) ((ptrdiff_t)&(((cls *)0)->mbr) - (ptrdiff_t)((cls *)0))
+
+namespace asn1
+{
+  class context;
+  class codecJER;
+  class codecBER;
+  class codecOER;
+}
+
+namespace asn1 {
+
+/* basic types that will be used by codecs, and so on */
+typedef unsigned char    byte; /*  8 bits data */
+typedef unsigned short   word; /* 16 bits data */
+
+
+namespace types {
+
+//int debug_level;
+
+typedef enum {
+    UNIVERSAL,
+    APPLICATION,
+    CONTEXT_SPECIFIC,
+    PRIVATE
+} tag_class;
+
+
+/**
+ * The descriptors below are provided for choice because I was unable to 
+ * come up with code that would work properly due to implicit / explicit
+ * tagging.
+ * I might considerer using this structures for set and sequence as well.
+ */ 
+struct member_desc;
+struct tag2member_desc;
+enum type_flags {
+  TF_NONE ,
+  TF_POINTER        = 0x01,
+  TF_SHARED_POINTER = 0x02,
+  TF_OPEN_TYPE      = 0x04
+};
+struct descriptor {
+  tag                    *m_tags;
+  unsigned int            m_tagcount;
+  /**
+   * For Sequence, Set and Choice
+   */
+  struct member_desc     *m_members;   /* array of member descriptors    */
+  int                     m_elcount;   /* number of elements in struct   */
+  struct tag2member_desc *m_t2el;      /* */
+  long                    m_t2elcount; /* number of elements in t2el arr */
+};
+
+
+struct member_desc {
+  enum               type_flags m_flags;
+  long               m_tmode;            /* tag mode EXPLICIT(1) or IMPLICIT(-1) */
+  long               m_tag;              /* tag value id<<2 |class      */
+  int                m_member_offser;    /* Member offset               */
+  long               m_midx;             /* member index is structure   */
+  struct descriptor *m_type;             /* member type descriptor      */
+  const char        *m_name;             /* member str name for display */
+};
+
+/**
+ * Most of the time m_kind == m_tag
+ */ 
+struct tag2member_desc {
+  long m_tag;     /* tag of the element        */
+  long m_kind;    /* This is a bit confusing.. */
+  int  m_elidx;   /* element index for the tag */
+};
+
+/**
+ *
+ */
+enum constraint_type {
+    un_constrained       = 0
+  , partial_constrained
+  , fixed_constrained
+  , extendable_constrained
+};
+
+struct constraint_desc {
+  constraint_type m_t;
+  long            m_l;
+  long            m_u;
+};
+
+/** Functions 
+ *  - length will go
+ *  - count_bits will be used to compute the length of an integer
+ *
+ */
+long length(unsigned char *buf, long *_read);
+
+size_t count_bits(unsigned int val);
+
+/**
+ * @brief top class for asn1 types. 
+ */
+class type 
+{
+  protected:
+  type(const type &t) ;
+
+  public:
+  type(int c = 0,int tid=0) ;
+
+  type(const asn1::tag &t) ;
+
+  virtual ~type() ;
+  // For the intrusive pointer managment
+  inline  void add_ref()
+  {m_ref++;} 
+
+  inline  void  release()
+  {if (--m_ref == 0) delete this;}
+
+  virtual bool   primitive() const ;
+  // Return length of encoded type tag + len + data
+  size_t         get_length() const;
+  // return only data length. Can'e declare
+  // as pure virtual because og object and objectclass templates
+  virtual size_t get_data_length() const
+  { return 0;}
+  virtual void   set_tag(const asn1::tag &t) ;
+
+
+  // Needed for copy constructor choice
+  virtual type  *clone()  ;
+  
+  // encoding / decoding mechanism.
+  
+  virtual void encode(asn1::context &ctx) ;
+
+  virtual int  decode(asn1::context &ctx) ;
+
+  virtual bool equal(const type &c)
+  {
+    std::cerr<<"type::equal should not be called"<<std::endl;
+    return false;
+  };
+  virtual const asn1::tag &tag() const ;
+
+  virtual void printf(std::ostream &os) const ;
+  friend std::ostream &operator <<(std::ostream &os, const type &s)
+    {
+      os<<" asn1::type ";
+      return os;
+    };
+  protected:
+   asn1::tag    m_tag;
+  private:
+   int m_ref;
+};
+
+
+/**
+ * Temporary class to be removed
+ * once completely moved code to codecBER
+ */
+class strtype : public asn1::types::type
+{
+  public:
+    strtype(int a,int b) : asn1::types::type(a,b) {}
+    strtype(const asn1::tag &t) : asn1::types::type(t) {}
+
+    virtual asn1::prim::types::String & get_prim()  = 0;
+    const asn1::prim::types::String & get_prim() const
+    { return const_cast<strtype *>(this)->get_prim(); };
+};
+
+/**
+ * container The fact that is a template and contains a
+ * vector is not really how it should be.
+ * Constructed types are sequences, choice, and any. This type
+ * should only be used for user interfaces.
+ */
+template <typename T>
+class container :  public asn1::types::type 
+{
+  public:
+    typedef T                                       prim_type;
+    typedef T                                       type;
+    typedef typename std::vector<T>                 items;
+    typedef typename std::vector<T>::iterator       iterator;
+    typedef typename std::vector<T>::const_iterator const_iterator;
+
+    inline container(const asn1::tag &t)
+      : asn1::types::type(t)
+    {
+#if 0
+      std::cerr<<"container::container(t="<<(int)t.byte()<<")\n";
+      std::cerr<<"Liste size="<<m_.size()<<std::endl;
+#endif
+    };
+    
+    inline container(const container<T> &c) 
+    {
+      std::cout<<"cp :"<<c.m_.size()<<std::endl;
+      m_ = c.m_;
+    }
+
+    inline container(const T &c)
+    {
+      m_.push_back(c);
+    }
+
+    inline void operator=(const container<T> &c) 
+    {
+#if 0
+      std::cout<<"container::cp copy " <<c.m_.size()<<std::endl;
+#endif
+      m_ = c.m_;
+    }
+    
+    inline void operator=(const T&c)  {
+      m_.push_back(c);
+    }
+    inline iterator begin()
+    {
+      return m_.begin();
+    };
+    inline const_iterator begin() const
+    {
+      return m_.begin();
+    };
+    
+    inline iterator end()
+    {
+      return m_.end();}
+    ;
+    inline const_iterator end() const
+    {
+      return m_.end();}
+    ;
+    
+    inline void push_back(T &t) {
+      m_.push_back(t);
+    };
+   
+    virtual bool primitive() const
+    { return false; };
+
+    /**/
+    virtual const asn1::tag &tag() const 
+    {
+      // std::cerr<<"container::tag\n";
+      static asn1::tag t = asn1::tag(0,0);
+      if (this->m_tag.byte() != 0) 
+      {
+        return m_tag;
+      }
+      else 
+        return t;
+    };
+    
+    size_t size() const 
+    {
+      return m_.size();
+    }
+    void resize(size_t t) 
+    {
+      m_.resize(t);
+    }
+    void printf(std::ostream &os) const
+    {
+      int count = 0;
+      const_iterator  mit = begin();
+      os << " container "<<std::endl;
+      for (; 
+          mit != end();
+          ++mit)
+      {
+        std::streamsize indent = os.precision() + 2;
+        os<<std::setw(indent+2)<<"["<<count++<<"] "<<std::setprecision(indent);
+        os<<(*mit);
+        //(*mit).printf(os);
+        os<<"\n";
+        os<<std::setprecision(indent-2);
+      }
+    }
+  protected:
+    items m_;
+};
+
+/**
+ * @brief any is a container class more precisely a variat
+ * object. It represents ASN1 type.
+ * -> The constructor should use a tag and build the 
+ *  appropriate object according to the tag.
+ */ 
+class any_type : public asn1::types::type
+{
+  protected:
+    asn1::types::type *m_any;
+  public:
+    any_type(asn1::types::type *v = NULL);
+    
+    any_type(const asn1::types::type &v);
+
+    ~any_type();
+    // Cast operator
+    // operator T() {return *m_any;}
+    // const T* operator *() {return m_any;}
+    virtual size_t get_data_length() const
+    { return 0 ; }
+    
+    virtual void encode(asn1::context &ctx) ;
+
+    virtual int  decode(asn1::context &ctx) ;
+    
+    bool operator == (const any_type &_c) const ;
+    
+    virtual const asn1::tag &tag() const ;
+
+    friend std::ostream &operator <<(std::ostream &os, const any_type &s)
+    {
+        //os<<" tag("<<C<<","<<I<<"){"<<(asn1::prim::types::Integer)s<<"}";
+        os<<" ANY Not  ";
+        return os;
+    };
+};
+
+/**
+ *
+ *
+ */
+class choice_type : public asn1::types::type 
+{
+  protected:
+    const descriptor *m_desc;
+    // copy constructor 
+    choice_type(const choice_type &c) ;
+  public:
+  choice_type( unsigned int kind 
+             , const asn1::tag &t = asn1::tag(0,0)
+             , const descriptor  *_d = NULL
+             );
+  choice_type( const asn1::tag &t = asn1::tag(0,0)
+             , const descriptor *_d = NULL
+             );
+
+
+  virtual ~choice_type();
+  
+  choice_type & operator = (const choice_type &c);
+    
+  choice_type &get_value() { return *this; };
+  const choice_type &get_value() const { return *this; };
+
+  virtual choice_type *clone()
+    {
+      ASN1_BER_LOG_ERROR("choice_type::clone should never be called");
+      return NULL;
+      //return new choice_type(*this);
+    }
+  //
+  //
+  virtual bool create_object() = 0;
+  // check if m_choice != NULL if not create 
+  bool  check_create() ;
+
+  virtual void  set_tag(const asn1::tag &t);
+  
+  inline unsigned int get_kind() const  { return m_kind;} ;
+  
+  virtual bool primitive() const ;
+  
+  bool operator == (const choice_type &_c) const;
+    
+  virtual const asn1::tag &tag() const ;
+  virtual size_t get_data_length() const ;
+  // New way
+  virtual void encode(asn1::context &ctx) ;
+  virtual int  decode(asn1::context &ctx) ;
+  // New way specific for ber  .. Does not work !!!
+  virtual void encode_ber(asn1::streams::ber &ctx) ;
+  
+  virtual int  decode_ber(asn1::streams::ber &ctx) ;
+  
+  virtual void printf(std::ostream &os) const ;
+
+  friend class ::asn1::codecJER;
+  friend class ::asn1::codecBER;
+
+  protected:
+    bool get_object();
+    // Get the current member. NULL if not found
+    member_desc *get_member() const;
+    // Attributes 
+    asn1::types::type   *m_choice;
+    unsigned int        m_kind;
+};
+
+/**
+ *
+ *
+ */
+class sequence_type : public asn1::types::type 
+{
+  // copy constructor 
+  //sequence_type(const sequence_type &c);
+  public:
+  sequence_type(const asn1::tag &t = asn1::tag(0,16,true));
+
+  virtual ~sequence_type();
+  
+  sequence_type & operator = (const sequence_type &c);
+  
+  sequence_type &get_value() { return *this; };
+  const sequence_type &get_value() const { return *this; };
+  
+  virtual bool primitive() const ;
+    
+  virtual const asn1::tag &tag() const ;
+  
+  virtual size_t get_data_length() const;
+  
+  // New way
+  virtual void encode(asn1::context &ctx) ;
+  virtual int  decode(asn1::context &ctx) ;
+  
+  virtual void encode_preamble(asn1::context &ctx);
+  virtual void encode_epilogue(asn1::context &ctx);
+  virtual int decode_preamble(asn1::context &ctx);
+  virtual int decode_epilogue(asn1::context &ctx);
+  // May be specific functions here BER / PER / XER / OT
+  virtual void encode_preamble_ber(asn1::context &ctx);
+  virtual void encode_epilogue_ber(asn1::context &ctx);
+  
+  virtual int decode_preamble_ber(asn1::streams::ber &ctx);
+  virtual int decode_epilogue_ber(asn1::streams::ber &ctx);
+  
+  protected:
+    unsigned char * m_buffer;
+    unsigned long   m_pos;
+};
+
+/* end of namespace types */
+}
+
+
+//  class asn1t : public asn1::types::prim<typ> {
+/* In namespace asn1 */
+#define ASN1_TYPE_CLS_GEN(parent,typ,cls,tg,asn1t) \
+  class asn1t :                                    \
+                 public asn1::types::parent  {     \
+    protected:                                     \
+      typ   m_Prim;                                \
+    public:                                        \
+      typedef typ  prim_type;                      \
+      typedef typ* prim_type_pointer;              \
+      typedef typ& prim_type_reference;            \
+      typedef const typ& prim_type_const_reference;\
+      ~asn1t()  {}                                 \
+    asn1t(const asn1::tag &t = asn1::tag(cls,tg))  \
+      : asn1::types::parent(t)                     \
+    {};                                            \
+    asn1t(const asn1t &v)                          \
+      : m_Prim(v.m_Prim) , asn1::types::parent(v.m_tag)      \
+    { } ;                                          \
+    inline asn1t(const typ &c)                     \
+      : asn1::types::parent(asn1::tag(cls,tg))     \
+      , m_Prim(c)                                  \
+    { };                                           \
+    inline asn1t(const typ::prim_type &c)          \
+      : asn1::types::parent(asn1::tag(cls,tg))     \
+      , m_Prim(c)                                  \
+    { };                                           \
+                                                   \
+    prim_type get_value() const                    \
+    {                                              \
+      return m_Prim;                               \
+    }                                              \
+    prim_type_reference get_value()                \
+    {                                              \
+      return m_Prim;                               \
+    }                                              \
+    prim_type::prim_type get_sys_value() const                \
+    {                                              \
+      return m_Prim.get_value();                   \
+    }                                              \
+    virtual asn1t *clone()                         \
+    {                                              \
+      return new asn1t(*this);                     \
+    }; /* Needed for copy constructor choice */    \
+    /**                                      */    \
+    bool equal(const asn1::types::type &t)         \
+    {                                              \
+      const asn1t *c = dynamic_cast<const asn1t *>(&t);  \
+      std::cerr<<"prim::equal "<<c<<std::endl;     \
+      if (c)                                       \
+      {                                            \
+        return m_Prim == c->get_value(); \
+      } else                                       \
+        return false ;                             \
+    }                                              \
+    /** */                                         \
+    inline asn1t &operator =(const asn1t &t)       \
+    {                                              \
+      m_Prim = t.m_Prim; return *this;             \
+    };                                             \
+                                                   \
+    virtual const asn1::tag &tag() const           \
+    {                                              \
+      static asn1::tag t = asn1::tag(cls,tg);      \
+      if (m_tag.byte() > 0)                        \
+      {                                            \
+        return m_tag;                              \
+      } else return t;                             \
+    };                                             \
+                                                   \
+    /** Will be new way */                                            \
+    virtual void encode(asn1::context &ctx);                          \
+                                                                      \
+    virtual int  decode(asn1::context &ctx);                          \
+                                                                      \
+    virtual void printf(std::ostream &os) const                       \
+    {os<<*this;};                                                     \
+                                                                      \
+    friend std::ostream &operator <<(std::ostream &os, const asn1t &s)\
+    {                                                                 \
+      os<<" tag("<<cls<<","<<tg<<"){";                                \
+      os<<(s.m_Prim);os<<"}";                                   \
+      return os;                                                      \
+    };                                                                \
+    static const types::descriptor _meta;
+
+
+/* Class completion macro mainly for missing ctors like long, int ... */
+#define ASN1_TYPE_CLS_ADD_BOOLEAN(parent,typ,cls,tg)   \
+    inline BOOLEAN(const bool c)                       \
+      : asn1::types::parent(asn1::tag(cls,tg))         \
+      , m_Prim(c)                                      \
+    { };                                               \
+    inline  BOOLEAN &operator =(const bool m)          \
+    { m_Prim =m; return *this; }                       \
+    inline bool operator ==(const bool m) const        \
+    { return m_Prim ==(m); }                           \
+    inline bool operator ==(const BOOLEAN &m) const    \
+    { return m_Prim == m.m_Prim; }                     \
+    virtual size_t get_data_length() const             \
+    { return 1 ; }
+
+#define ASN1_TYPE_CLS_ADD_INTEGER(parent,typ,cls,tg)   \
+    inline INTEGER(const int c)                        \
+      : asn1::types::parent(asn1::tag(cls,tg))         \
+      , m_Prim(c)                                      \
+    { };                                               \
+    virtual size_t get_data_length() const;            \
+    inline  INTEGER &operator =(const int  m)          \
+    { m_Prim = m; return *this; }                      \
+    inline  bool   operator==(const INTEGER &o) const  \
+    { return m_Prim == o.m_Prim; };                    \
+    inline  bool   operator==(const long o) const      \
+    { return m_Prim == o; };                           \
+
+#define ASN1_TYPE_CLS_ADD_Int8(parent,typ,cls,tg)      \
+    virtual size_t get_data_length() const             \
+    { return 1 ; }
+#define ASN1_TYPE_CLS_ADD_Int16(parent,typ,cls,tg)     \
+    virtual size_t get_data_length() const             \
+    { return 2 ; }
+#define ASN1_TYPE_CLS_ADD_Int32(parent,typ,cls,tg)     \
+    virtual size_t get_data_length() const             \
+    { return 4 ; }
+#define ASN1_TYPE_CLS_ADD_Int64(parent,typ,cls,tg)     \
+    virtual size_t get_data_length() const             \
+    { return 8 ; }
+#define ASN1_TYPE_CLS_ADD_UInt8(parent,typ,cls,tg)     \
+    virtual size_t get_data_length() const             \
+    { return 1 ; }
+#define ASN1_TYPE_CLS_ADD_UInt16(parent,typ,cls,tg)    \
+    virtual size_t get_data_length() const             \
+    { return 2 ; }
+#define ASN1_TYPE_CLS_ADD_UInt32(parent,typ,cls,tg)    \
+    virtual size_t get_data_length() const             \
+    { return 4 ; }
+#define ASN1_TYPE_CLS_ADD_UInt64(parent,typ,cls,tg)    \
+    inline UInt64(const unsigned long c)               \
+      : asn1::types::parent(asn1::tag(cls,tg))         \
+      , m_Prim(c)                                      \
+    { };                                               \
+    virtual size_t get_data_length() const;            \
+    inline  UInt64 &operator =(const typ::prim_type m) \
+    { m_Prim = m; return *this; }                      \
+    inline  bool   operator==(const UInt64 &o) const   \
+    { return m_Prim == o.m_Prim; };                    \
+    inline  bool   operator==(const typ::prim_type m) const   \
+    { return m_Prim == m; };                              \
+
+#define ASN1_TYPE_CLS_ADD_BIT_STRING(parent,typ,cls,tg)   \
+    virtual size_t get_data_length() const;               \
+    size_t  size() const { return m_Prim.size();}         \
+    inline size_t  get_nb_bits() const                    \
+    { return m_Prim.get_nb_bits();}                       \
+    inline void set_nb_bits(int i)                        \
+    { return m_Prim.set_nb_bits(i);}                      \
+    typ::const_reference operator[](int idx) const        \
+    { return m_Prim[idx]; }                               \
+    typ::reference operator[](int idx)                    \
+    { return m_Prim[idx]; }                               \
+    inline  bool   operator==(const BIT_STRING &o) const  \
+    { return m_Prim == o.m_Prim; };                    \
+
+#define ASN1_TYPE_CLS_ADD_OCTET_STRING(parent,typ,cls,tg) \
+    inline OCTET_STRING(const char *c)                    \
+      : asn1::types::parent(asn1::tag(cls,tg))            \
+      , m_Prim(c)                                         \
+    { };                                                  \
+    virtual size_t get_data_length() const;               \
+    inline  bool   operator==(OCTET_STRING &o) const      \
+    { return m_Prim == o.m_Prim; };                       \
+
+#define ASN1_TYPE_CLS_ADD_STRING(parent,typ,cls,tg)       \
+    inline STRING(const char *c)                          \
+      : asn1::types::parent(asn1::tag(cls,tg))            \
+      , m_Prim(c)                                         \
+    { };                                                  \
+    inline  bool   operator==(STRING &o) const            \
+    { return m_Prim == o.m_Prim; };                       \
+    virtual size_t get_data_length() const                \
+    { return 0 ; }
+#define ASN1_TYPE_CLS_ADD_Null(parent,typ,cls,tg)         \
+    virtual size_t get_data_length() const                \
+    { return 0 ; }                                        \
+    inline  bool   operator==(Null &o) const              \
+    { return true; };                                     \
+
+#define ASN1_TYPE_CLS_ADD_EXTERNAL(parent,typ,cls,tg)     \
+    virtual size_t get_data_length() const                \
+    { return 0 ; }
+#define ASN1_TYPE_CLS_ADD_GeneralizedTime(parent,typ,cls,tg) \
+    virtual size_t get_data_length() const                   \
+    { return 0 ; }                                           \
+    inline bool operator ==(const GeneralizedTime &m) const  \
+    { return m_Prim == m.m_Prim; }                           \
+
+#define ASN1_TYPE_CLS_ADD_UTCTime(parent,typ,cls,tg)         \
+    virtual size_t get_data_length() const                   \
+    { return 0 ; }                                           \
+    inline bool operator ==(const UTCTime &m) const          \
+    { return m_Prim == m.m_Prim; }                           \
+
+#define ASN1_TYPE_CLS_ADD_REAL(parent,typ,cls,tg)         \
+    inline REAL(const double c)                           \
+      : asn1::types::parent(asn1::tag(cls,tg))            \
+      , m_Prim(c)                                         \
+    { };                                                  \
+    inline REAL &operator =(const double m)               \
+    { m_Prim == m; return *this; }                        \
+    inline bool operator ==(const REAL &m) const          \
+    { return m_Prim == m.m_Prim; }                        \
+    virtual size_t get_data_length() const                \
+    { return 0 ; }
+
+#define ASN1_TYPE_CLS_ADD_ENUMERATED(parent,typ,cls,tg)   \
+  friend class ::asn1::codecJER;                          \
+    virtual size_t get_data_length() const;               \
+
+#define ASN1_TYPE_CLS_ADD_UTF8String(parent,typ,cls,tg)   \
+    inline UTF8String(const char *c)                      \
+      : asn1::types::parent(asn1::tag(cls,tg))            \
+      , m_Prim(c)                                         \
+    { };                                                  \
+    UTF8String &operator =(const char *s);                \
+    inline bool operator ==(const UTF8String &m) const    \
+    { return m_Prim == m.m_Prim; }                        \
+    virtual size_t get_data_length() const;               \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_NumericString(parent,typ,cls,tg)\
+    inline NumericString(const char *c)                   \
+      : asn1::types::parent(asn1::tag(cls,tg))            \
+      , m_Prim(c)                                         \
+    { };                                                  \
+    NumericString &operator =(const char *s);             \
+    inline bool operator ==(const NumericString &m) const \
+    { return m_Prim == m.m_Prim; }                        \
+    virtual size_t get_data_length() const;               \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_PrintableString(parent,typ,cls,tg) \
+    inline PrintableString(const char *c)                    \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    PrintableString &operator =(const char *s);              \
+    inline bool operator ==(const PrintableString &m) const  \
+    { return m_Prim == m.m_Prim; }                           \
+    virtual size_t get_data_length() const;                  \
+    virtual asn1::prim::types::String & get_prim()           \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_TeletexString(parent,typ,cls,tg)   \
+    inline TeletexString(const char *c)                      \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    TeletexString &operator =(const char *s);                \
+    inline bool operator ==(const TeletexString &m) const    \
+    { return m_Prim == m.m_Prim; }                           \
+    virtual size_t get_data_length() const;                  \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_VideotexString(parent,typ,cls,tg)  \
+    inline VideotexString(const char *c)                     \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    VideotexString &operator =(const char *s);               \
+    virtual size_t get_data_length() const;                  \
+    virtual asn1::prim::types::String & get_prim()           \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_IA5String(parent,typ,cls,tg)       \
+    inline IA5String(const char *c)                          \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    IA5String &operator =(const char *s);                    \
+    virtual size_t get_data_length() const;                  \
+    inline  bool   operator==(IA5String &o) const            \
+    { return m_Prim == o.m_Prim; };                          \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_GraphicString(parent,typ,cls,tg)   \
+    inline GraphicString(const char *c)                      \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    GraphicString &operator =(const char *s);                \
+    virtual size_t get_data_length() const;                  \
+    inline  bool   operator==(const GraphicString &o) const  \
+    { return m_Prim == o.m_Prim; };                    \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_VisibleString(parent,typ,cls,tg)   \
+    inline VisibleString(const char *c)                      \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    VisibleString &operator =(const char *s);                \
+    virtual size_t get_data_length() const;                  \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_GeneralString(parent,typ,cls,tg)   \
+    inline GeneralString(const char *c)                      \
+      : asn1::types::parent(asn1::tag(cls,tg))               \
+      , m_Prim(c)                                            \
+    { };                                                     \
+    GeneralString &operator =(const char *s);                \
+    virtual size_t get_data_length() const;                  \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_UniversalString(parent,typ,cls,tg)  \
+    inline UniversalString(const char *c)                     \
+      : asn1::types::parent(asn1::tag(cls,tg))                \
+      , m_Prim(c)                                             \
+    { };                                                      \
+    UniversalString &operator =(const char *s);               \
+    inline bool operator ==(const UniversalString &m) const   \
+    { return m_Prim == m.m_Prim; }                            \
+    virtual size_t get_data_length() const;                   \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_BMPString(parent,typ,cls,tg)        \
+    inline BMPString(const char *c)                           \
+      : asn1::types::parent(asn1::tag(cls,tg))                \
+      , m_Prim(c)                                             \
+    { };                                                      \
+    BMPString &operator =(const char *s);                     \
+    inline bool operator ==(const BMPString &m) const         \
+    { return m_Prim == m.m_Prim; }                            \
+    virtual size_t get_data_length() const;                   \
+    virtual asn1::prim::types::String & get_prim()        \
+    { return m_Prim;};
+
+#define ASN1_TYPE_CLS_ADD_OBJECT_IDENTIFIER_NG(parent,typ,cls,tg) \
+    inline void from_arc(size_t len, const long *m)               \
+    { m_Prim.from_arc(len,m); }                                   \
+    inline bool operator ==(const OBJECT_IDENTIFIER_NG &m) const  \
+    { return m_Prim == m.m_Prim; }                                \
+    inline bool operator !=(const OBJECT_IDENTIFIER_NG &m) const  \
+    { return ! (m_Prim == m.m_Prim); }                            \
+    virtual size_t get_data_length() const                        \
+    { return 0 ; }
+
+#define ASN1_TYPE_CLS(parent,typ,cls,tg,asn1t) \
+          ASN1_TYPE_CLS_GEN(parent,typ,cls,tg,asn1t) \
+          ASN1_TYPE_CLS_ADD_##asn1t(parent,typ,cls,tg) };
+
+
+/**/              
+ASN1_TYPE_CLS(type,asn1::prim::types::Boolean,asn1::types::UNIVERSAL,1,BOOLEAN)
+ASN1_TYPE_CLS(type,asn1::prim::types::Integer,asn1::types::UNIVERSAL,2,INTEGER)
+ASN1_TYPE_CLS(type,asn1::prim::types::Int8,asn1::types::UNIVERSAL,2,Int8)
+ASN1_TYPE_CLS(type,asn1::prim::types::Int16,asn1::types::UNIVERSAL,2,Int16)
+ASN1_TYPE_CLS(type,asn1::prim::types::Int32,asn1::types::UNIVERSAL,2,Int32)
+ASN1_TYPE_CLS(type,asn1::prim::types::Int64,asn1::types::UNIVERSAL,2,Int64)
+ASN1_TYPE_CLS(type,asn1::prim::types::UInt8,asn1::types::UNIVERSAL,2,UInt8)
+ASN1_TYPE_CLS(type,asn1::prim::types::UInt16,asn1::types::UNIVERSAL,2,UInt16)
+ASN1_TYPE_CLS(type,asn1::prim::types::UInt32,asn1::types::UNIVERSAL,2,UInt32)
+ASN1_TYPE_CLS(type,asn1::prim::types::UInt64,asn1::types::UNIVERSAL,2,UInt64)
+ASN1_TYPE_CLS(type,asn1::prim::types::BitString,asn1::types::UNIVERSAL,3,BIT_STRING)
+ASN1_TYPE_CLS(type,asn1::prim::types::String,asn1::types::UNIVERSAL,4,OCTET_STRING)
+ASN1_TYPE_CLS(type,asn1::prim::types::String,asn1::types::UNIVERSAL,4,STRING)
+ASN1_TYPE_CLS(type,asn1::prim::types::Integer,asn1::types::UNIVERSAL,5,Null)
+    //ASN1_TYPE_CLS(type,asn1::prim::types::Integer,asn1::types::UNIVERSAL,6,OBJECT_IDENTIFIER)
+ASN1_TYPE_CLS(type,asn1::prim::types::String,asn1::types::UNIVERSAL,8,EXTERNAL)
+ASN1_TYPE_CLS(type,asn1::prim::types::UTCTime,asn1::types::UNIVERSAL,24,GeneralizedTime)
+ASN1_TYPE_CLS(type,asn1::prim::types::UTCTime,asn1::types::UNIVERSAL,23,UTCTime)
+ASN1_TYPE_CLS(type,asn1::prim::types::Real,asn1::types::UNIVERSAL,9,REAL)
+ASN1_TYPE_CLS(type,asn1::prim::types::Integer,asn1::types::UNIVERSAL,10,ENUMERATED)
+    
+    typedef asn1::types::any_type ANY;
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,12,UTF8String)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,18,NumericString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,19,PrintableString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,20,TeletexString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,21,VideotexString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,22,IA5String)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,25,GraphicString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,26,VisibleString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,27,GeneralString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,29,UniversalString)
+ASN1_TYPE_CLS(strtype,asn1::prim::types::String,asn1::types::UNIVERSAL,30,BMPString)
+ASN1_TYPE_CLS(type,asn1::prim::types::ObjectIdentifier,asn1::types::UNIVERSAL,6,OBJECT_IDENTIFIER_NG)
+#undef ASN1_TYPE_CLS   
+
+    class ObjectIdentifier;
+    
+    std::ostream & operator <<(std::ostream &os, const ObjectIdentifier &s);
+
+    /**
+     * ASN1 ObjectIdentifier
+     */
+    class ObjectIdentifier : public asn1::prim::types::ObjectIdentifier
+                   , public asn1::types::type
+    {
+      public:
+
+        ObjectIdentifier(int len = 0,const char *buf = NULL) ;
+        
+        ObjectIdentifier(const asn1::tag &t) ;
+
+        ObjectIdentifier(const ObjectIdentifier &c)
+          : asn1::types::type(c.tag())
+            , asn1::prim::types::ObjectIdentifier(c)
+        { };
+        // What is this for ?
+        ObjectIdentifier(const ObjectIdentifier &c,int v)  
+          : asn1::types::type(c.tag())
+            , asn1::prim::types::ObjectIdentifier(c)
+        { };
+        
+        ObjectIdentifier &operator =(const ObjectIdentifier &c) ;
+        
+        ObjectIdentifier *clone()
+        { return new ObjectIdentifier(*this); };
+
+        virtual size_t get_data_length() const
+        { return 0 ; }
+
+        bool operator ==(const ObjectIdentifier &o) ;
+        
+        virtual void encode(asn1::context &ctx);
+
+        virtual int decode(asn1::context &ctx);
+        
+        inline size_t size() {return m_len;}
+        
+        virtual ~ObjectIdentifier() {};
+    
+        virtual void printf(std::ostream &os) const {os<<*this;};
+        
+        friend  std::ostream &operator << (std::ostream &os,const ObjectIdentifier &o) ;
+    };
+    
+    typedef ObjectIdentifier OBJECT_IDENTIFIER;
+    
+    /**
+     *
+     *
+     */
+    template <typename T>
+    class Seq : public  asn1::types::container<T>
+    {
+      public:
+        typedef typename asn1::types::container<T>::iterator iterator;
+        typedef typename asn1::types::container<T>::const_iterator const_iterator ;
+
+        Seq(const asn1::tag &t = asn1::tag(asn1::types::UNIVERSAL,16,true))
+          : asn1::types::container<T>(t) 
+        {
+//          std::cerr<<"Seq<T>::Seq<T>(t="<<(int)t.byte()<<")\n";
+        };
+        Seq(const Seq<T> &c) :
+            asn1::types::container<T>(asn1::tag(c.tag())) 
+        {
+//           std::cerr<<"Seq<T>::Seq<T> m_="<<this->m_.size()<<" c:"<<c.m_.size()<<std::endl;
+            this->m_ = c.m_;
+//    std::cerr<<" After:"<<this->m_.size()<<std::endl;
+        };
+        Seq(const T &c) :
+          asn1::types::container<T>(asn1::tag(asn1::types::UNIVERSAL,16,true)) 
+        {
+//            std::cerr<<"Seq:: copy base :"<<this->m_.size()<<std::endl;
+            this->m_.push_back(c);
+        };
+        
+        inline Seq<T> &operator=(const Seq<T> &c)
+        {
+          if (this != &c)
+          {
+            this->m_ = c.m_;
+          } 
+          return *this;
+        }
+
+        Seq<T> &get_value()
+        { 
+          return *this;
+        }
+        
+        const Seq<T> &get_value() const 
+        { 
+          return *this; 
+        }
+
+        virtual Seq<T> *clone() 
+        {
+          return new Seq<T>(*this);
+        }
+
+        bool operator ==(const Seq<T> &o) const
+        {
+          std::cerr<<"TODO implement Seq<T> =="<<std::endl;
+          return false;
+        }
+
+        virtual size_t get_data_length() const
+        { return 0 ; }
+        
+        inline void push_back(T &t)
+        {
+          this->::asn1::types::container<T>::push_back(t);
+        };
+
+        inline iterator begin()
+        { return this->::asn1::types::container<T>::begin(); };
+
+        inline const_iterator begin() const
+        { return this->::asn1::types::container<T>::begin(); };
+
+        inline iterator end()
+        { return this->::asn1::types::container<T>::end(); };
+
+        inline const_iterator end() const
+        { return this->::asn1::types::container<T>::end(); };
+
+        inline T operator [](int i)
+        { return this->m_[i]; };
+
+        virtual ~Seq() ;
+
+      virtual void encode(asn1::context &ctx);
+      virtual int  decode(asn1::context &ctx);
+
+      friend std::ostream &operator <<(std::ostream &os,const Seq<T> &t)
+      {
+        int count = 0;
+        typename ::asn1::types::container<T>::const_iterator  mit= 
+          const_cast<Seq<T> &>(t).begin();
+        os << "SEQUENCE OF"<<std::endl;
+        for (; 
+            mit != const_cast<Seq<T> &>(t).end();
+            ++mit)
+        {
+          std::streamsize indent = os.precision() + 2;
+          os<<std::setw(indent+2)<<"["<<count++<<"] "<<std::setprecision(indent)<<(*mit)<<"\n";
+          os<<std::setprecision(indent-2);
+        }
+        return os;
+      };
+    };
+
+
+    template <typename T>
+    class Set : public asn1::types::container<T>
+    {
+      public:
+        typedef typename asn1::types::container<T>::iterator iterator;
+        typedef typename asn1::types::container<T>::const_iterator const_iterator ;
+        Set(const asn1::tag &t = asn1::tag(asn1::types::UNIVERSAL,17,true))
+            : asn1::types::container<T>(t)
+        {};
+        
+        virtual ~Set() {};
+
+        Set(const Set<T> &c) : 
+            asn1::types::container<T>(asn1::tag(c.tag()))
+        {
+            this->m_ = c.m_;
+        }
+        inline Set<T> &operator=(const Set<T> &c)
+        {
+            this->m_ = c.m_;
+            return *this;
+        }
+        virtual Set<T> *clone() 
+        {
+          return new Set<T>(*this);
+        }
+
+        virtual size_t get_data_length() const
+        { return 0 ; }
+        
+        Set<T> &get_value() { return *this; }
+        
+        const Set<T> &get_value() const { return *this; }
+        Set(const T &c) : 
+            asn1::types::container<T>(asn1::tag(asn1::types::UNIVERSAL,17))
+        {
+            this->m_.push_back(c);
+        }
+        
+        bool operator ==(const Set<T> &o) const
+        {
+          std::cerr<<"TODO implement Seq<T> =="<<std::endl;
+          return false;
+        }
+        
+        inline iterator begin()
+        { return this->::asn1::types::container<T>::begin(); };
+
+        inline const_iterator begin() const
+        { return this->::asn1::types::container<T>::begin(); }
+        
+        inline iterator end()
+        { return this->::asn1::types::container<T>::end(); };
+
+        inline const_iterator end() const
+        { return this->::asn1::types::container<T>::end(); };
+
+        virtual const asn1::tag &tag() const
+        {
+            return this->::asn1::types::container<T>::tag();
+        };
+
+        virtual void encode(asn1::context &ctx);
+
+        virtual int  decode(asn1::context &ctx);
+
+        inline T operator [](int i) {return this->m_[i];};
+
+        friend std::ostream &operator <<(std::ostream &os,const Set<T> &t)
+        {
+          int count = 0;
+          typename ::asn1::types::container<T>::const_iterator  mit= 
+            const_cast<Set<T> &>(t).begin();
+            for (; 
+                mit != const_cast<Set<T> &>(t).end();
+                ++mit)
+               os<<"SET OF ["<<count++<<"]"<< (*mit)<<"\n";
+          return os;
+        };
+    };
+
+
+}
+
+/*
+ * vim: et sw=2 ts=2 list:
+ */
+#endif
diff --git a/rtasn1/asn1_types.hpp b/rtasn1/asn1_types.hpp
new file mode 100644 (file)
index 0000000..d67a1c6
--- /dev/null
@@ -0,0 +1,148 @@
+
+namespace asn1 {
+
+namespace types {
+
+
+// End of namespace types
+}
+
+/**
+ * Seq Template definition
+ */
+template <typename T>
+Seq<T>::~Seq() {
+  this->m_.erase(this->m_.begin(),this->m_.end());
+//  ASN1_BER_LOG_DEBUG("Seq::~Seq SEQUENCE OF %s [size=%zu]",typeid(T).name(),this->m_.size());
+  
+};
+
+template<typename T>
+void Seq<T>::encode(asn1::context &ctx)
+{
+  iterator  mit;
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  ASN1_BER_LOG_DEBUG("Seq<T>::encode SEQUENCE-OF %s %s",typeid(T).name(),__FUNCTION__);
+  asn1::tag t_(0,16,true);
+  b[pos] = t_.byte() | 0x20;
+  ctx.nb_bits(16);
+  for (mit = begin(); 
+        mit != end();
+        ++mit)
+  {
+    ASN1_BER_LOG_DEBUG("Seq<T>::encode call encode on item ");
+    (*mit).T::encode(ctx);
+  }
+  b[pos+1]= ctx.bytes()-pos-2;
+}
+
+template<typename T>
+int Seq<T>::decode(asn1::context &ctx)
+{
+  int ret = asn1::ok;
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  long llen = 0;
+  long i    = 0;
+  long nb = 1; // I need to find a way to get the length
+  ASN1_BER_LOG_DEBUG("Seq<T>::decode SEQUENCE-OF %s check_tag:%d  b[pos]=%d b[pos+1]=%d b[pos+2]=%d",typeid(T).name(),ctx.check_tag(),b[pos],
+        static_cast<int>(static_cast<unsigned char>(b[pos+1])),
+        static_cast<int>(static_cast<unsigned char>(b[pos+2])));
+  long len = asn1::types::length(&b[pos+1],&nb);
+  ctx.nb_bits(((nb)<<3)+8);
+  if (len == 0 )
+  {
+    return  0;
+  }
+  do {
+    T element;
+    //ret = this->m_.back().decode(ctx);
+    ret = element.decode(ctx);
+    if (ret != asn1::ok)
+      break;
+    this->m_.resize(nb);
+    //this->m_.push_back(element);
+    this->m_[i++] = element;
+    nb++;
+    llen = ctx.bytes();
+  } while ((llen-(long)pos) < len);
+  
+  if ((this->m_.size() == 0)) 
+  { // Failed decoding ....
+    ctx.nb_bits(-1*(((nb)<<3)+8));
+  }
+  ASN1_BER_LOG_DEBUG("Seq<T>::decode SEQUENCE-OF %s %s GOT %lu END",typeid(T).name(),__FUNCTION__,this->m_.size());
+  return ret;
+}
+
+/**
+ *
+ */
+/**
+ * Set Template definition
+ */
+template<typename T>
+void Set<T>::encode(asn1::context &ctx)
+{
+  iterator  mit;
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  ASN1_BER_LOG_DEBUG("Set<T>::encode SET-OF %s %s",typeid(T).name(),__FUNCTION__);
+  asn1::tag t_(0,17,true);
+  b[pos] = t_.byte() | 0x20;
+  ctx.nb_bits(16);
+  for (mit = begin(); 
+        mit != end();
+        ++mit)
+  {
+    ASN1_BER_LOG_DEBUG("Set<T>::encode call encode on item ");
+    (*mit).encode(ctx);
+  }
+  b[pos+1]= ctx.bytes()-pos-2;
+}
+
+template<typename T>
+int Set<T>::decode(asn1::context &ctx)
+{
+  int ret = asn1::ok;
+  unsigned long pos = ctx.bytes();
+  unsigned char *b = ctx.buffer();
+  long llen = 0;
+  long i    = 0;
+  long nb = 1; // I need to find a way to get the length
+  ASN1_BER_LOG_DEBUG("Set<T>::decode SET-OF %s check_tag:%d  b[pos]=%d b[pos+1]=%d b[pos+2]=%d",typeid(T).name(),ctx.check_tag(),b[pos],
+        static_cast<int>(static_cast<unsigned char>(b[pos+1])),
+        static_cast<int>(static_cast<unsigned char>(b[pos+2])));
+  long len = asn1::types::length(&b[pos+1],&nb);
+  ctx.nb_bits(((nb)<<3)+8);
+  if (len == 0 )
+  {
+    return  0;
+  }
+  do {
+    T element;
+    //ret = this->m_.back().decode(ctx);
+    ret = element.decode(ctx);
+    if (ret != asn1::ok)
+      break;
+    this->m_.resize(nb);
+    //this->m_.push_back(element);
+    this->m_[i++] = element;
+    nb++;
+    llen = ctx.bytes();
+  } while ((llen-pos) < len);
+  
+  if ((this->m_.size() == 0)) 
+  { // Failed decoding ....
+    ctx.nb_bits(-1*(((nb)<<3)+8));
+  }
+  ASN1_BER_LOG_DEBUG("Set<T>::decode SET-OF %s %s GOT %lu END"
+                    ,typeid(T).name()
+                    ,__FUNCTION__
+                    ,this->m_.size());
+  return ret;
+}
+
+
+}
diff --git a/rtasn1/asn1_types.inc b/rtasn1/asn1_types.inc
new file mode 100644 (file)
index 0000000..863b7ac
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef ASN1_TYPE_CLS
+#  define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type)
+#endif
+
+ASN1_TYPE_CLS(asn1::prim::types::Boolean,asn1::types::UNIVERSAL,1,BOOLEAN)
+ASN1_TYPE_CLS(asn1::prim::types::Integer,asn1::types::UNIVERSAL,2,INTEGER)
+ASN1_TYPE_CLS(asn1::prim::types::Int8,asn1::types::UNIVERSAL,2,Int8)
+ASN1_TYPE_CLS(asn1::prim::types::Int16,asn1::types::UNIVERSAL,2,Int16)
+ASN1_TYPE_CLS(asn1::prim::types::Int32,asn1::types::UNIVERSAL,2,Int32)
+ASN1_TYPE_CLS(asn1::prim::types::Int64,asn1::types::UNIVERSAL,2,Int64)
+ASN1_TYPE_CLS(asn1::prim::types::UInt8,asn1::types::UNIVERSAL,2,UInt8)
+ASN1_TYPE_CLS(asn1::prim::types::UInt16,asn1::types::UNIVERSAL,2,UInt16)
+ASN1_TYPE_CLS(asn1::prim::types::UInt32,asn1::types::UNIVERSAL,2,UInt32)
+ASN1_TYPE_CLS(asn1::prim::types::UInt64,asn1::types::UNIVERSAL,2,UInt64)
+ASN1_TYPE_CLS(asn1::prim::types::BitString,asn1::types::UNIVERSAL,3,BIT_STRING)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,4,OCTET_STRING)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,4,STRING)
+ASN1_TYPE_CLS(asn1::prim::types::Integer,asn1::types::UNIVERSAL,5,Null)
+// ASN1_TYPE_CLS(asn1::prim::types::Integer,asn1::types::UNIVERSAL,6,OBJECT_IDENTIFIER)
+ASN1_TYPE_CLS(asn1::prim::types::ObjectIdentifier,asn1::types::UNIVERSAL,6,OBJECT_IDENTIFIER_NG)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,8,EXTERNAL)
+ASN1_TYPE_CLS(asn1::prim::types::UTCTime,asn1::types::UNIVERSAL,24,GeneralizedTime)
+ASN1_TYPE_CLS(asn1::prim::types::UTCTime,asn1::types::UNIVERSAL,23,UTCTime)
+ASN1_TYPE_CLS(asn1::prim::types::Real,asn1::types::UNIVERSAL,9,REAL)
+ASN1_TYPE_CLS(asn1::prim::types::Integer,asn1::types::UNIVERSAL,10,ENUMERATED)
+// typedef asn1::types::any_type ANY;
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,12,UTF8String)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,18,NumericString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,19,PrintableString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,20,TeletexString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,21,VideotexString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,22,IA5String)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,25,GraphicString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,26,VisibleString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,27,GeneralString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,29,UniversalString)
+ASN1_TYPE_CLS(asn1::prim::types::String,asn1::types::UNIVERSAL,30,BMPString)
+
+#undef ASN1_TYPE_CLS   
diff --git a/rtasn1/cjson/LICENSE b/rtasn1/cjson/LICENSE
new file mode 100644 (file)
index 0000000..fa0a438
--- /dev/null
@@ -0,0 +1,20 @@
+  Copyright (c) 2009 Dave Gamble
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+
diff --git a/rtasn1/cjson/README b/rtasn1/cjson/README
new file mode 100644 (file)
index 0000000..7531c04
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+  Copyright (c) 2009 Dave Gamble
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+Welcome to cJSON.
+
+cJSON aims to be the dumbest possible parser that you can get your job done with.
+It's a single file of C, and a single header file.
+
+JSON is described best here: http://www.json.org/
+It's like XML, but fat-free. You use it to move data around, store things, or just
+generally represent your program's state.
+
+
+First up, how do I build?
+Add cJSON.c to your project, and put cJSON.h somewhere in the header search path.
+For example, to build the test app:
+
+gcc cJSON.c test.c -o test -lm
+./test
+
+
+As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
+As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
+in one of two modes: Auto and Manual. Let's have a quick run-through.
+
+
+I lifted some JSON from this page: http://www.json.org/fatfree.html
+That page inspired me to write cJSON, which is a parser that tries to share the same
+philosophy as JSON itself. Simple, dumb, out of the way.
+
+Some JSON:
+{
+    "name": "Jack (\"Bee\") Nimble", 
+    "format": {
+        "type":       "rect", 
+        "width":      1920, 
+        "height":     1080, 
+        "interlace":  false, 
+        "frame rate": 24
+    }
+}
+
+Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
+you have a char * to it. Everything is a cJSON struct.
+Get it parsed:
+       cJSON *root = cJSON_Parse(my_json_string);
+
+This is an object. We're in C. We don't have objects. But we do have structs.
+What's the framerate?
+
+       cJSON *format = cJSON_GetObjectItem(root,"format");
+       int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
+
+
+Want to change the framerate?
+       cJSON_GetObjectItem(format,"frame rate")->valueint=25;
+       
+Back to disk?
+       char *rendered=cJSON_Print(root);
+
+Finished? Delete the root (this takes care of everything else).
+       cJSON_Delete(root);
+
+That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
+before you dereference them. If you want to see how you'd build this struct in code?
+       cJSON *root,*fmt;
+       root=cJSON_CreateObject();      
+       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
+       cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
+       cJSON_AddStringToObject(fmt,"type",             "rect");
+       cJSON_AddNumberToObject(fmt,"width",            1920);
+       cJSON_AddNumberToObject(fmt,"height",           1080);
+       cJSON_AddFalseToObject (fmt,"interlace");
+       cJSON_AddNumberToObject(fmt,"frame rate",       24);
+
+Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
+Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
+a few from elsewhere.
+
+What about manual mode? First up you need some detail.
+Let's cover how the cJSON objects represent the JSON data.
+cJSON doesn't distinguish arrays from objects in handling; just type.
+Each cJSON has, potentially, a child, siblings, value, a name.
+
+The root object has: Object Type and a Child
+The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
+Sibling has type Object, name "format", and a child.
+That child has type String, name "type", value "rect", and a sibling:
+Sibling has type Number, name "width", value 1920, and a sibling:
+Sibling has type Number, name "height", value 1080, and a sibling:
+Sibling hs type False, name "interlace", and a sibling:
+Sibling has type Number, name "frame rate", value 24
+
+Here's the structure:
+typedef struct cJSON {
+       struct cJSON *next,*prev;
+       struct cJSON *child;
+
+       int type;
+
+       char *valuestring;
+       int valueint;
+       double valuedouble;
+
+       char *string;
+} cJSON;
+
+By default all values are 0 unless set by virtue of being meaningful.
+
+next/prev is a doubly linked list of siblings. next takes you to your sibling,
+prev takes you back from your sibling to you.
+Only objects and arrays have a "child", and it's the head of the doubly linked list.
+A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0.
+The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in
+cJSON.h
+
+A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
+valuedouble.
+
+Any entry which is in the linked list which is the child of an object will have a "string"
+which is the "name" of the entry. When I said "name" in the above example, that's "string".
+"string" is the JSON name for the 'variable name' if you will.
+
+Now you can trivially walk the lists, recursively, and parse as you please.
+You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take
+the root object, and traverse the structure (which is, formally, an N-tree),
+and tokenise as you please. If you wanted to build a callback style parser, this is how
+you'd do it (just an example, since these things are very specific):
+
+void parse_and_callback(cJSON *item,const char *prefix)
+{
+       while (item)
+       {
+               char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
+               sprintf(newprefix,"%s/%s",prefix,item->name);
+               int dorecurse=callback(newprefix, item->type, item);
+               if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
+               item=item->next;
+               free(newprefix);
+       }
+}
+
+The prefix process will build you a separated list, to simplify your callback handling.
+The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
+let you invoke it per-item. For the item above, your callback might look like this:
+
+int callback(const char *name,int type,cJSON *item)
+{
+       if (!strcmp(name,"name"))       { /* populate name */ }
+       else if (!strcmp(name,"format/type")    { /* handle "rect" */ }
+       else if (!strcmp(name,"format/width")   { /* 800 */ }
+       else if (!strcmp(name,"format/height")  { /* 600 */ }
+       else if (!strcmp(name,"format/interlace")       { /* false */ }
+       else if (!strcmp(name,"format/frame rate")      { /* 24 */ }
+       return 1;
+}
+
+Alternatively, you might like to parse iteratively.
+You'd use:
+
+void parse_object(cJSON *item)
+{
+       int i; for (i=0;i<cJSON_GetArraySize(item);i++)
+       {
+               cJSON *subitem=cJSON_GetArrayItem(item,i);
+               // handle subitem.      
+       }
+}
+
+Or, for PROPER manual mode:
+
+void parse_object(cJSON *item)
+{
+       cJSON *subitem=item->child;
+       while (subitem)
+       {
+               // handle subitem
+               if (subitem->child) parse_object(subitem->child);
+               
+               subitem=subitem->next;
+       }
+}
+
+Of course, this should look familiar, since this is just a stripped-down version
+of the callback-parser.
+
+This should cover most uses you'll find for parsing. The rest should be possible
+to infer.. and if in doubt, read the source! There's not a lot of it! ;)
+
+
+In terms of constructing JSON data, the example code above is the right way to do it.
+You can, of course, hand your sub-objects to other functions to populate.
+Also, if you find a use for it, you can manually build the objects.
+For instance, suppose you wanted to build an array of objects?
+
+cJSON *objects[24];
+
+cJSON *Create_array_of_anything(cJSON **items,int num)
+{
+       int i;cJSON *prev, *root=cJSON_CreateArray();
+       for (i=0;i<24;i++)
+       {
+               if (!i) root->child=objects[i];
+               else    prev->next=objects[i], objects[i]->prev=prev;
+               prev=objects[i];
+       }
+       return root;
+}
+       
+and simply: Create_array_of_anything(objects,24);
+
+cJSON doesn't make any assumptions about what order you create things in.
+You can attach the objects, as above, and later add children to each
+of those objects.
+
+As soon as you call cJSON_Print, it renders the structure to text.
+
+
+
+The test.c code shows how to handle a bunch of typical cases. If you uncomment
+the code, it'll load, parse and print a bunch of test files, also from json.org,
+which are more complex than I'd care to try and stash into a const char array[].
+
+
+Enjoy cJSON!
+
+
+- Dave Gamble, Aug 2009
diff --git a/rtasn1/cjson/cJSON.c b/rtasn1/cjson/cJSON.c
new file mode 100644 (file)
index 0000000..31c43dd
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+  Copyright (c) 2009 Dave Gamble
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+static const char *ep;
+
+const char *cJSON_GetErrorPtr(void) {return ep;}
+
+static int cJSON_strcasecmp(const char *s1,const char *s2)
+{
+       if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
+       for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0)    return 0;
+       return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char* cJSON_strdup(const char* str)
+{
+      size_t len;
+      char* copy;
+
+      len = strlen(str) + 1;
+      if (!(copy = (char*)cJSON_malloc(len))) return 0;
+      memcpy(copy,str,len);
+      return copy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+    if (!hooks) { /* Reset hooks */
+        cJSON_malloc = malloc;
+        cJSON_free = free;
+        return;
+    }
+
+       cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
+       cJSON_free       = (hooks->free_fn)?hooks->free_fn:free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(void)
+{
+       cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
+       if (node) memset(node,0,sizeof(cJSON));
+       return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c)
+{
+       cJSON *next;
+       while (c)
+       {
+               next=c->next;
+               if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+               if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+               if (c->string) cJSON_free(c->string);
+               cJSON_free(c);
+               c=next;
+       }
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char *parse_number(cJSON *item,const char *num)
+{
+       double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
+
+       if (*num=='-') sign=-1,num++;   /* Has sign? */
+       if (*num=='0') num++;                   /* is zero */
+       if (*num>='1' && *num<='9')     do      n=(n*10.0)+(*num++ -'0');       while (*num>='0' && *num<='9'); /* Number? */
+       if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;            do      n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}      /* Fractional part? */
+       if (*num=='e' || *num=='E')             /* Exponent? */
+       {       num++;if (*num=='+') num++;     else if (*num=='-') signsubscale=-1,num++;              /* With sign? */
+               while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
+       }
+
+       n=sign*n*pow(10.0,(scale+subscale*signsubscale));       /* number = +/- number.fraction * 10^+/- exponent */
+       
+       item->valuedouble=n;
+       item->valueint=(int)n;
+       item->type=cJSON_Number;
+       return num;
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(cJSON *item)
+{
+       char *str;
+       double d=item->valuedouble;
+       if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+       {
+               str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
+               if (str) sprintf(str,"%d",item->valueint);
+       }
+       else
+       {
+               str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
+               if (str)
+               {
+                       if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
+                       else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)                       sprintf(str,"%e",d);
+                       else                                                                                            sprintf(str,"%f",d);
+               }
+       }
+       return str;
+}
+
+static unsigned parse_hex4(const char *str)
+{
+       unsigned h=0;
+       if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+       h=h<<4;str++;
+       if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+       h=h<<4;str++;
+       if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+       h=h<<4;str++;
+       if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+       return h;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+static const char *parse_string(cJSON *item,const char *str)
+{
+       const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
+       if (*str!='\"') {ep=str;return 0;}      /* not a string! */
+       
+       while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;  /* Skip escaped quotes. */
+       
+       out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
+       if (!out) return 0;
+       
+       ptr=str+1;ptr2=out;
+       while (*ptr!='\"' && *ptr)
+       {
+               if (*ptr!='\\') *ptr2++=*ptr++;
+               else
+               {
+                       ptr++;
+                       switch (*ptr)
+                       {
+                               case 'b': *ptr2++='\b'; break;
+                               case 'f': *ptr2++='\f'; break;
+                               case 'n': *ptr2++='\n'; break;
+                               case 'r': *ptr2++='\r'; break;
+                               case 't': *ptr2++='\t'; break;
+                               case 'u':        /* transcode utf16 to utf8. */
+                                       uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */
+
+                                       if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)        break;  /* check for invalid.   */
+
+                                       if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.       */
+                                       {
+                                               if (ptr[1]!='\\' || ptr[2]!='u')        break;  /* missing second-half of surrogate.    */
+                                               uc2=parse_hex4(ptr+3);ptr+=6;
+                                               if (uc2<0xDC00 || uc2>0xDFFF)           break;  /* invalid second-half of surrogate.    */
+                                               uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
+                                       }
+
+                                       len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
+                                       
+                                       switch (len) {
+                                               case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+                                               case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+                                               case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+                                               case 1: *--ptr2 =(uc | firstByteMark[len]);
+                                       }
+                                       ptr2+=len;
+                                       break;
+                               default:  *ptr2++=*ptr; break;
+                       }
+                       ptr++;
+               }
+       }
+       *ptr2=0;
+       if (*ptr=='\"') ptr++;
+       item->valuestring=out;
+       item->type=cJSON_String;
+       return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str)
+{
+       const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
+       
+       if (!str) return cJSON_strdup("");
+       ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
+       
+       out=(char*)cJSON_malloc(len+3);
+       if (!out) return 0;
+
+       ptr2=out;ptr=str;
+       *ptr2++='\"';
+       while (*ptr)
+       {
+               if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
+               else
+               {
+                       *ptr2++='\\';
+                       switch (token=*ptr++)
+                       {
+                               case '\\':      *ptr2++='\\';   break;
+                               case '\"':      *ptr2++='\"';   break;
+                               case '\b':      *ptr2++='b';    break;
+                               case '\f':      *ptr2++='f';    break;
+                               case '\n':      *ptr2++='n';    break;
+                               case '\r':      *ptr2++='r';    break;
+                               case '\t':      *ptr2++='t';    break;
+                               default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
+                       }
+               }
+       }
+       *ptr2++='\"';*ptr2++=0;
+       return out;
+}
+/* Invote print_string_ptr (which is useful) on an item. */
+static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item,const char *value);
+static char *print_value(cJSON *item,int depth,int fmt);
+static const char *parse_array(cJSON *item,const char *value);
+static char *print_array(cJSON *item,int depth,int fmt);
+static const char *parse_object(cJSON *item,const char *value);
+static char *print_object(cJSON *item,int depth,int fmt);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
+{
+       const char *end=0;
+       cJSON *c=cJSON_New_Item();
+       ep=0;
+       if (!c) return 0;       /* memory fail */
+
+       end=parse_value(c,skip(value));
+       if (!end)       {cJSON_Delete(c);return 0;}     /* parse failure. ep is set. */
+
+       /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+       if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
+       if (return_parse_end) *return_parse_end=end;
+       return c;
+}
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(cJSON *item)                         {return print_value(item,0,1);}
+char *cJSON_PrintUnformatted(cJSON *item)      {return print_value(item,0,0);}
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item,const char *value)
+{
+       if (!value)                                             return 0;       /* Fail on null. */
+       if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
+       if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
+       if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;      return value+4; }
+       if (*value=='\"')                               { return parse_string(item,value); }
+       if (*value=='-' || (*value>='0' && *value<='9'))        { return parse_number(item,value); }
+       if (*value=='[')                                { return parse_array(item,value); }
+       if (*value=='{')                                { return parse_object(item,value); }
+
+       ep=value;return 0;      /* failure. */
+}
+
+/* Render a value to text. */
+static char *print_value(cJSON *item,int depth,int fmt)
+{
+       char *out=0;
+       if (!item) return 0;
+       switch ((item->type)&255)
+       {
+               case cJSON_NULL:        out=cJSON_strdup("null");       break;
+               case cJSON_False:       out=cJSON_strdup("false");break;
+               case cJSON_True:        out=cJSON_strdup("true"); break;
+               case cJSON_Number:      out=print_number(item);break;
+               case cJSON_String:      out=print_string(item);break;
+               case cJSON_Array:       out=print_array(item,depth,fmt);break;
+               case cJSON_Object:      out=print_object(item,depth,fmt);break;
+       }
+       return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item,const char *value)
+{
+       cJSON *child;
+       if (*value!='[')        {ep=value;return 0;}    /* not an array! */
+
+       item->type=cJSON_Array;
+       value=skip(value+1);
+       if (*value==']') return value+1;        /* empty array. */
+
+       item->child=child=cJSON_New_Item();
+       if (!item->child) return 0;              /* memory fail */
+       value=skip(parse_value(child,skip(value)));     /* skip any spacing, get the value. */
+       if (!value) return 0;
+
+       while (*value==',')
+       {
+               cJSON *new_item;
+               if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
+               child->next=new_item;new_item->prev=child;child=new_item;
+               value=skip(parse_value(child,skip(value+1)));
+               if (!value) return 0;   /* memory fail */
+       }
+
+       if (*value==']') return value+1;        /* end of array */
+       ep=value;return 0;      /* malformed. */
+}
+
+/* Render an array to text */
+static char *print_array(cJSON *item,int depth,int fmt)
+{
+       char **entries;
+       char *out=0,*ptr,*ret;int len=5;
+       cJSON *child=item->child;
+       int numentries=0,i=0,fail=0;
+       
+       /* How many entries in the array? */
+       while (child) numentries++,child=child->next;
+       /* Explicitly handle numentries==0 */
+       if (!numentries)
+       {
+               out=(char*)cJSON_malloc(3);
+               if (out) strcpy(out,"[]");
+               return out;
+       }
+       /* Allocate an array to hold the values for each */
+       entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+       if (!entries) return 0;
+       memset(entries,0,numentries*sizeof(char*));
+       /* Retrieve all the results: */
+       child=item->child;
+       while (child && !fail)
+       {
+               ret=print_value(child,depth+1,fmt);
+               entries[i++]=ret;
+               if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
+               child=child->next;
+       }
+       
+       /* If we didn't fail, try to malloc the output string */
+       if (!fail) out=(char*)cJSON_malloc(len);
+       /* If that fails, we fail. */
+       if (!out) fail=1;
+
+       /* Handle failure. */
+       if (fail)
+       {
+               for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
+               cJSON_free(entries);
+               return 0;
+       }
+       
+       /* Compose the output array. */
+       *out='[';
+       ptr=out+1;*ptr=0;
+       for (i=0;i<numentries;i++)
+       {
+               strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+               if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
+               cJSON_free(entries[i]);
+       }
+       cJSON_free(entries);
+       *ptr++=']';*ptr++=0;
+       return out;     
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item,const char *value)
+{
+       cJSON *child;
+       if (*value!='{')        {ep=value;return 0;}    /* not an object! */
+       
+       item->type=cJSON_Object;
+       value=skip(value+1);
+       if (*value=='}') return value+1;        /* empty array. */
+       
+       item->child=child=cJSON_New_Item();
+       if (!item->child) return 0;
+       value=skip(parse_string(child,skip(value)));
+       if (!value) return 0;
+       child->string=child->valuestring;child->valuestring=0;
+       if (*value!=':') {ep=value;return 0;}   /* fail! */
+       value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
+       if (!value) return 0;
+       
+       while (*value==',')
+       {
+               cJSON *new_item;
+               if (!(new_item=cJSON_New_Item()))       return 0; /* memory fail */
+               child->next=new_item;new_item->prev=child;child=new_item;
+               value=skip(parse_string(child,skip(value+1)));
+               if (!value) return 0;
+               child->string=child->valuestring;child->valuestring=0;
+               if (*value!=':') {ep=value;return 0;}   /* fail! */
+               value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
+               if (!value) return 0;
+       }
+       
+       if (*value=='}') return value+1;        /* end of array */
+       ep=value;return 0;      /* malformed. */
+}
+
+/* Render an object to text. */
+static char *print_object(cJSON *item,int depth,int fmt)
+{
+       char **entries=0,**names=0;
+       char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
+       cJSON *child=item->child;
+       int numentries=0,fail=0;
+       /* Count the number of entries. */
+       while (child) numentries++,child=child->next;
+       /* Explicitly handle empty object case */
+       if (!numentries)
+       {
+               out=(char*)cJSON_malloc(fmt?depth+4:3);
+               if (!out)       return 0;
+               ptr=out;*ptr++='{';
+               if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
+               *ptr++='}';*ptr++=0;
+               return out;
+       }
+       /* Allocate space for the names and the objects */
+       entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+       if (!entries) return 0;
+       names=(char**)cJSON_malloc(numentries*sizeof(char*));
+       if (!names) {cJSON_free(entries);return 0;}
+       memset(entries,0,sizeof(char*)*numentries);
+       memset(names,0,sizeof(char*)*numentries);
+
+       /* Collect all the results into our arrays: */
+       child=item->child;depth++;if (fmt) len+=depth;
+       while (child)
+       {
+               names[i]=str=print_string_ptr(child->string);
+               entries[i++]=ret=print_value(child,depth,fmt);
+               if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
+               child=child->next;
+       }
+       
+       /* Try to allocate the output string */
+       if (!fail) out=(char*)cJSON_malloc(len);
+       if (!out) fail=1;
+
+       /* Handle failure */
+       if (fail)
+       {
+               for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
+               cJSON_free(names);cJSON_free(entries);
+               return 0;
+       }
+       
+       /* Compose the output: */
+       *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
+       for (i=0;i<numentries;i++)
+       {
+               if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
+               strcpy(ptr,names[i]);ptr+=strlen(names[i]);
+               *ptr++=':';if (fmt) *ptr++='\t';
+               strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+               if (i!=numentries-1) *ptr++=',';
+               if (fmt) *ptr++='\n';*ptr=0;
+               cJSON_free(names[i]);cJSON_free(entries[i]);
+       }
+       
+       cJSON_free(names);cJSON_free(entries);
+       if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
+       *ptr++='}';*ptr++=0;
+       return out;     
+}
+
+/* Get Array size/item / object item. */
+int    cJSON_GetArraySize(cJSON *array)                                                        {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
+cJSON *cJSON_GetArrayItem(cJSON *array,int item)                               {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
+cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)   {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
+/* Utility for handling references. */
+static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
+
+/* Add item to array/object. */
+void   cJSON_AddItemToArray(cJSON *array, cJSON *item)                                         {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
+void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)     {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
+void   cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                                                {cJSON_AddItemToArray(array,create_reference(item));}
+void   cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)                       {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
+       if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
+void   cJSON_DeleteItemFromArray(cJSON *array,int which)                       {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
+cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
+void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
+
+/* Replace array/object items with new ones. */
+void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)         {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
+       newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
+       if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
+void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
+
+/* Create basic types: */
+cJSON *cJSON_CreateNull(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
+cJSON *cJSON_CreateTrue(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
+cJSON *cJSON_CreateFalse(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
+cJSON *cJSON_CreateBool(int b)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
+cJSON *cJSON_CreateNumber(double num)                  {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
+cJSON *cJSON_CreateString(const char *string)  {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
+cJSON *cJSON_CreateArray(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
+cJSON *cJSON_CreateObject(void)                                        {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
+
+/* Create Arrays: */
+cJSON *cJSON_CreateIntArray(const int *numbers,int count)              {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateFloatArray(const float *numbers,int count)  {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateDoubleArray(const double *numbers,int count)        {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+
+/* Duplication */
+cJSON *cJSON_Duplicate(cJSON *item,int recurse)
+{
+       cJSON *newitem,*cptr,*nptr=0,*newchild;
+       /* Bail on bad ptr */
+       if (!item) return 0;
+       /* Create new item */
+       newitem=cJSON_New_Item();
+       if (!newitem) return 0;
+       /* Copy over all vars */
+       newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
+       if (item->valuestring)  {newitem->valuestring=cJSON_strdup(item->valuestring);  if (!newitem->valuestring)      {cJSON_Delete(newitem);return 0;}}
+       if (item->string)               {newitem->string=cJSON_strdup(item->string);                    if (!newitem->string)           {cJSON_Delete(newitem);return 0;}}
+       /* If non-recursive, then we're done! */
+       if (!recurse) return newitem;
+       /* Walk the ->next chain for the child. */
+       cptr=item->child;
+       while (cptr)
+       {
+               newchild=cJSON_Duplicate(cptr,1);               /* Duplicate (with recurse) each item in the ->next chain */
+               if (!newchild) {cJSON_Delete(newitem);return 0;}
+               if (nptr)       {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}        /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+               else            {newitem->child=newchild;nptr=newchild;}                                        /* Set newitem->child and move to it */
+               cptr=cptr->next;
+       }
+       return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+       char *into=json;
+       while (*json)
+       {
+               if (*json==' ') json++;
+               else if (*json=='\t') json++;   // Whitespace characters.
+               else if (*json=='\r') json++;
+               else if (*json=='\n') json++;
+               else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;      // double-slash comments, to end of line.
+               else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   // multiline comments.
+               else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
+               else *into++=*json++;                   // All other characters.
+       }
+       *into=0;        // and null-terminate.
+}
\ No newline at end of file
diff --git a/rtasn1/cjson/cJSON.h b/rtasn1/cjson/cJSON.h
new file mode 100644 (file)
index 0000000..867b7c3
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+  Copyright (c) 2009 Dave Gamble
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* cJSON Types: */
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+       
+#define cJSON_IsReference 256
+
+/* The cJSON structure: */
+typedef struct cJSON {
+       struct cJSON *next,*prev;       /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+       struct cJSON *child;            /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+
+       int type;                                       /* The type of the item, as above. */
+
+       char *valuestring;                      /* The item's string, if type==cJSON_String */
+       int valueint;                           /* The item's number, if type==cJSON_Number */
+       double valuedouble;                     /* The item's number, if type==cJSON_Number */
+
+       char *string;                           /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+} cJSON;
+
+typedef struct cJSON_Hooks {
+      void *(*malloc_fn)(size_t sz);
+      void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+/* Supply malloc, realloc and free functions to cJSON */
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
+extern cJSON *cJSON_Parse(const char *value);
+/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
+extern char  *cJSON_Print(cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
+extern char  *cJSON_PrintUnformatted(cJSON *item);
+/* Delete a cJSON entity and all subentities. */
+extern void   cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+extern int       cJSON_GetArraySize(cJSON *array);
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
+
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char *cJSON_GetErrorPtr(void);
+       
+/* These calls create a cJSON item of the appropriate type. */
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+/* These utilities create an Array of count items. */
+extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
+
+/* Append item to the specified array/object. */
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
+extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
+extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
+       
+/* Update array items. */
+extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+need to be released. With recurse!=0, it will duplicate any children connected to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+/* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object,name)             cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name)             cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name)            cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b)   cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object,val)                  ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rtasn1/cjson/test.c b/rtasn1/cjson/test.c
new file mode 100644 (file)
index 0000000..b308a92
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+  Copyright (c) 2009 Dave Gamble
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "cJSON.h"
+
+/* Parse text to JSON, then render back to text, and print! */
+void doit(char *text)
+{
+       char *out;cJSON *json;
+       
+       json=cJSON_Parse(text);
+       if (!json) {printf("Error before: [%s]\n",cJSON_GetErrorPtr());}
+       else
+       {
+               out=cJSON_Print(json);
+               cJSON_Delete(json);
+               printf("%s\n",out);
+               free(out);
+       }
+}
+
+/* Read a file, parse, render back, etc. */
+void dofile(char *filename)
+{
+       FILE *f=fopen(filename,"rb");fseek(f,0,SEEK_END);long len=ftell(f);fseek(f,0,SEEK_SET);
+       char *data=(char*)malloc(len+1);fread(data,1,len,f);fclose(f);
+       doit(data);
+       free(data);
+}
+
+/* Used by some code below as an example datatype. */
+struct record {const char *precision;double lat,lon;const char *address,*city,*state,*zip,*country; };
+
+/* Create a bunch of objects as demonstration. */
+void create_objects()
+{
+       cJSON *root,*fmt,*img,*thm,*fld;char *out;int i;        /* declare a few. */
+
+       /* Here we construct some JSON standards, from the JSON site. */
+       
+       /* Our "Video" datatype: */
+       root=cJSON_CreateObject();      
+       cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
+       cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject());
+       cJSON_AddStringToObject(fmt,"type",             "rect");
+       cJSON_AddNumberToObject(fmt,"width",            1920);
+       cJSON_AddNumberToObject(fmt,"height",           1080);
+       cJSON_AddFalseToObject (fmt,"interlace");
+       cJSON_AddNumberToObject(fmt,"frame rate",       24);
+       
+       out=cJSON_Print(root);  cJSON_Delete(root);     printf("%s\n",out);     free(out);      /* Print to text, Delete the cJSON, print it, release the string. */
+
+       /* Our "days of the week" array: */
+       const char *strings[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
+       root=cJSON_CreateStringArray(strings,7);
+
+       out=cJSON_Print(root);  cJSON_Delete(root);     printf("%s\n",out);     free(out);
+
+       /* Our matrix: */
+       int numbers[3][3]={{0,-1,0},{1,0,0},{0,0,1}};
+       root=cJSON_CreateArray();
+       for (i=0;i<3;i++) cJSON_AddItemToArray(root,cJSON_CreateIntArray(numbers[i],3));
+
+/*     cJSON_ReplaceItemInArray(root,1,cJSON_CreateString("Replacement")); */
+       
+       out=cJSON_Print(root);  cJSON_Delete(root);     printf("%s\n",out);     free(out);
+
+
+       /* Our "gallery" item: */
+       int ids[4]={116,943,234,38793};
+       root=cJSON_CreateObject();
+       cJSON_AddItemToObject(root, "Image", img=cJSON_CreateObject());
+       cJSON_AddNumberToObject(img,"Width",800);
+       cJSON_AddNumberToObject(img,"Height",600);
+       cJSON_AddStringToObject(img,"Title","View from 15th Floor");
+       cJSON_AddItemToObject(img, "Thumbnail", thm=cJSON_CreateObject());
+       cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943");
+       cJSON_AddNumberToObject(thm,"Height",125);
+       cJSON_AddStringToObject(thm,"Width","100");
+       cJSON_AddItemToObject(img,"IDs", cJSON_CreateIntArray(ids,4));
+
+       out=cJSON_Print(root);  cJSON_Delete(root);     printf("%s\n",out);     free(out);
+
+       /* Our array of "records": */
+       struct record fields[2]={
+               {"zip",37.7668,-1.223959e+2,"","SAN FRANCISCO","CA","94107","US"},
+               {"zip",37.371991,-1.22026e+2,"","SUNNYVALE","CA","94085","US"}};
+
+       root=cJSON_CreateArray();
+       for (i=0;i<2;i++)
+       {
+               cJSON_AddItemToArray(root,fld=cJSON_CreateObject());
+               cJSON_AddStringToObject(fld, "precision", fields[i].precision);
+               cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat);
+               cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon);
+               cJSON_AddStringToObject(fld, "Address", fields[i].address);
+               cJSON_AddStringToObject(fld, "City", fields[i].city);
+               cJSON_AddStringToObject(fld, "State", fields[i].state);
+               cJSON_AddStringToObject(fld, "Zip", fields[i].zip);
+               cJSON_AddStringToObject(fld, "Country", fields[i].country);
+       }
+       
+/*     cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root,1),"City",cJSON_CreateIntArray(ids,4)); */
+       
+       out=cJSON_Print(root);  cJSON_Delete(root);     printf("%s\n",out);     free(out);
+
+}
+
+int main (int argc, const char * argv[]) {
+       /* a bunch of json: */
+       char text1[]="{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n\"format\": {\"type\":       \"rect\", \n\"width\":      1920, \n\"height\":     1080, \n\"interlace\":  false,\"frame rate\": 24\n}\n}";   
+       char text2[]="[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
+       char text3[]="[\n    [0, -1, 0],\n    [1, 0, 0],\n    [0, 0, 1]\n       ]\n";
+       char text4[]="{\n               \"Image\": {\n                  \"Width\":  800,\n                      \"Height\": 600,\n                      \"Title\":  \"View from 15th Floor\",\n                 \"Thumbnail\": {\n                              \"Url\":    \"http:/*www.example.com/image/481989943\",\n                               \"Height\": 125,\n                              \"Width\":  \"100\"\n                   },\n                    \"IDs\": [116, 943, 234, 38793]\n               }\n     }";
+       char text5[]="[\n        {\n     \"precision\": \"zip\",\n       \"Latitude\":  37.7668,\n       \"Longitude\": -122.3959,\n     \"Address\":   \"\",\n  \"City\":      \"SAN FRANCISCO\",\n     \"State\":     \"CA\",\n        \"Zip\":       \"94107\",\n     \"Country\":   \"US\"\n         },\n    {\n     \"precision\": \"zip\",\n       \"Latitude\":  37.371991,\n     \"Longitude\": -122.026020,\n   \"Address\":   \"\",\n  \"City\":      \"SUNNYVALE\",\n         \"State\":     \"CA\",\n        \"Zip\":       \"94085\",\n     \"Country\":   \"US\"\n         }\n     ]";
+
+       /* Process each json textblock by parsing, then rebuilding: */
+       doit(text1);
+       doit(text2);    
+       doit(text3);
+       doit(text4);
+       doit(text5);
+
+       /* Parse standard testfiles: */
+/*     dofile("../../tests/test1"); */
+/*     dofile("../../tests/test2"); */
+/*     dofile("../../tests/test3"); */
+/*     dofile("../../tests/test4"); */
+/*     dofile("../../tests/test5"); */
+
+       /* Now some samplecode for building objects concisely: */
+       create_objects();
+       
+       return 0;
+}
diff --git a/rtasn1/cjson/tests/test1 b/rtasn1/cjson/tests/test1
new file mode 100644 (file)
index 0000000..eacfbf5
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "glossary": {
+        "title": "example glossary",
+               "GlossDiv": {
+            "title": "S",
+                       "GlossList": {
+                "GlossEntry": {
+                    "ID": "SGML",
+                                       "SortAs": "SGML",
+                                       "GlossTerm": "Standard Generalized Markup Language",
+                                       "Acronym": "SGML",
+                                       "Abbrev": "ISO 8879:1986",
+                                       "GlossDef": {
+                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
+                                               "GlossSeeAlso": ["GML", "XML"]
+                    },
+                                       "GlossSee": "markup"
+                }
+            }
+        }
+    }
+}
diff --git a/rtasn1/cjson/tests/test2 b/rtasn1/cjson/tests/test2
new file mode 100644 (file)
index 0000000..5600991
--- /dev/null
@@ -0,0 +1,11 @@
+{"menu": {
+  "id": "file",
+  "value": "File",
+  "popup": {
+    "menuitem": [
+      {"value": "New", "onclick": "CreateNewDoc()"},
+      {"value": "Open", "onclick": "OpenDoc()"},
+      {"value": "Close", "onclick": "CloseDoc()"}
+    ]
+  }
+}}
diff --git a/rtasn1/cjson/tests/test3 b/rtasn1/cjson/tests/test3
new file mode 100644 (file)
index 0000000..5662b37
--- /dev/null
@@ -0,0 +1,26 @@
+{"widget": {
+    "debug": "on",
+    "window": {
+        "title": "Sample Konfabulator Widget",
+        "name": "main_window",
+        "width": 500,
+        "height": 500
+    },
+    "image": { 
+        "src": "Images/Sun.png",
+        "name": "sun1",
+        "hOffset": 250,
+        "vOffset": 250,
+        "alignment": "center"
+    },
+    "text": {
+        "data": "Click Here",
+        "size": 36,
+        "style": "bold",
+        "name": "text1",
+        "hOffset": 250,
+        "vOffset": 100,
+        "alignment": "center",
+        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+    }
+}}    
\ No newline at end of file
diff --git a/rtasn1/cjson/tests/test4 b/rtasn1/cjson/tests/test4
new file mode 100644 (file)
index 0000000..d540b57
--- /dev/null
@@ -0,0 +1,88 @@
+{"web-app": {
+  "servlet": [   
+    {
+      "servlet-name": "cofaxCDS",
+      "servlet-class": "org.cofax.cds.CDSServlet",
+      "init-param": {
+        "configGlossary:installationAt": "Philadelphia, PA",
+        "configGlossary:adminEmail": "ksm@pobox.com",
+        "configGlossary:poweredBy": "Cofax",
+        "configGlossary:poweredByIcon": "/images/cofax.gif",
+        "configGlossary:staticPath": "/content/static",
+        "templateProcessorClass": "org.cofax.WysiwygTemplate",
+        "templateLoaderClass": "org.cofax.FilesTemplateLoader",
+        "templatePath": "templates",
+        "templateOverridePath": "",
+        "defaultListTemplate": "listTemplate.htm",
+        "defaultFileTemplate": "articleTemplate.htm",
+        "useJSP": false,
+        "jspListTemplate": "listTemplate.jsp",
+        "jspFileTemplate": "articleTemplate.jsp",
+        "cachePackageTagsTrack": 200,
+        "cachePackageTagsStore": 200,
+        "cachePackageTagsRefresh": 60,
+        "cacheTemplatesTrack": 100,
+        "cacheTemplatesStore": 50,
+        "cacheTemplatesRefresh": 15,
+        "cachePagesTrack": 200,
+        "cachePagesStore": 100,
+        "cachePagesRefresh": 10,
+        "cachePagesDirtyRead": 10,
+        "searchEngineListTemplate": "forSearchEnginesList.htm",
+        "searchEngineFileTemplate": "forSearchEngines.htm",
+        "searchEngineRobotsDb": "WEB-INF/robots.db",
+        "useDataStore": true,
+        "dataStoreClass": "org.cofax.SqlDataStore",
+        "redirectionClass": "org.cofax.SqlRedirection",
+        "dataStoreName": "cofax",
+        "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+        "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
+        "dataStoreUser": "sa",
+        "dataStorePassword": "dataStoreTestQuery",
+        "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
+        "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
+        "dataStoreInitConns": 10,
+        "dataStoreMaxConns": 100,
+        "dataStoreConnUsageLimit": 100,
+        "dataStoreLogLevel": "debug",
+        "maxUrlLength": 500}},
+    {
+      "servlet-name": "cofaxEmail",
+      "servlet-class": "org.cofax.cds.EmailServlet",
+      "init-param": {
+      "mailHost": "mail1",
+      "mailHostOverride": "mail2"}},
+    {
+      "servlet-name": "cofaxAdmin",
+      "servlet-class": "org.cofax.cds.AdminServlet"},
+    {
+      "servlet-name": "fileServlet",
+      "servlet-class": "org.cofax.cds.FileServlet"},
+    {
+      "servlet-name": "cofaxTools",
+      "servlet-class": "org.cofax.cms.CofaxToolsServlet",
+      "init-param": {
+        "templatePath": "toolstemplates/",
+        "log": 1,
+        "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
+        "logMaxSize": "",
+        "dataLog": 1,
+        "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
+        "dataLogMaxSize": "",
+        "removePageCache": "/content/admin/remove?cache=pages&id=",
+        "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
+        "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
+        "lookInContext": 1,
+        "adminGroupID": 4,
+        "betaServer": true}}],
+  "servlet-mapping": {
+    "cofaxCDS": "/",
+    "cofaxEmail": "/cofaxutil/aemail/*",
+    "cofaxAdmin": "/admin/*",
+    "fileServlet": "/static/*",
+    "cofaxTools": "/tools/*"},
+  "taglib": {
+    "taglib-uri": "cofax.tld",
+    "taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
\ No newline at end of file
diff --git a/rtasn1/cjson/tests/test5 b/rtasn1/cjson/tests/test5
new file mode 100644 (file)
index 0000000..49980ca
--- /dev/null
@@ -0,0 +1,27 @@
+{"menu": {
+    "header": "SVG Viewer",
+    "items": [
+        {"id": "Open"},
+        {"id": "OpenNew", "label": "Open New"},
+        null,
+        {"id": "ZoomIn", "label": "Zoom In"},
+        {"id": "ZoomOut", "label": "Zoom Out"},
+        {"id": "OriginalView", "label": "Original View"},
+        null,
+        {"id": "Quality"},
+        {"id": "Pause"},
+        {"id": "Mute"},
+        null,
+        {"id": "Find", "label": "Find..."},
+        {"id": "FindAgain", "label": "Find Again"},
+        {"id": "Copy"},
+        {"id": "CopyAgain", "label": "Copy Again"},
+        {"id": "CopySVG", "label": "Copy SVG"},
+        {"id": "ViewSVG", "label": "View SVG"},
+        {"id": "ViewSource", "label": "View Source"},
+        {"id": "SaveAs", "label": "Save As"},
+        null,
+        {"id": "Help"},
+        {"id": "About", "label": "About Adobe CVG Viewer..."}
+    ]
+}}
diff --git a/rtasn1/cpp/CMakeLists.txt b/rtasn1/cpp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f892f9f
--- /dev/null
@@ -0,0 +1,21 @@
+
+ADD_LIBRARY(asn1cpp
+    prim_oid.cpp)
+
+#
+# Install stull
+#
+
+IF(APPLE)
+  INSTALL(TARGETS asn1cpp 
+    COMPONENT RuntimeLibraries
+    LIBRARY DESTINATION Smartasn1.app/Contents/lib/
+    ARCHIVE DESTINATION Smartasn1.app/Contents/lib/
+  )
+ELSE(APPLE)
+  INSTALL(TARGETS asn1cpp 
+    COMPONENT RuntimeLibraries
+    LIBRARY DESTINATION lib/
+    ARCHIVE DESTINATION lib/
+  )
+ENDIF(APPLE)
diff --git a/rtasn1/cpp/prim_GeneralizedTime.h b/rtasn1/cpp/prim_GeneralizedTime.h
new file mode 100644 (file)
index 0000000..ccb2c89
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef PRIM_GENERALIZEDTIME_H
+#define PRIM_GENERALIZEDTIME_H
+
+namespace ans1 {
+namespace prim {
+namespace types {
+
+
+class GeneralizedTime {
+  public:
+      inline GeneralizedTime(int len,const char *v) : m_len(len),m_(v) {};
+      inline GeneralizedTime(const GeneralizedTime &oid) {}
+      inline ~GeneralizedTime() {}
+
+      inline bool operator==(const GeneralizedTime &o) { return true;};
+
+  protected:
+    int         m_len;
+    const char  *m_;
+
+};
+
+}
+}
+}
+#endif
diff --git a/rtasn1/cpp/prim_UTCTime.h b/rtasn1/cpp/prim_UTCTime.h
new file mode 100644 (file)
index 0000000..ef40d61
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef PRIM_UTCTIME_H
+#define PRIM_UTCTIME_H
+
+namespace ans1 {
+namespace prim {
+namespace types {
+
+
+class UTCTime {
+  public:
+      inline UTCTime(int len,const char *v) : m_len(len),m_(v) {};
+      inline UTCTime(const UTCTime &oid) {}
+      inline ~UTCTime() {}
+
+      inline bool operator==(const UTCTime &o) {return true;};
+
+  protected:
+    int         m_len;
+    const char  *m_;
+
+};
+
+}
+}
+}
+#endif
+
diff --git a/rtasn1/cpp/prim_oid.cpp b/rtasn1/cpp/prim_oid.cpp
new file mode 100644 (file)
index 0000000..e913fc0
--- /dev/null
@@ -0,0 +1,215 @@
+
+#include <iostream>
+#include <vector>
+#include <assert.h>
+#include <string.h>
+#include "rtasn1/prim_types.h"
+#include "rtasn1/cpp/prim_oid.h"
+
+#define GEN_LOG_DEBUG
+
+#define MIN(a,b) (((a)< (b))?(a):(b))
+
+namespace asn1 {
+namespace prim {
+namespace types {
+
+/**
+ * Default constructor 
+ */
+ObjectIdentifier::ObjectIdentifier(long len,const char *buf) 
+    : m_len(len)
+{
+  memset(m_oid,0x00,MAX_OID_LEN); 
+  m_ = m_oid;
+  assert(len < MAX_OID_LEN);
+  memcpy(m_,buf,MIN(len,MAX_OID_LEN));
+}
+
+ObjectIdentifier::ObjectIdentifier(const char *v)
+{
+  memset(m_oid,0x00,MAX_OID_LEN); 
+  m_ = m_oid;
+  size_t len = strlen(v);
+  assert(len < MAX_OID_LEN);
+  memcpy(m_,v,MIN(len,MAX_OID_LEN));
+}
+
+// Compare
+bool ObjectIdentifier::operator ==(const ObjectIdentifier &o) const 
+{
+  return ( m_len == o.m_len ) && !strncmp(m_oid,o.m_oid,m_len);
+}
+// Copy constructor 
+ObjectIdentifier::ObjectIdentifier(const ObjectIdentifier &oid)
+{
+  if (oid.m_len > MAX_OID_LEN)
+  {
+    std::cerr<<"ObjectIdentifier::ObjectIdentifier MAX_OID_LEN exeeded "<<oid.m_len<<std::endl;
+  }
+  assert(oid.m_len < MAX_OID_LEN);
+  memset(m_oid,0x00,MAX_OID_LEN); 
+  m_ = m_oid;
+  m_len = oid.m_len;  
+  memcpy(m_oid,oid.m_oid,MIN(oid.m_len,MAX_OID_LEN));
+}
+
+// Build string from ... 3 {1,3,5} 
+ObjectIdentifier::ObjectIdentifier(long len,const long *arcs)
+{
+  from_arc(len,arcs);
+}
+
+
+// Copy operator
+ObjectIdentifier &ObjectIdentifier::operator =(const ObjectIdentifier &oid)
+{
+  assert(oid.m_len < MAX_OID_LEN);
+#if 0
+  std::cerr<<"ObjectIdentifier::=  len="<<oid.m_len<<std::endl;
+#endif
+  m_len = oid.m_len;  
+  m_ = m_oid;
+  memcpy(m_oid,oid.m_oid,MIN(oid.m_len,MAX_OID_LEN));
+  return *this;
+}
+
+/**
+ * This is only valid for OID where we use 7 bits for each octet.
+ */
+void ObjectIdentifier::encode_integer(long value)
+{
+  long integer = value;
+  long intsize = 4;
+  long mask       =   0x1FF <<23; // Shift 8 *3 - 1 ? 0xFF800000
+  while ( (((integer & mask) == 0) || ((integer & mask) == mask)) 
+          && (intsize > 1)) {
+      intsize--;
+      integer <<=8;
+  }
+  mask = (0x7f << ((intsize-1)*7));
+  long decal = (intsize -1)*7;
+  
+  while ((value & mask  ) != 0) 
+  {
+      long treat = ((value & mask)>>decal);
+      m_oid[m_len++] = (( treat   & 0x7F) |0x80 );
+      value<<=7;
+      intsize--;
+  }
+  if (intsize)
+    m_oid[m_len++] = 0;
+  m_oid[m_len -1 ] = m_oid[m_len - 1] & 0x7F;
+  //m_oid[m_len  ] = m_oid[m_len ] & 0x7F;
+}
+
+void 
+ObjectIdentifier::from_string(long len,const char *arcs)
+{
+  memset(m_oid,0x00,MAX_OID_LEN); 
+  m_len = len;  
+  assert(len < MAX_OID_LEN);
+  memcpy(m_oid,arcs,MIN(len,MAX_OID_LEN));
+}
+    
+void 
+ObjectIdentifier::from_arc(long len,const long *arcs)
+{
+  long * pos = &m_len; 
+  int first2 = 0;
+  *pos = 0;
+  assert(len < MAX_OID_LEN);
+  for ( int i = 0 ; i < len; i++)
+  {
+    long l = arcs[i];
+    if (i == 0)
+    {
+      first2 = 40 * arcs[i];
+    } else if (i == 1)
+    {
+      first2 = first2 + arcs[i];
+      m_oid[*pos] = first2; 
+      (*pos)++;
+    } else
+    {
+      encode_integer(l);
+    }
+
+  }
+  assert(m_len < MAX_OID_LEN);
+}
+
+void 
+ObjectIdentifier::to_arc(array_type &a)
+{
+  char *buf = const_cast<char *>(m_oid);
+  if (m_len)
+  {
+    for (int i = 0 ; i < m_len ; i++)
+    {
+      if (i == 0 )
+      {
+        long byte = buf[i] / 40;
+        a.push_back(byte);
+        byte = buf[i] % 40;
+        a.push_back(byte);
+
+      } else if (buf[i] & 0x80 ) {
+        long res = 0;
+        while ((buf[i] & 0x80))
+        {
+          res = (res<<7) | (buf[i++] &0x7F);
+        }
+        res = (res<<7) | (buf[i] &0x7F);
+       a.push_back(res);
+      } else
+      {
+        long l = buf[i];
+        a.push_back(l);
+      }
+    }
+  } 
+}
+
+// Compare
+std::ostream & operator <<(std::ostream &os,const ObjectIdentifier &oid )
+{
+  char *buf = const_cast<char *>(oid.m_oid);
+
+  if (oid.m_len)
+  {
+    for (int i = 0 ; (i < oid.m_len) && (i<MAX_OID_LEN); i++)
+    {
+      if (i == 0 )
+      {
+        long byte = buf[i] / 40;
+        //this->m_.push_back((T)byte);
+        os<<byte;
+        byte = buf[i] % 40;
+        os<<"."<<byte;
+
+      } else if (buf[i] & 0x80 ) {
+        long res = 0;
+        while ((buf[i] & 0x80))
+        {
+          res = (res<<7) | (buf[i++] &0x7F);
+        }
+        res = (res<<7) | (buf[i] &0x7F);
+        os<<"."<<res;
+      } else
+      {
+        long l = buf[i];   
+        os<<"."<<l;
+      }
+    }
+  } else
+  {
+    os<<"{}"; 
+  }
+  return os;
+}
+
+//END
+}
+}
+}
diff --git a/rtasn1/cpp/prim_oid.h b/rtasn1/cpp/prim_oid.h
new file mode 100644 (file)
index 0000000..3504a73
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef PRIM_OID_H
+#define PRIM_OID_H
+
+#include <vector>
+
+namespace asn1 {
+namespace prim {
+namespace types {
+#define MAX_OID_LEN 48
+/**
+ * ObjectIdentifier type 
+ *  Only store the encoded form.
+ *  Decode the encoded form from display
+ */ 
+class ObjectIdentifier : public asn1::prim::types::prim< char *>
+{
+  public:
+    typedef std::vector<long>     array_type;
+    typedef array_type::iterator  iterator;
+
+    // Build from encoded ObjectIdentidier
+    ObjectIdentifier(long len=0,const char *v=NULL);
+    // Build from encoded ObjectIdentidier
+    ObjectIdentifier(const char *v);
+
+    // Build string from ... 3 {1,3,5} 
+    ObjectIdentifier(long len,const long *arcs);
+      
+    ObjectIdentifier(const ObjectIdentifier &oid);
+  
+    inline ~ObjectIdentifier() {}
+    // Build oid string from arcs
+    void from_arc(long len,const long *arcs);
+    //
+    void from_string(long len,const char *arcs);
+
+    void to_arc(array_type &result);
+      // Copy operator
+    ObjectIdentifier &operator=(const ObjectIdentifier &oid);
+    // Compare
+    bool operator==(const ObjectIdentifier &oid) const;
+    
+    inline long get_oid_length() const { return m_len;}
+    friend std::ostream & operator <<(std::ostream &os,const ObjectIdentifier &oid );
+  protected:
+    void encode_integer(long l);
+  protected:
+    char        m_oid[MAX_OID_LEN] ; // Encoded Oid 
+    long        m_len;
+};
+
+std::ostream & operator <<(std::ostream &os,ObjectIdentifier &oid );
+
+}
+}
+}
+#endif
diff --git a/rtasn1/json_token.h.inc b/rtasn1/json_token.h.inc
new file mode 100644 (file)
index 0000000..a648a2f
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef JER_TOKEN
+#define JER_TOKEN(id,str)
+#endif
+JER_TOKEN(bool,"bool")
+JER_TOKEN(colon,"colon")
+JER_TOKEN(comma,"comma")
+JER_TOKEN(eof,"eof")
+JER_TOKEN(error,"error")
+JER_TOKEN(left_brace,"lbrace")
+JER_TOKEN(left_bracket,"lbracket")
+JER_TOKEN(null,"null")
+JER_TOKEN(integer,"integer")
+JER_TOKEN(double,"double")
+JER_TOKEN(right_brace,"rbrace")
+JER_TOKEN(right_bracket,"rbracket")
+JER_TOKEN(string,"string")
+JER_TOKEN(string_with_escapes,"string_with_escapes")
+JER_TOKEN(comment,"comment")
+#undef JER_TOKEN
diff --git a/rtasn1/prim_types.cpp b/rtasn1/prim_types.cpp
new file mode 100644 (file)
index 0000000..bd37f97
--- /dev/null
@@ -0,0 +1,135 @@
+#include <iostream>
+#include <string>
+#include <stdio.h>
+#include "rtasn1/asn1_config.h"
+#include "prim_types.h"
+
+#if 0
+#include "rtasn1/cpp/prim_oid.h"
+#include "rtasn1/cpp/prim_UTCTime.h"
+#include "rtasn1/cpp/prim_GeneralizedTime.h"
+#endif
+
+//#define NOTEMPLATE
+namespace asn1 {
+namespace prim {
+namespace types {
+
+template <typename C> struct prim;
+
+template <>
+std::ostream &operator << <bool>(std::ostream &os,const prim<bool> &_p)
+{
+  bool b = _p.get_value();
+  os<<"bool("<<std::hex<<b<<std::dec<<") ";
+  return os;
+}
+
+
+
+template <>
+std::ostream &operator << <std::string>(std::ostream &os,const prim<std::string> &_p)
+{
+      os<<" string (";
+
+      for (int i = 0 ; i < _p.m_.size(); i++) 
+      {
+         char tmp[10];
+        sprintf(tmp,"%02x",(unsigned char )_p.m_[i]);
+        os<<tmp<<" ";
+      }
+
+            os<<std::dec<<") ";
+      return os;
+}
+
+std::ostream &operator << (std::ostream &os,const String &_p)
+{
+      os<<(const prim<std::string> &)(_p);
+      return os;
+}
+
+
+
+//
+#ifndef HAVE_STDINT_H
+template <> 
+std::ostream & operator << <long>(std::ostream &os,const arithm_prim<long> &_p )
+{
+      os<<" long("<<_p.m_<<") ";
+      return os;
+};
+#endif
+template <> 
+std::ostream & operator << <unsigned char>(std::ostream &os,const arithm_prim<unsigned char> &_p )
+{
+      os<<" UI8("<<static_cast<int>(_p.m_)<<") ";
+      return os;
+};
+
+template <> 
+std::ostream & operator << <unsigned short>(std::ostream &os,const arithm_prim<unsigned short> &_p )
+{
+      os<<" UI16("<<_p.m_<<") ";
+      return os;
+};
+
+#ifdef HAVE_STDINT_H
+template <> 
+std::ostream & operator << <uint32_t>(std::ostream &os,const arithm_prim<uint32_t> &_p )
+#else
+template <> 
+std::ostream & operator << <unsigned int>(std::ostream &os,const arithm_prim<unsigned int> &_p )
+#endif
+{
+      os<<" UI32("<<_p.m_<<") ";
+      return os;
+};
+
+#ifdef HAVE_STDINT_H
+/* int64_t is long ??? */
+template <> 
+std::ostream & operator << <int64_t>(std::ostream &os,const arithm_prim<int64_t> &_p )
+#else
+template <> 
+std::ostream & operator << <long long>(std::ostream &os,const arithm_prim<long long> &_p )
+#endif
+{
+      os<<" I64("<<_p.m_<<") ";
+      return os;
+};
+
+
+
+#ifdef HAVE_STDINT_H
+template <> 
+std::ostream & operator << <uint64_t>(std::ostream &os,const arithm_prim<uint64_t> &_p )
+#else
+template <> 
+std::ostream & operator << <unsigned long long>(std::ostream &os,const arithm_prim<unsigned long long> &_p )
+#endif
+{
+      os<<" UI64("<<_p.m_<<") ";
+      return os;
+};
+
+
+
+template <> 
+std::ostream & operator << <double>(std::ostream &os,const arithm_prim<double> &_p )
+{
+      os<<" <dbl("<<_p.m_<<") ";
+      return os;
+};
+
+
+std::ostream & operator <<(std::ostream &os,const asn1::prim::types::UTCTime  &_p )
+{
+    std::string str = _p.toString();
+      os<<"Time ("<<str<<") ";
+      return os;
+}
+
+}
+}
+}
diff --git a/rtasn1/prim_types.h b/rtasn1/prim_types.h
new file mode 100644 (file)
index 0000000..97e81b8
--- /dev/null
@@ -0,0 +1,449 @@
+#ifndef ASN1_PTYPES_H__
+#define ASN1_PTYPES_H__
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include "rtasn1/cpp/prim_UTCTime.h"
+#include "rtasn1/cpp/prim_GeneralizedTime.h"
+
+//#define NOTEMPLATE
+namespace asn1 {
+namespace prim {
+namespace types {
+
+template <typename C> struct prim;
+
+template <typename C>
+std::ostream &operator <<(std::ostream &os,const prim<C> &t);
+
+
+/**
+ *
+ */
+template <typename C>
+struct prim {
+
+  protected:
+  public:
+    typedef C         prim_type;
+    typedef C*        prim_pointer;
+    typedef C&        prim_type_reference;
+    typedef const C & prim_type_const_reference;
+
+    inline prim() : m_() {};
+    inline prim(const C &c) : m_(c) {}
+    inline prim(const prim<C> &v) : m_(v.m_) {};
+    inline ~prim() {};
+    // Copy assignement
+    inline prim<C> &operator =(const prim<C> &v)  {m_ = v.m_; return *this;};
+    inline prim<C> &operator=(const C c)  { m_ = c; return *this;}
+    //
+    inline bool operator==(const prim<C> &c)  const { return m_ == c.m_;}
+    //
+    inline bool operator!=(const prim<C> &c)  { return ! operator==(c);}
+    inline bool operator==(const C &c)  const { return m_ == c;}
+    inline bool operator!=(const C &c)  const { return m_ != c;}
+    //inline operator C() const {return m_;}
+    //template <typename X = C>
+    friend std::ostream & operator << <>(std::ostream &os,const prim<C> &_p );
+    // Better than cast
+    prim_type_reference       get_value()       { return m_;} ;
+    prim_type_const_reference get_value() const { return m_;} ;
+protected:
+    prim_type m_;
+};
+
+  
+
+typedef prim<bool>              Boolean;
+//typedef prim<std::string>       String;
+
+/**
+ *
+ */ 
+class String : public prim<std::string>
+{
+  public:
+
+    String() {};
+    String(const String &t): prim<std::string>::prim(t.m_) {};
+    String(const std::string &t): prim<std::string>::prim(t) {};
+    String(const char *t): prim<std::string>::prim(t) {};
+    ~String() {};
+    
+    inline void operator=(const std::string &c)  { m_ = c;}
+    
+    inline bool operator==(const String &c)  const { return ! m_.compare(c.m_) ;}
+  
+    inline const std::string toString(void) const {return this->m_;};
+    friend std::ostream & operator <<(std::ostream &os,const String &_p );
+
+    size_t size () const { return m_.size() ; }
+
+    const char *c_str() const { return m_.c_str() ; }
+};
+
+
+// Forward declation for array
+template <typename C> struct array ;
+template <typename C>
+std::ostream &operator <<(std::ostream &os,const array<C> &t);
+
+/**
+ *
+ */
+template <typename C>
+struct array {
+  public:
+    typedef C&                                       reference;
+    typedef const C&                                 const_reference;
+    typedef std::vector<C>                           type;
+    typedef typename std::vector<C>::iterator        iterator;
+    typedef typename std::vector<C>::const_iterator  const_iterator;
+
+    inline array(size_t sz = 0) :m_(sz)
+    {
+      //std::cout<<" build array "<<std::endl;
+    };
+    inline array(const array<C> &v) : m_(v.m_)
+    {
+      std::cout<<"array::array copy"<<std::endl;
+    };
+    inline array(const type &v) : m_(v)
+    {
+      std::cout<<"array::array(std::vector<C> &)"<<std::endl;
+    };
+    inline array(const C c)
+    {
+        std::cout<<" from c "<<std::endl;
+        m_.push_back(c);
+    }
+    inline array<C> &operator =(const array<C> &v)  {m_ = v.m_;};
+    inline ~array() {};
+    inline iterator begin() {return m_.begin();};
+    inline const_iterator begin() const {return m_.begin();};
+    inline iterator end() {return m_.end();};
+    inline size_t size() const {return m_.size();};
+    //inline void operator=(const C c)  { m_ = c;}
+    inline reference operator[](int c)  { 
+        if (m_.size() == 0)
+        { 
+            m_.resize(c+1) ;
+            m_[c] = 0;
+        } else if (m_.size() <= c)
+        {
+            m_.resize(c+1);
+            m_[c] = 0;
+        }
+        return m_[c];
+    }
+    inline const_reference operator[](int c) const  { return m_[c];}
+//    inline bool operator==(const prim<C> &c)  { m_ == c;}
+    inline void operator=(const C &c)  { m_[0] = c;}
+    inline void operator=(const prim<C> &c)  { m_ = c.m_;}
+    inline operator type () const {return m_;}
+  
+    friend std::ostream & operator <<(std::ostream &os,const array<C> &_p )
+  {
+      typename std::vector<C>::const_iterator iter = _p.begin();
+      os<<" array [";os<<_p.size()<<"] ";
+      os<<std::setfill('0');
+      os<<std::setw(2);
+#if 1
+      for (; iter < _p.m_.end() ; ++iter) {
+          if (iter != _p.begin() )
+              os<<":";
+        os<<std::hex<<std::setfill('0')<<std::setw(2)<<(int)(*iter);
+      }
+      os<<std::dec;
+#endif
+      os<<std::setfill(' ');
+      return os;
+  };
+
+  protected:
+    type m_;
+};
+
+/**
+ *
+ */ 
+class UTCTime : public prim<std::string>
+{
+  public:
+
+    UTCTime() {};
+    UTCTime(const UTCTime &t): prim<std::string>::prim(t.m_) {};
+    UTCTime(const std::string &t): prim<std::string>::prim(t) {};
+    UTCTime(const char *t): prim<std::string>::prim(t) {};
+    ~UTCTime() {};
+    
+    inline void operator=(const std::string &c)  { m_ = c;}
+  
+    inline const std::string toString(void) const {return this->m_;};
+    friend std::ostream & operator <<(std::ostream &os,const UTCTime &_p );
+
+
+};
+
+// Forward declaration for arith_prim streaming 
+template <typename C> class arithm_prim;
+
+template <typename C>
+std::ostream &operator <<(std::ostream &os,const arithm_prim<C> &s);
+
+/**
+ *
+ */
+template <typename C>
+class arithm_prim : public prim<C>
+{
+  public:
+    inline arithm_prim() {};
+    inline arithm_prim(const arithm_prim<C> &v) : prim<C>(v) {};
+    inline ~arithm_prim() {};
+    inline arithm_prim(const C c) : prim<C>(c) {};
+    
+    inline void operator = (const C c) {prim<C>::operator =(c);}
+    // Available in prim<C>
+    // inline bool operator ==(const arithm_prim<C> &c) { return  this->m_ == (C)c.m_;};
+    // inline bool operator ==(const C c) { return prim<C>::operator ==(c);};
+    inline C operator +=(const C v) {return this->m_+=v;}
+    inline C operator -=(const C v) {return this->m_-=v;}
+    inline C operator *=(const C v) {return this->m_*=v;}
+    inline C operator /=(const C v) {return this->m_/=v;}
+#if 1
+    inline arithm_prim<C> &operator +=(const arithm_prim<C> &v) 
+    { prim<C>::m_ += v.m_; return *this; }
+    inline arithm_prim<C> &operator -=(const arithm_prim<C> &v) 
+    { prim<C>::m_ -= v.m_; return *this; }
+    inline arithm_prim<C> &operator *=(const arithm_prim<C> &v) 
+    { prim<C>::m_ *= v.m_; return *this; }
+    inline arithm_prim<C> &operator /=(const arithm_prim<C> &v) 
+    { prim<C>::m_ /= v.m_; return *this; }
+#endif
+
+    //inline C operator --(const C v) {return --this->m_;}
+    //inline C operator ++(const C v) {return ++this->m_;}
+    //
+    friend std::ostream &operator << <>(std::ostream &os,const arithm_prim<C> &_p);
+};
+
+/**
+ * Be aware the that what's below depends on the processor
+ * use it carefully.
+ * If stdint is available, I should use
+ *
+ */
+#ifdef HAVE_STDINT_H
+
+typedef arithm_prim<uint8_t>     UInt8;
+typedef arithm_prim<uint16_t>    UInt16;
+typedef arithm_prim<uint32_t>    UInt32;
+typedef arithm_prim<uint64_t>    UInt64;
+
+typedef arithm_prim<int8_t>      Int8;
+typedef arithm_prim<int16_t>     Int16;
+typedef arithm_prim<int32_t>     Int32;
+typedef arithm_prim<int64_t>     Int64;
+
+typedef arithm_prim<int64_t>     Integer;
+#else
+typedef arithm_prim<long>                 Integer;
+typedef arithm_prim<unsigned char>        UInt8;
+typedef arithm_prim<unsigned short>       UInt16;
+typedef arithm_prim<unsigned int>         UInt32;
+typedef arithm_prim<unsigned long long>   UInt64;
+
+typedef arithm_prim<char>        Int8;
+typedef arithm_prim<short>       Int16;
+typedef arithm_prim<int>         Int32;
+typedef arithm_prim<long long>   Int64;
+#endif
+
+typedef arithm_prim<double>     Real;
+
+
+std::ostream & operator <<(std::ostream &os,const asn1::prim::types::UTCTime  &_p );
+/**
+ * BIT STRING ....
+ *  -> I use a template in order to be able to specify
+ *  several size of bit strings (8, 16 , 32, and above)
+ */ 
+class bs_prim : public prim<std::vector<unsigned char> >
+{
+  public:
+    typedef unsigned char                            C;  
+
+    typedef std::vector<C>         prim_type;
+    typedef prim_type *            prim_pointer;
+    typedef prim_type &            prim_type_reference;
+    typedef const  prim_type &     prim_type_const_reference;
+    /* There is an inconsitency */
+    typedef C*                                       pointer;
+    typedef C&                                       reference;
+    typedef const C&                                 const_reference;
+    typedef std::vector<C>                           type;
+    typedef type &                                   type_reference;  
+    typedef std::vector<C>::iterator                 iterator;
+    typedef std::vector<C> ::const_iterator          const_iterator;
+
+    bs_prim(size_t sz = 0) 
+      : prim<std::vector<unsigned char> >()  
+    {
+    }
+    bs_prim(const prim_type &c) 
+      : prim<std::vector<unsigned char> >(c)  
+    {
+    }
+    
+    bs_prim(const bs_prim &_bs) 
+      : prim<std::vector<unsigned char> >(_bs.get_value())
+        , m_NbBits(_bs.m_NbBits)
+    {
+    }
+
+    ~bs_prim()
+    {
+    }
+#if 0
+    void set_data(const char *)
+    {
+    }
+    
+    void set_data(const std::string &_v)
+    {
+      m_NbBits = _v.size() << 3;  
+    }
+#endif
+    //
+    inline size_t size() const 
+    {
+        return this->m_.size();
+    }
+    //
+    void set_nb_bits( size_t _nb)
+    {
+      m_NbBits = _nb; 
+      this->m_.resize(_nb/8+1);
+    };
+
+    //
+    inline size_t get_nb_bits() const 
+    {
+      return m_NbBits;  
+    };
+
+    //
+    void set_bit(int _bit)
+    {
+      int a,b;
+      unsigned char val = 1;
+      a = _bit / 8;
+      b = _bit % 8;
+      val = 1<<b;
+      this->m_[a] = this->m_[a] | val;
+    };
+    
+    //
+    void clear_bit(int _bit)
+    {
+      int a,b;
+      unsigned char val = 1;
+      a = _bit / 8;
+      b = _bit % 8;
+      val = 1<<b;
+      this->m_[a] = this->m_[a] & ~val;
+    };
+
+    //
+    inline bool get_bit(int _bit) const
+    {
+      int a,b;
+      unsigned char val = 1;
+      a = _bit / 8;
+      b = _bit % 8;
+      val = 1<<b;
+      return (this->m_[a] & val)>0;
+    };
+    
+    //
+    const_reference operator[](size_t c) const
+    { 
+      return this->m_[c];
+    }
+    //
+    reference operator[](size_t c)
+    { 
+      if (this->m_.size() <= c)
+      {
+        this->m_.resize(c+1);
+        this->m_[c] = 0;
+        m_NbBits = c << 3;
+      }
+      return this->m_[c];
+    }
+
+    //
+    iterator begin() 
+    { return this->m_.begin() ; }
+    //
+    const_iterator begin() const
+    { return this->m_.begin() ; }
+    //
+    iterator end() 
+    { return this->m_.end() ; }
+    //
+    const_iterator end() const
+    { return this->m_.end() ; }
+
+
+    friend std::ostream & operator <<(std::ostream &os,const bs_prim &_p )
+    {
+      size_t count = 0;
+      //const_iterator iter = _p.end();
+      const_iterator iter = _p.begin(); iter+=_p.m_NbBits/8 - 1 ;
+      os<<" bs[";os<<_p.size()<<"] ("<<_p.m_NbBits<<")";
+      //os<<std::setfill('0');
+      //os<<std::setw(2);
+      if (! _p.size())
+      {
+        return os;
+      }
+      std::streamsize indent = os.precision() + 2;
+      os<<std::endl;
+      os<<std::setfill(' ');
+      os<<std::setw(indent+2);
+      for (; iter >= _p.m_.begin() ; --iter) {
+          if (iter != _p.end() )
+              os<<":";
+        os<<std::hex<<std::setfill('0')<<std::setw(2)<<(int)(*iter);
+       if ( ! (++count % 16))
+        {
+         os<<std::endl;
+          os<<std::setfill(' ');
+         os<<std::setw(indent+2);
+       }
+      }
+      os<<std::dec;
+      os<<std::setfill(' ');
+      os<<"\n"<<std::setw(indent)<<std::setprecision(indent-2);
+      return os;
+    };
+
+  protected:
+    size_t m_NbBits;
+};
+
+typedef bs_prim               BitString;
+
+
+}
+}
+}
+
+#include "rtasn1/cpp/prim_oid.h"
+
+
+#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d6be538
--- /dev/null
@@ -0,0 +1,136 @@
+PROJECT(test-lib)
+
+ADD_DEFINITIONS(-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER)
+# WIN32 no CPPUNIT AVAILABLE
+IF(NOT WIN32)
+       
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${rules_SOURCE_DIR}/")
+
+INCLUDE(${rules_SOURCE_DIR}/utils.cmake)
+
+#FIND_LIBRARY(CPPUNIT_LIBRARY cppunit PATHS "/usr/local/lib:/usr/lib:/Users/aeb/External/lib/:/Users/aeb/External/bin/")
+FIND_LIBRARY(DL_LIB ltdl "/lib:/usr/local/lib:/usr/lib")
+
+FIND_PACKAGE(CPPUNIT REQUIRED)
+INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIRS})
+
+#FIND_PACKAGE(CppUnit PATHS  "/usr/local/lib:/usr/lib:/Users/aeb/External/lib/:/Users/aeb/External/bin/")
+#FIND_PACKAGE(CppUnit)
+
+IF(CPPUNIT_FOUND)
+  MESSAGE("FOUND CCPUNIT")
+  INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIRS})
+ELSE(CPPUNIT_FOUND)
+  INCLUDE_DIRECTORIES("/Users/aeb/External/include")
+ENDIF(CPPUNIT_FOUND)
+#EXEC_PROGRAM(cat ARGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt OUTPUT_VARIABLE
+#    CSTAMODULES)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/modules.txt TESTMODULES)
+
+
+
+
+MACRO(TESTCASE)
+  PARSE_ARGUMENTS(THIS_TC
+     "NAME;SOURCE"
+     "DEBUG"
+     ${ARGN}
+     )
+  STRING(REGEX REPLACE ".cpp" "_codec.cpp" CODEC ${THIS_TC_SOURCE})
+  STRING(REGEX REPLACE "-" "_" CODEC ${CODEC})
+  ADD_EXECUTABLE(${THIS_TC_NAME}
+           UNIT-${THIS_TC_SOURCE}
+      ${CMAKE_CURRENT_BINARY_DIR}/${THIS_TC_SOURCE}
+      ${CMAKE_CURRENT_BINARY_DIR}/${CODEC}
+       main_test.cpp
+  )
+  TARGET_LINK_LIBRARIES(${THIS_TC_NAME} asn1)
+  TARGET_LINK_LIBRARIES(${THIS_TC_NAME} ${CPPUNIT_LIBRARY} )
+  IF(NOT ${DL_LIB} STREQUAL DL_LIB-NOTFOUND)
+    MESSAGE("DL LIB contains: ${DL_LIB} and var ")
+    TARGET_LINK_LIBRARIES(${THIS_TC_NAME} ${DL_LIB} )
+  ENDIF(NOT ${DL_LIB} STREQUAL DL_LIB-NOTFOUND)
+ENDMACRO(TESTCASE)
+
+# Also add codec codec now
+FOREACH(ITEM ${TESTMODULES})
+ STRING(REGEX REPLACE "-" "_" HITEM ${ITEM})
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}.h GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${HITEM}_codec.cpp GENERATED)
+ SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp GENERATED)
+ SET(TESTSRC ${TESTSRC} ${CMAKE_CURRENT_BINARY_DIR}/${ITEM}.cpp)
+ SET(TESTSRC ${TESTSRC} ${CMAKE_CURRENT_BINARY_DIR}/${HITEM}_codec.cpp)
+ # SET(UNITTESTSRC ${UNITTESTSRC} ${CMAKE_CURRENT_SOURCE_DIR}/UNIT-${ITEM}.cpp)
+ SET(TESTHDR ${TESTHDR} ${HITEM}.h)
+ENDFOREACH(ITEM)
+
+#
+# Start OPTIONAL has SHARED POINTER
+#
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/TEST-basic-types-optional.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/UNIT-TEST-basic-types-optional.cpp COMPILE_FLAGS "-DASN1_ATTRIBUTE_OPTIONAL_AS_SHARED_POINTER")
+
+FILE(GLOB UNITESTSRC ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
+MESSAGE("GLOBAL FILES: ${UNITESTSRC}")
+SET_DIRECTORY_PROPERTIES(PROPERTIES 
+    ADDITIONAL_MAKE_CLEAN_FILES  "${TESTSRC} ${TESTHDR}"
+    )
+
+
+# ${CMAKE_CURRENT_SOURCE_DIR}/../../../data-models/asn1/Remote-Operations-Information-Objects.asn1
+#
+#
+#
+#
+ADD_CUSTOM_COMMAND(
+    OUTPUT ${TESTSRC}
+    COMMAND cat
+    ${CMAKE_CURRENT_SOURCE_DIR}/source.asn1
+    ARGS | ${CMAKE_CURRENT_BINARY_DIR}/../asn1p -c ON -e ber  -C true
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../asn1p
+    COMMENT "Build test .h and .cpp"
+    )
+
+LIST(REMOVE_ITEM UNITESTSRC ${CMAKE_CURRENT_SOURCE_DIR}/main_asn1_type_sizes.cpp)
+
+ADD_EXECUTABLE(tests
+       #      UNIT-TEST-ber-primary-types.cpp
+      ${TESTSRC}
+      ${UNITESTSRC}
+      #      main_test.cpp
+    )
+# Size checks
+ADD_EXECUTABLE(asn1p_type_sizes
+    main_asn1_type_sizes.cpp
+)
+
+TARGET_LINK_LIBRARIES(asn1p_type_sizes asn1)
+
+TESTCASE(NAME test-choice SOURCE TEST-basic-types-choice.cpp)
+TESTCASE(NAME test-implicit SOURCE TEST-basic-types-implicit.cpp)
+TESTCASE(NAME test-bt SOURCE TEST-basic-types.cpp)
+TESTCASE(NAME test-explicit SOURCE TEST-basic-types-explicit.cpp)
+TESTCASE(NAME test-tagged SOURCE TEST-basic-types-tagged.cpp)
+TESTCASE(NAME test-private-choice SOURCE TEST-private-types-choice.cpp)
+#ADD_EXECUTABLE(tests-choice
+#          UNIT-TEST-basic-types-choice.cpp
+#      ${CMAKE_CURRENT_BINARY_DIR}/TEST-basic-types-choice.cpp
+#       main_test.cpp
+#    )
+
+TARGET_LINK_LIBRARIES(tests asn1)
+ADD_DEPENDENCIES(tests ${TESTSRC})
+
+TARGET_LINK_LIBRARIES(tests ${CPPUNIT_LIBRARY} )
+IF(NOT ${DL_LIB} STREQUAL DL_LIB-NOTFOUND)
+MESSAGE("DL LIB contains: ${DL_LIB} and var ")
+TARGET_LINK_LIBRARIES(tests ${DL_LIB} )
+ENDIF(NOT ${DL_LIB} STREQUAL DL_LIB-NOTFOUND)
+
+
+ENDIF(NOT WIN32)
diff --git a/tests/UNIT-TEST-basic-types-choice.cpp b/tests/UNIT-TEST-basic-types-choice.cpp
new file mode 100644 (file)
index 0000000..6bfaade
--- /dev/null
@@ -0,0 +1,324 @@
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-choice.h"
+#include "TEST_basic_types_choice.h"
+
+using namespace asn1;
+using namespace TEST_basic_types_choice;
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_choice);
+
+
+void TC_TEST_basic_types_choice::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice_device()
+{
+  TEST_Choice c( TEST_Choice::typeof_device );
+  c.get_device() = 3; 
+  c.encode(m_ctx);
+  
+  const unsigned char seq[] = {0x02,0x01,0x03};
+  int result = memcmp(m_ctx.buffer(),seq,3);
+  m_ctx.reset();
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice_name()
+{
+  TEST_Choice c( TEST_Choice::typeof_name ,asn1::tag(asn1::types::UNIVERSAL,22));
+  c.get_name() = "Jones";
+  c.encode(m_ctx);
+  
+  const unsigned char seq[] = {0x16,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  CppUnit::Message message(std::string("Failed encode name Jones"));
+  int result = memcmp(m_ctx.buffer(),seq,7);
+  m_ctx.reset();
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice_b1()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice c( TEST_Choice::typeof_b1 ,asn1::tag(asn1::types::UNIVERSAL,1));
+  c.get_b1() = false;
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  
+  const unsigned char seq[] = {0x01,0x01,0x00};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice_ip4()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice c( TEST_Choice::typeof_ip4 ,asn1::tag(asn1::types::UNIVERSAL,16));
+  
+  c.get_ip4().address = asn1::prim::types::String("\x0A\x03\x10\x21");
+  c.get_ip4().portNumber.get() = INTEGER(asn1::prim::types::Integer(2));
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  //10 09 04 04 0a 03 10 21 02 01 02
+  //30 08 04 0a 03 10 21 02 01 02 
+  const unsigned char seq[] = {0x30,0x09,0x04,0x04,0x0A,0x03,0X10,0x21,0x02,0x1,0x02};
+  int result = memcmp(ctx.buffer(),seq,11);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_deviceId()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_device ,asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+  c.get_device() = 9;
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x80,0x01,0x09};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_i2()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_i2,asn1::tag(asn1::types::CONTEXT_SPECIFIC,1) );
+  c.get_i2() = 16;
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x81,0x01,0x10};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_b1()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_b1 , asn1::tag(asn1::types::CONTEXT_SPECIFIC,2));
+  c.get_b1() = true;
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x82,0x01,0xFF};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_bs1()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_bs1,asn1::tag(asn1::types::CONTEXT_SPECIFIC,3) );
+  c.get_bs1()[0] = 0x02;
+  c.get_bs1().set_nb_bits(2);
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x83,0x02,0x06,0x80};
+  const unsigned char seq1[] = {0x83,0x07,0x04,0x0a,0x3B,0x5F,0x29,0x1c,0xd0};
+  int result = memcmp(ctx.buffer(),seq,4);
+  ctx.reset();
+  CPPUNIT_ASSERT(result==0);
+  c.get_bs1()[0] = 0xcd;
+  c.get_bs1()[1] = 0x91;
+  c.get_bs1()[2] = 0xf2;
+  c.get_bs1()[3] = 0xB5;
+  c.get_bs1()[4] = 0xA3;
+  c.get_bs1()[5] = 0x0;
+  c.get_bs1().set_nb_bits(44);
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  result = memcmp(ctx.buffer(),seq1,9);
+  CPPUNIT_ASSERT(result==0);
+
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_os1()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_os1, asn1::tag(asn1::types::CONTEXT_SPECIFIC,4) );
+  
+  c.get_os1() = asn1::prim::types::String("1");
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x84,0x01,0x31};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_Choice1_nul()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice1 c( TEST_Choice1::typeof_nul , asn1::tag(asn1::types::CONTEXT_SPECIFIC,5));
+  CPPUNIT_ASSERT(c.check_create());
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  const unsigned char seq[] = {0x85,0x00,0x0};
+  int result = memcmp(ctx.buffer(),seq,2);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_ChoiceChoiceA()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x40,0x01,0x0b};
+  //ChoiceChoice c(ChoiceChoice::typeof_choicea,  asn1::tag(asn1::types::APPLICATION,0) );
+  ChoiceChoice c(ChoiceChoice::typeof_choicea );
+  //ChoiceChoice c(asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+  c.get_choicea().get_i() = 11;
+  c.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::encode_TEST_ChoiceChoiceB()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x81,0x01,0x0a};
+  ChoiceChoice c(asn1::tag(asn1::types::CONTEXT_SPECIFIC,1));
+  c.get_choiceb().get_ib() = 10;
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+//decode
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice_device()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice c;
+  const unsigned char seq[] = {0x02,0x01,0x07};
+  //c.get_device() = 3;
+  memcpy(ctx.buffer(),seq,3);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice::typeof_device);
+  CPPUNIT_ASSERT(c.get_device()== 7);
+}
+void TC_TEST_basic_types_choice::decode_TEST_Choice_name()
+{
+  asn1::streams::ber ctx;
+  TEST_Choice c;
+  const unsigned char seq[] = {0x16,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  
+//  asn1::prim::types::String s("Jones");
+  
+  memcpy(ctx.buffer(),seq,7);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice::typeof_name);
+  //CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_deviceId()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x80,0x01,0x0D};
+  TEST_Choice1 c;
+  
+  memcpy(ctx.buffer(),seq,3);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_device()==13);
+  CPPUNIT_ASSERT(5==5);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_i2()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x81,0x01,0x0D};
+  //TEST_Choice1 c( TEST_Choice1::typeof_i2 );
+  TEST_Choice1 c( TEST_Choice1::typeof_i2,asn1::tag(asn1::types::CONTEXT_SPECIFIC,1) );
+  c.get_i2() = 14;
+  memcpy(ctx.buffer(),seq,3);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_i2()==13);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_b1()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x82,0x01,0xFF};
+  TEST_Choice1 c( TEST_Choice1::typeof_i2,asn1::tag(asn1::types::CONTEXT_SPECIFIC,1) );
+  c.get_i2() = 14;
+  memcpy(ctx.buffer(),seq,3);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice1::typeof_b1);
+  CPPUNIT_ASSERT(c.get_b1() == true);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_bs1()
+{
+  asn1::streams::ber ctx;
+  //const unsigned char seq[] = {0x83,0x02,0x00,0x0D};
+  const unsigned char seq[] = {0x83,0x07,0x04,0x0a,0x3B,0x5F,0x29,0x1c,0xd0};
+  TEST_Choice1 c( TEST_Choice1::typeof_i2 );
+  memcpy(ctx.buffer(),seq,9);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice1::typeof_bs1);
+  CPPUNIT_ASSERT(c.get_bs1()[0] == 0xcd);
+  CPPUNIT_ASSERT(c.get_bs1()[1] == 0x91);
+  CPPUNIT_ASSERT(c.get_bs1()[2] == 0xf2);
+  CPPUNIT_ASSERT(c.get_bs1()[3] == 0xb5);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_os1()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x84,0x01,0x32};
+  TEST_Choice1 c( TEST_Choice1::typeof_i2,asn1::tag(asn1::types::CONTEXT_SPECIFIC,1) );
+  c.get_i2() = 14;
+  memcpy(ctx.buffer(),seq,3);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice1::typeof_os1);
+  CPPUNIT_ASSERT(std::string("2").compare(c.get_os1().get_sys_value() ) == 0);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_Choice1_nul()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x85,0x00,0x00};
+  TEST_Choice1 c( TEST_Choice1::typeof_i2 );
+  memcpy(ctx.buffer(),seq,2);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_kind() == TEST_Choice1::typeof_nul);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_ChoiceChoiceA()
+{
+  asn1::streams::ber ctx;
+  //const unsigned char seq[] = {0x40,0x01,0x0b};
+  const unsigned char seq[] = {0x80,0x03,0x40,0x01,0x0b};
+  ChoiceChoice c( 0, asn1::tag(asn1::types::APPLICATION,0) );
+  memcpy(ctx.buffer(),seq,5);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_choicea().get_i()== 11);
+}
+
+void TC_TEST_basic_types_choice::decode_TEST_ChoiceChoiceB()
+{
+  asn1::streams::ber ctx;
+  //const unsigned char seq[] = {0x81,0x01,0x0a};
+  const unsigned char seq[] = {0x81,0x03,0x81,0x01,0x0a};
+  ChoiceChoice c(asn1::tag(asn1::types::CONTEXT_SPECIFIC,1));
+  c.get_choiceb().get_ib() = 0;
+  memcpy(ctx.buffer(),seq,5);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+  CPPUNIT_ASSERT(c.get_choiceb().get_ib() == 10);
+}
+
diff --git a/tests/UNIT-TEST-basic-types-choice.h b/tests/UNIT-TEST-basic-types-choice.h
new file mode 100644 (file)
index 0000000..cbf0689
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "TEST_basic_types.h"
+
+
+class TC_TEST_basic_types_choice : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_choice );
+    CPPUNIT_TEST(encode_TEST_Choice_device);
+    CPPUNIT_TEST(encode_TEST_Choice_name);
+    CPPUNIT_TEST(encode_TEST_Choice_b1);
+    CPPUNIT_TEST(encode_TEST_Choice_ip4);
+    CPPUNIT_TEST(encode_TEST_Choice1_deviceId);
+    CPPUNIT_TEST(encode_TEST_Choice1_i2);
+    CPPUNIT_TEST(encode_TEST_Choice1_b1);
+    CPPUNIT_TEST(encode_TEST_Choice1_bs1);
+    CPPUNIT_TEST(encode_TEST_Choice1_os1);
+    CPPUNIT_TEST(encode_TEST_Choice1_nul);
+    CPPUNIT_TEST(encode_TEST_ChoiceChoiceA);
+    CPPUNIT_TEST(encode_TEST_ChoiceChoiceB);
+    CPPUNIT_TEST(decode_TEST_Choice_device);
+    CPPUNIT_TEST(decode_TEST_Choice_name);
+    CPPUNIT_TEST(decode_TEST_Choice1_deviceId);
+    CPPUNIT_TEST(decode_TEST_Choice1_i2);
+    CPPUNIT_TEST(decode_TEST_Choice1_b1);
+    CPPUNIT_TEST(decode_TEST_Choice1_bs1);
+    CPPUNIT_TEST(decode_TEST_Choice1_os1);
+    CPPUNIT_TEST(decode_TEST_Choice1_nul);
+    CPPUNIT_TEST(decode_TEST_ChoiceChoiceA);
+    CPPUNIT_TEST(decode_TEST_ChoiceChoiceB);
+   
+
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_TEST_Choice_device();
+    void encode_TEST_Choice_name();
+    void encode_TEST_Choice_b1();
+    void encode_TEST_Choice_ip4();
+    void encode_TEST_Choice1_deviceId();
+    void encode_TEST_Choice1_i2();
+    void encode_TEST_Choice1_b1();
+    void encode_TEST_Choice1_bs1();
+    void encode_TEST_Choice1_os1();
+    void encode_TEST_Choice1_nul();
+    void encode_TEST_ChoiceChoiceA();
+    void encode_TEST_ChoiceChoiceB();
+    //
+    //
+    void decode_TEST_Choice_device();
+    void decode_TEST_Choice_name();
+    void decode_TEST_Choice1_deviceId();
+    void decode_TEST_Choice1_i2();
+    void decode_TEST_Choice1_b1();
+    void decode_TEST_Choice1_bs1();
+    void decode_TEST_Choice1_os1();
+    void decode_TEST_Choice1_nul();
+    void decode_TEST_ChoiceChoiceA();
+    void decode_TEST_ChoiceChoiceB();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-enum.cpp b/tests/UNIT-TEST-basic-types-enum.cpp
new file mode 100644 (file)
index 0000000..1d17a61
--- /dev/null
@@ -0,0 +1,65 @@
+
+
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_enum.h"
+#include "UNIT-TEST-basic-types-enum.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_enum);
+
+using namespace TEST_basic_types_enum;
+
+void TC_TEST_basic_types_enum::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_enum::encode_TEST_Enum()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x0a,0x01,0x02};
+  //S.m_value = TEST_Enum::two;
+  asn1::prim::types::Integer I(TEST_Enum::two);
+  TEST_Enum S;
+  //S = I;
+  S = TEST_Enum::two;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result == 0);
+}
+void TC_TEST_basic_types_enum::encode_TEST_SeqEnum()
+{
+  const unsigned char seq[] = {0x31,0x05,0x02,0x01,0x06,0x05,0x00};
+  asn1::streams::ber ctx;
+  TEST_SeqEnum S;
+  S.enum1 = TEST_Enum::one ;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,7);
+//  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_enum::decode_TEST_Enum()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x0a,0x01,0x01};
+  TEST_Enum S;
+  memcpy(ctx.buffer(),seq,3);
+  //S.codec(ctx,S,asn1::CODEC_DECODE);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S  == TEST_Enum::one);
+}
+
+void TC_TEST_basic_types_enum::decode_TEST_SeqEnum()
+{
+  asn1::streams::ber ctx;
+  asn1::INTEGER i(asn1::prim::types::Integer(10)),i2(asn1::prim::types::Integer(12));
+}
+
diff --git a/tests/UNIT-TEST-basic-types-enum.h b/tests/UNIT-TEST-basic-types-enum.h
new file mode 100644 (file)
index 0000000..be0f4e5
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-enum.h"
+
+class TC_TEST_basic_types_enum : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_enum );
+    CPPUNIT_TEST(encode_TEST_Enum);   
+    CPPUNIT_TEST(encode_TEST_SeqEnum);
+    CPPUNIT_TEST(decode_TEST_Enum);
+    CPPUNIT_TEST(decode_TEST_SeqEnum);
+    CPPUNIT_TEST_SUITE_END();
+
+  public:
+    void setUp();
+  protected:
+
+    void encode_TEST_Enum();
+    void encode_TEST_SeqEnum();
+    void decode_TEST_Enum();
+    void decode_TEST_SeqEnum();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-explicit.cpp b/tests/UNIT-TEST-basic-types-explicit.cpp
new file mode 100644 (file)
index 0000000..2121617
--- /dev/null
@@ -0,0 +1,126 @@
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-explicit.h"
+#include "TEST_basic_types_explicit.h"
+#include "TEST_basic_types_explicit_codec.hpp"
+
+using namespace asn1;
+using namespace TEST_basic_types_explicit;
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_explicit);
+
+
+void TC_TEST_basic_types_explicit::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_explicit::encode_Test()
+{
+  asn1::streams::ber ctx;
+  Test i;
+  i.get_value() = 5;
+  
+  //i.codec(ctx,i,asn1::CODEC_ENCODE);
+  i.encode(ctx);
+  const unsigned char seq[] = {0x60,0x03,0x02,0x01,0x05};
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_explicit::encode_O_String()
+{
+  const unsigned char seq[] = {0x61,0x06,0x04,0x04,0x64,0x65,0x64,0x65};
+  asn1::streams::ber ctx;
+  std::string dede("dede"); 
+  O_String q; 
+  q.get_value() = dede;
+  q.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,8);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_explicit::encode_B_String()
+{
+  const unsigned char seq[] = { 0x62,0x04,0x03,0x02,0x00,0x55 };
+  asn1::streams::ber ctx;
+  B_String q; 
+  q[0]=0x55;
+  q.set_nb_bits(8);
+  //m_codec.encode(ctx,q);
+  q.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,6);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_explicit::encode_Bool_String()
+{
+  const unsigned char seq[] = { 0x63,0x03,0x01,0x01,0xFF };
+  asn1::streams::ber ctx;
+  Bool_String q; 
+  q .get_value() = true;
+  q.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+
+/**
+ *
+ */ 
+void TC_TEST_basic_types_explicit::decode_Test()
+{
+  asn1::streams::ber ctx;
+  Test q;
+  const unsigned char seq[] = {0x60,0x03,0x02,0x01,0x09};
+  
+  memcpy(ctx.buffer(),seq,5);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+  CPPUNIT_ASSERT(q.get_value() == 9);
+}
+
+void TC_TEST_basic_types_explicit::decode_O_String()
+{
+  asn1::streams::ber ctx;
+  O_String q;
+  const unsigned char seq[] = {0x61,0x06,0x04,0x04,0x64,0x65,0x64,0x65};
+  
+  memcpy(ctx.buffer(),seq,8);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+}
+
+void TC_TEST_basic_types_explicit::decode_B_String()
+{
+  asn1::streams::ber ctx;
+  B_String q;
+  //const unsigned char seq[] = { 0x62,0x07,0x30,0x05,0x0a,0x01,0x01,0x16,0x00 };
+  const unsigned char seq[] = { 0x62,0x04,0x03,0x02,0x00,0x51 };
+  
+  memcpy(ctx.buffer(),seq,6);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+  CPPUNIT_ASSERT(q[0] == 0x51);
+}
+
+void TC_TEST_basic_types_explicit::decode_Bool_String()
+{
+  asn1::streams::ber ctx;
+  Bool_String q;
+  const unsigned char seq[] = { 0x63,0x03,0x01,0x01,0x00 };
+  
+  memcpy(ctx.buffer(),seq,5);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+}
diff --git a/tests/UNIT-TEST-basic-types-explicit.h b/tests/UNIT-TEST-basic-types-explicit.h
new file mode 100644 (file)
index 0000000..2b9cab7
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef TESTCASE_IMPLICITTYPE_H
+#define TESTCASE_IMPLICITTYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_explicit.h"
+
+class TC_TEST_basic_types_explicit : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_explicit );
+    CPPUNIT_TEST(encode_Test);   
+    CPPUNIT_TEST(encode_O_String); 
+    CPPUNIT_TEST(encode_B_String); 
+    CPPUNIT_TEST(encode_Bool_String); 
+    // Decoding
+    CPPUNIT_TEST(decode_Test);   
+    CPPUNIT_TEST(decode_O_String);
+    CPPUNIT_TEST(decode_B_String);
+    CPPUNIT_TEST(decode_Bool_String);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Test();
+    void encode_O_String();
+    void encode_B_String();
+    void encode_Bool_String();
+
+    void decode_Test();
+    void decode_O_String();
+    void decode_B_String();
+    void decode_Bool_String();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-implicit.cpp b/tests/UNIT-TEST-basic-types-implicit.cpp
new file mode 100644 (file)
index 0000000..119af98
--- /dev/null
@@ -0,0 +1,80 @@
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-implicit.h"
+#include "TEST_basic_types_implicit.h"
+
+using namespace asn1;
+using namespace TEST_basic_types_implicit;
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_implicit);
+
+
+void TC_TEST_basic_types_implicit::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_implicit::encode_Ti()
+{
+  asn1::streams::ber ctx;
+  Ti i;
+  i.get_value() = 5;
+  
+  //i.codec(ctx,i,asn1::CODEC_ENCODE);
+  i.encode(ctx); 
+  const unsigned char seq[] = {0x88,0x01,0x05};
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_implicit::encode_query_device()
+{
+  const unsigned char seq[] = { 0xa2,0x07,0x30,0x05,0x0a,0x01,0x01,0x16,0x00 };
+  asn1::streams::ber ctx;
+  ListForwardParameters_type lfp;
+  lfp.forwardingType = 1; 
+  QueryDeviceResult q( QueryDeviceResult::typeof_deviceInformation,asn1::tag(2,0,true) );
+  q.get_deviceInformation().set_tag(asn1::tag(2,2));
+  q.get_deviceInformation().get_forward().push_back(lfp);; 
+  //q.codec(ctx,q,asn1::CODEC_ENCODE);
+  q.encode(ctx); 
+  
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+
+/**
+ *
+ */ 
+void TC_TEST_basic_types_implicit::decode_Ti()
+{
+  asn1::streams::ber ctx;
+  Ti q;
+  const unsigned char seq[] = { 0x88,0x01,0x0a};
+  
+  memcpy(ctx.buffer(),seq,3);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+  CPPUNIT_ASSERT(q.get_value() == 10);
+}
+
+void TC_TEST_basic_types_implicit::decode_query_device()
+{
+  asn1::streams::ber ctx;
+  QueryDeviceResult q( QueryDeviceResult::typeof_deviceInformation );
+  const unsigned char seq[] = { 0xa1,0x07,0x30,0x05,0x0a,0x01,0x01,0x16,0x00 };
+  
+  memcpy(ctx.buffer(),seq,9);
+  int r = q.decode(ctx);
+  
+  CPPUNIT_ASSERT(r == asn1::ok);
+}
+
diff --git a/tests/UNIT-TEST-basic-types-implicit.h b/tests/UNIT-TEST-basic-types-implicit.h
new file mode 100644 (file)
index 0000000..93f6ff6
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef TESTCASE_IMPLICITTYPE_H
+#define TESTCASE_IMPLICITTYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_implicit.h"
+
+class TC_TEST_basic_types_implicit : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_implicit );
+    CPPUNIT_TEST(encode_Ti);   
+    CPPUNIT_TEST(encode_query_device); 
+    // Decoding
+    CPPUNIT_TEST(decode_Ti);   
+    CPPUNIT_TEST(decode_query_device);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Ti();
+    void encode_query_device();
+
+    void decode_Ti();
+    void decode_query_device();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-optional.cpp b/tests/UNIT-TEST-basic-types-optional.cpp
new file mode 100644 (file)
index 0000000..243695f
--- /dev/null
@@ -0,0 +1,432 @@
+#include <cppunit/config/SourcePrefix.h>
+#include <string.h>
+#include <fstream>
+#define MAIN
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_optional.h"
+#include "UNIT-TEST-basic-types-optional.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_optional);
+
+using namespace TEST_basic_types_optional;
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::setUp()
+{
+
+}
+/**
+  requestID    INTEGER,
+  extention Extention OPTIONAL
+  */
+void TC_TEST_basic_types_optional::encode_Request()
+{
+  asn1::INTEGER i(asn1::prim::types::Integer(4));
+  Request r;
+  r.requestID = i;
+
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  //ctx.nb_bits(-1*ctx.nb_read_bits());
+  
+  //r.codec(ctx,str,CODEC_ENCODE);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 5);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_Request()
+{
+  const unsigned char seq[] = {0x30,0x03,0x02,0x01,0x04};
+  Request r;
+  asn1::streams::ber ctx;
+  
+  memcpy(ctx.buffer(),seq,5);
+  
+  r.decode(ctx);
+
+  CPPUNIT_ASSERT(r.requestID==4);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultInt()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  ReqDefaultInt r;
+  //r.extID = i;
+
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4);
+
+  CPPUNIT_ASSERT( memcmp(ctx.buffer(),seq,4)  == 0);
+
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultIntOther()
+{
+  const unsigned char seq[] = {0x30,0x05,0x02,0x01,0x03,0x05,0x00};
+  ReqDefaultInt r;
+  // Why should an attribute with a default value be tagged as shared ptr ?
+  //r.extID = asn1::intrusive_ptr<INTEGER>(new INTEGER(3));
+  r.extID = 3;
+  r.bit_mask.set(ReqDefaultInt::extID_present);
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 7);
+
+  CPPUNIT_ASSERT( memcmp(ctx.buffer(),seq,7)  == 0);
+
+}
+
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultBool()
+{
+  ReqDefaultBool r;
+  //r.extID = i;
+
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultBoolOther()
+{
+  const unsigned char seq[] = {0x30,0x05,0x01,0x01,0x00,0x05,0x00};
+  ReqDefaultBool r;
+  //r.extID = i;
+  //r.extID = asn1::intrusive_ptr<BOOLEAN>(new BOOLEAN(false));
+  r.extID   = true;
+  r.bit_mask.set(ReqDefaultBool::extID_present);
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 7);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultString()
+{
+  ReqDefaultString r;
+  //r.extID = i;
+
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqDefaultStringOther()
+{
+  const unsigned char seq[] = {0x30,0x08,0x16,0x04,0x64,0x65,0x64,0x65,0x05,0x00};
+  ReqDefaultString r;
+  //r.extID = i;
+  asn1::prim::types::String ps = std::string("dede");
+  //r.extID = asn1::intrusive_ptr<IA5String>(new IA5String());
+  (r.extID) = ps; 
+  r.bit_mask.set(ReqDefaultString::extID_present);
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 10);
+}
+
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqOptInt()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x03,0x02,0x01,0x04};
+  ReqOptInt r;
+  asn1::intrusive_ptr<INTEGER> i( new INTEGER(asn1::prim::types::Integer(3)));
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4);
+ // Set the optional value
+  ctx.reset();
+  
+  r.extID = i;
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 7);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqOptBool()
+{
+  ReqOptBool r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ReqOptString()
+{
+  ReqOptString r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  r.encode(ctx);
+  
+  CPPUNIT_ASSERT( (ctx.nb_read_bits() / 8)  == 4) ;
+}
+
+
+/**
+Extension ::= SEQUENCE {
+  extID  INTEGER DEFAULT 2,
+  data   OCTET STRING,
+  bits   BitSTR DEFAULT {bit1} ,
+  boolean BOOLEAN   DEFAULT TRUE,
+  toto  BitSTR DEFAULT {}
+}
+*/
+
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_Extension()
+{
+  const unsigned char seq[] = {0x30,0x02,0x04,0x00};
+  Extension e;
+  
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  e.encode(ctx);
+  CPPUNIT_ASSERT((ctx.nb_read_bits()/8) == 4);
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::encode_ExtensionOther()
+{
+  //   30 08 02 01 04 04 00 01 01 00
+  Extension e;
+  e.extID   = 4;
+  e.bit_mask.set(Extension::extID_present);
+  e.boolean = false;
+  e.bit_mask.set(Extension::boolean_present);
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  e.encode(ctx);
+  CPPUNIT_ASSERT((ctx.nb_read_bits()/8) == 10);
+}
+
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_Extension()
+{
+  const unsigned char seq[] = { 0x30,0x08,0x02,0x01,0x04,0x04,0x00,0x01,0x01,0x00 };
+  Extension e;
+  
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,10);
+  e.decode(ctx);
+  CPPUNIT_ASSERT(e.boolean == false);
+  CPPUNIT_ASSERT(e.extID == 4);
+}
+
+void TC_TEST_basic_types_optional::decode_ReqDefaultInt()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x03,0x02,0x01,0x04,0x05,0x00};
+  ReqDefaultInt r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+   CPPUNIT_ASSERT( r.extID == 2);
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,7);
+  
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT(r.extID == 4 );
+}
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_ReqDefaultBool()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x03,0x01,0x01,0x04,0x05,0x00};
+  ReqDefaultBool r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+  //CPPUNIT_ASSERT( r.extID.is_nul() == true);
+ CPPUNIT_ASSERT( r.extID == false);
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,7);
+  
+  r.decode(ctx);
+  
+  //CPPUNIT_ASSERT( r.extID.is_nul() == false);
+  CPPUNIT_ASSERT(r.extID == true );
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_ReqDefaultString()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x06,0x16,0x02,0x30,0x31,0x05,0x00};
+  ReqDefaultString r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT(std::string("james").compare(r.extID.get_sys_value()) == 0 );
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,8);
+  
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT(std::string("01").compare(r.extID.get_sys_value()) == 0 );
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_ReqOptInt()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x03,0x02,0x01,0x04,0x05,0x00};
+  ReqOptInt r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+   CPPUNIT_ASSERT( r.extID.is_nul() == true);
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,7);
+  
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT(**(r.extID) == 4 );
+}
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_ReqOptBool()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x03,0x01,0x01,0x04,0x05,0x00};
+  ReqOptBool r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT( r.extID.is_nul() == true);
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,7);
+  
+  r.decode(ctx);
+  
+  CPPUNIT_ASSERT( r.extID.is_nul() == false);
+  CPPUNIT_ASSERT(**(r.extID) == true );
+}
+
+/**
+ *
+ */
+void TC_TEST_basic_types_optional::decode_ReqOptString()
+{
+  const unsigned char seq[] = {0x30,0x02,0x05,0x00};
+  const unsigned char seqopt[] = {0x30,0x06,0x16,0x02,0x30,0x31,0x05,0x00};
+  ReqOptString r;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  
+  memcpy(ctx.buffer(),seq,4);
+  r.decode(ctx);
+  
+   CPPUNIT_ASSERT( r.extID.is_nul() == true);
+ // Set the optional value
+  ctx.reset();
+  memcpy(ctx.buffer(),seqopt,8);
+  
+  r.decode(ctx);
+  
+   CPPUNIT_ASSERT( r.extID.is_nul() == false);
+  CPPUNIT_ASSERT(std::string("01").compare(r.extID->get_sys_value()) == 0 );
+}
+
diff --git a/tests/UNIT-TEST-basic-types-optional.h b/tests/UNIT-TEST-basic-types-optional.h
new file mode 100644 (file)
index 0000000..439bb05
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef TESTCASE_BTYPE_OPT_H
+#define TESTCASE_BTYPE_OPT_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+
+class TC_TEST_basic_types_optional : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_optional );
+    CPPUNIT_TEST(encode_Request);
+    CPPUNIT_TEST(encode_ReqDefaultInt);
+    CPPUNIT_TEST(encode_ReqDefaultIntOther);
+    CPPUNIT_TEST(encode_ReqDefaultBool);
+    CPPUNIT_TEST(encode_ReqDefaultBoolOther);
+    CPPUNIT_TEST(encode_ReqDefaultString);
+    CPPUNIT_TEST(encode_ReqDefaultStringOther);
+    CPPUNIT_TEST(encode_Extension);
+    CPPUNIT_TEST(encode_ExtensionOther);
+    CPPUNIT_TEST(encode_ReqOptInt);
+    CPPUNIT_TEST(encode_ReqOptBool);
+    CPPUNIT_TEST(encode_ReqOptString);
+    
+    CPPUNIT_TEST(decode_Request);
+    CPPUNIT_TEST(decode_Extension);
+    CPPUNIT_TEST(decode_ReqDefaultInt);
+    CPPUNIT_TEST(decode_ReqDefaultBool);
+    CPPUNIT_TEST(decode_ReqDefaultString);
+    CPPUNIT_TEST(decode_ReqOptInt);
+    CPPUNIT_TEST(decode_ReqOptBool);
+    CPPUNIT_TEST(decode_ReqOptString);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Request();
+    void encode_ReqDefaultInt();
+    void encode_ReqDefaultIntOther();
+    void encode_ReqDefaultBool();
+    void encode_ReqDefaultBoolOther();
+    void encode_ReqDefaultString();
+    void encode_ReqDefaultStringOther();
+    void encode_Extension();
+    void encode_ExtensionOther();
+    void encode_ReqOptInt();
+    void encode_ReqOptBool();
+    void encode_ReqOptString();
+    
+    void decode_Request();
+    void decode_Extension();
+    void decode_ReqDefaultInt();
+    void decode_ReqDefaultBool();
+    void decode_ReqDefaultString();
+    void decode_ReqOptInt();
+    void decode_ReqOptBool();
+    void decode_ReqOptString();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-sequence.cpp b/tests/UNIT-TEST-basic-types-sequence.cpp
new file mode 100644 (file)
index 0000000..1fc2059
--- /dev/null
@@ -0,0 +1,88 @@
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_sequence.h"
+#include "UNIT-TEST-basic-types-sequence.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_sequence);
+
+using namespace TEST_basic_types_sequence;
+
+void TC_TEST_basic_types_sequence::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_sequence::decode_Sequence()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x05,0x02,0x01,0x05,0x05,0x00};
+  unsigned char *table = ctx.buffer();
+  memcpy(table,seq,7);
+  TEST_Sequence S;
+  S.decode(ctx);
+  CPPUNIT_ASSERT(S.device==5);
+}
+void TC_TEST_basic_types_sequence::decode_ImplicitSequence()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x07,0x80,0x02,0x61,0x62,0x82,0x1,0x63};
+  unsigned char *table = ctx.buffer();
+  memcpy(table,seq,9);
+  TEST_Implicit_Sequence S;
+  S.decode(ctx);
+  CPPUNIT_ASSERT(std::string("ab").compare(S.s1.get_sys_value())==0);
+}
+void TC_TEST_basic_types_sequence::decode_IntegerList()
+{
+  asn1::streams::ber ctx;
+    const unsigned char seq[] = { 0x30, 0x06, 0x02, 0x01, 0x0a, 0x02, 0x01, 0x0c};
+  unsigned char *table = ctx.buffer();
+  memcpy(table,seq,8);
+  Seq<asn1::INTEGER> S;
+  S.decode(ctx);
+  CPPUNIT_ASSERT(S[0]==10);
+}
+
+void TC_TEST_basic_types_sequence::encode_Sequence()
+{
+  const unsigned char seq[] = {0x30,0x05,0x02,0x01,0x06,0x05,0x00};
+  asn1::streams::ber ctx;
+  TEST_Sequence S;
+  S.device = 6;
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+void TC_TEST_basic_types_sequence::encode_ImplicitSequence()
+{
+  asn1::streams::ber ctx;
+  TEST_Implicit_Sequence S;
+  IA5String s(asn1::prim::types::String("ab"));
+  S.s1 = s;
+  //S.s2.get() = "c";
+  S.s3.get() = "d";
+  //S.encode(ctx);
+  m_codec.encode(ctx,S);
+  unsigned char seq[] = {0x30, 0x07, 0x80, 0x02, 0x61, 0x62, 0x82, 0x01,0x64 };  
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+void TC_TEST_basic_types_sequence::encode_IntegerList()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = { 0x30, 0x06, 0x02, 0x01, 0x0a, 0x02, 0x01, 0x0c};
+  TEST_IntegerList S;
+  //Seq<asn1::INTEGER> S;
+  asn1::INTEGER i(10),i2(12);
+  S.push_back(i);
+  S.push_back(i2);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,8);
+  CPPUNIT_ASSERT(result==0);
+}
diff --git a/tests/UNIT-TEST-basic-types-sequence.h b/tests/UNIT-TEST-basic-types-sequence.h
new file mode 100644 (file)
index 0000000..c671f8f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-sequence.h"
+
+class TC_TEST_basic_types_sequence : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_sequence );
+
+    CPPUNIT_TEST(encode_IntegerList);   
+    CPPUNIT_TEST(encode_Sequence);
+    CPPUNIT_TEST(encode_ImplicitSequence);
+    CPPUNIT_TEST(decode_IntegerList); 
+    CPPUNIT_TEST(decode_Sequence);
+    CPPUNIT_TEST(decode_ImplicitSequence);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void decode_Sequence();
+    void decode_IntegerList();
+    void decode_ImplicitSequence();
+
+    void encode_IntegerList();
+    void encode_ImplicitSequence();
+    void encode_Sequence();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-set.cpp b/tests/UNIT-TEST-basic-types-set.cpp
new file mode 100644 (file)
index 0000000..503659a
--- /dev/null
@@ -0,0 +1,89 @@
+
+
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_set.h"
+#include "UNIT-TEST-basic-types-set.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_set);
+
+using namespace TEST_basic_types_set;
+
+void TC_TEST_basic_types_set::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_set::encode_Set()
+{
+  const unsigned char seq[] = {0x31,0x05,0x02,0x01,0x06,0x05,0x00};
+  asn1::streams::ber ctx;
+  TEST_Set S;
+  S.device = 6;
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_set::encode_SetOfInt()
+{
+  const unsigned char seq[] = {0x31,0x06,0x02,0x01,0x05,0x02,0x01,0x04};
+  asn1::streams::ber ctx;
+  TEST_SetOfInt S;
+       Int i;
+  i    = 5;
+  S.push_back(i);
+       i = 4;
+  S.push_back(i);
+       S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,8);
+
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_set::encode_ImplicitSequence()
+{
+  asn1::streams::ber ctx;
+ // TEST_Implicit_Sequence S;
+  IA5String s(asn1::prim::types::String("ab"));
+}
+
+void TC_TEST_basic_types_set::encode_IntegerList()
+{
+  asn1::streams::ber ctx;
+  asn1::INTEGER i(10),i2(12);
+}
+
+/**
+ * Decode Stuff
+ */ 
+
+void TC_TEST_basic_types_set::decode_Set()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x31,0x05,0x02,0x01,0x05,0x05,0x00};
+  unsigned char *table = ctx.buffer();
+  memcpy(table,seq,7);
+  TEST_Set S;
+  S.decode(ctx);
+  CPPUNIT_ASSERT(S.device==5);
+}
+
+void TC_TEST_basic_types_set::decode_SetOfInt()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x31,0x06,0x02,0x01,0x03,0x02,0x01,0x08};
+  unsigned char *table = ctx.buffer();
+  memcpy(table,seq,8);
+  TEST_SetOfInt S;
+  S.decode(ctx);
+  CPPUNIT_ASSERT(S.size() == 2);
+}
+
+
diff --git a/tests/UNIT-TEST-basic-types-set.h b/tests/UNIT-TEST-basic-types-set.h
new file mode 100644 (file)
index 0000000..d6a4875
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-set.h"
+
+class TC_TEST_basic_types_set : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_set );
+    CPPUNIT_TEST(encode_Set);
+    CPPUNIT_TEST(encode_SetOfInt);
+    CPPUNIT_TEST(encode_IntegerList);   
+    CPPUNIT_TEST(encode_ImplicitSequence);
+    
+    CPPUNIT_TEST(decode_Set);
+    CPPUNIT_TEST(decode_SetOfInt);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Set();
+    void encode_IntegerList();
+    void encode_ImplicitSequence();
+    void encode_SetOfInt();
+
+    void decode_Set();
+    void decode_SetOfInt();
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types-tagged.cpp b/tests/UNIT-TEST-basic-types-tagged.cpp
new file mode 100644 (file)
index 0000000..e002ea9
--- /dev/null
@@ -0,0 +1,291 @@
+
+
+#include <cppunit/config/SourcePrefix.h>
+
+#include <fstream>
+#include <string.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types_tagged.h"
+#include "UNIT-TEST-basic-types-tagged.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types_tagged);
+
+using namespace TEST_basic_types_tagged;
+
+void TC_TEST_basic_types_tagged::setUp()
+{
+
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedInteger()
+{
+  asn1::streams::ber ctx;
+//  const unsigned char seq[] = {0x43,0x03,0x02,0x01,0x03};
+  // Explicit tagging is constructed
+  const unsigned char seq[] = {0x63,0x03,0x02,0x01,0x03};
+  Int S;
+  asn1::prim::types::Integer i = 3;
+  S = i;
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result == 0);
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedSeq()
+{
+  const unsigned char seq[] = {0x62,0x07,0x30,0x05,0x02,0x01,0x06,0x05,0x00};
+  asn1::streams::ber ctx;
+  SeqE S;
+  asn1::prim::types::Integer i = 6;
+  S.one = i;
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedSeqE1()
+{
+  // Explicit tagging is construted
+  const unsigned char seq[] = {0x64,0x09,0x30,0x07,0x63,0x03,0x02,0x01,0x0A,0x05,0x00};
+  asn1::streams::ber ctx;
+  SeqE1 S;
+  asn1::prim::types::Integer i = 10;
+  S.one = i;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,11);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_tagged::encode_TaggedSeqI()
+{
+  const unsigned char seq[] = {0x65,0x05,0x55,0x01,0x06,0x56,0x00};
+  asn1::streams::ber ctx;
+  SeqI S;
+  asn1::prim::types::Integer i = 6;
+  S.one = i;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedInSeq()
+{
+  //const unsigned char seq[] = {0x30,0x0a,0xa0,0x03,0x02,0x01,0x06,0x43,0x03,0x02,0x01,0x09};
+  // Explicit is constructed
+  // 30 06 a0 03 02 01 06 63 03 43 01 09
+  const unsigned char seq[] = {0x30,0x0a,0xa0,0x03,0x02,0x01,0x06,0x63,0x03,0x02,0x01,0x09};
+  asn1::streams::ber ctx;
+  InSeq S;
+  asn1::prim::types::Integer i = 6;
+  S.one = i;
+  Int nu; i= 9;
+  nu = i;
+  S.nu = nu;
+  //S.encode(ctx);
+  m_codec.encode(ctx,S);
+  int result = memcmp(ctx.buffer(),seq,12);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedChoice()
+{
+  //const unsigned char seq[] = {0xa2,0x09,0x30,0x07,0x83,0x03,0x02,0x01,0x06,0x05,0x00};
+  const unsigned char seq[] = {0x64,0x03,0x40,0x01,0x06};
+  asn1::streams::ber ctx;
+  Choice S(Choice::typeof_one);
+  asn1::prim::types::Integer i = 6;
+  S.get_one() = i;
+  //S.kind_ = Choice::typeof_one;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_tagged::encode_TaggedChoiceSeqE()
+{
+  //const unsigned char seq[] = {0x62,0x07,0x30,0x05,0x02,0x01,0x06,0x05,0x00};
+  //const unsigned char seq[] = {0xa2,0x09,0x30,0x07,0x83,0x03,0x02,0x01,0x06,0x05,0x00};
+  const unsigned char seq[] = {0x64,0x09,0x62,0x07,0x30,0x05,0X02,0x01,0x6,0x05,0x00};
+  asn1::streams::ber ctx;
+  Choice S(Choice::typeof_seqe,asn1::tag(asn1::types::APPLICATION,2));
+  S.get_seqe().one = 6;
+  //S.kind_ = Choice::typeof_one;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_basic_types_tagged::encode_TaggedSetE()
+{
+  //   64 07 30 05 02 01 06 05 00
+  const unsigned char seq[] = {0x64,0x07,0x31,0x05,0x02,0x01,0x06,0x05,0x00};
+  asn1::streams::ber ctx;
+  TSetE S;
+  asn1::prim::types::Integer i = 6;
+  S.one = i;
+  S.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types_tagged::encode_IntILT62()
+{
+  const unsigned char seq[] = {0x5F,0x3E,0x01,0x05};
+  asn1::streams::ber ctx;
+  IntILT62 I;
+  I = 5;
+  I.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+    
+void TC_TEST_basic_types_tagged::encode_IntILT432()
+{
+  const unsigned char seq[] = {0x5F,0x83,0x30,0x01,0x05};
+  asn1::streams::ber ctx;
+  IntILT432 I;
+  I = 5;
+  I.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+    
+void TC_TEST_basic_types_tagged::encode_IntELT72()
+{
+  //   7f 48 03 02 01 05
+  const unsigned char seq[] = {0x5F,0x83,0x30,0x01,0x05};
+  asn1::streams::ber ctx;
+  IntELT72 I;
+  I = 5;
+  //I.encode(ctx);
+  m_codec.encode(ctx,I);
+  int result = memcmp(ctx.buffer(),seq,5);
+  CPPUNIT_ASSERT(result==0);
+}
+    
+
+
+
+
+#if 0
+void TC_TEST_basic_types_tagged::decode_TEST_SeqEnum()
+{
+  asn1::streams::ber ctx;
+  asn1::INTEGER i(10),i2(12);
+}
+
+#endif
+
+void TC_TEST_basic_types_tagged::decode_IntILT62()
+{
+  const unsigned char seq[] = {0x5F,0x3E,0x01,0x05};
+  asn1::streams::ber ctx;
+  IntILT62 I;
+  memcpy(ctx.buffer(),seq,4);
+  I.decode(ctx);
+  CPPUNIT_ASSERT(I.get_value()==5);
+}
+    
+void TC_TEST_basic_types_tagged::decode_IntILT432()
+{
+  const unsigned char seq[] = {0x5F,0x83,0x30,0x01,0x0a};
+  asn1::streams::ber ctx;
+  IntILT432 I;
+  memcpy(ctx.buffer(),seq,5);
+  I.decode(ctx);
+  CPPUNIT_ASSERT(I.get_value()==10);
+}
+    
+void TC_TEST_basic_types_tagged::decode_IntELT72()
+{
+}
+    
+
+void TC_TEST_basic_types_tagged::decode_TaggedInteger()
+{
+  asn1::streams::ber ctx;
+  //const unsigned char seq[] = {0x43,0x03,0x02,0x01,0x07};
+  const unsigned char seq[] = {0x63,0x03,0x02,0x01,0x07};
+  Int S;
+  memcpy(ctx.buffer(),seq,5);
+  //S.codec(ctx,S,asn1::CODEC_DECODE);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.get_value()  == 7);
+}
+
+
+void TC_TEST_basic_types_tagged::decode_TaggedSeq()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x62,0x07,0x30,0x05,0x02,0x01,0x06,0x05,0x00};
+  SeqE S;
+  memcpy(ctx.buffer(),seq,9);
+  //S.codec(ctx,S,asn1::CODEC_DECODE);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.one  == 6);
+}
+void TC_TEST_basic_types_tagged::decode_TaggedSeqE1()
+{
+  asn1::streams::ber ctx;
+  //const unsigned char seq[] = {0x64,0x09,0x30,0x07,0x43,0x03,0x02,0x01,0x06,0x05,0x00};
+  const unsigned char seq[] = {0x64,0x09,0x30,0x07,0x63,0x03,0x02,0x01,0x06,0x05,0x00};
+  SeqE1 S;
+  memcpy(ctx.buffer(),seq,11);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.one.get_value()  == 6);
+}
+
+void TC_TEST_basic_types_tagged::decode_TaggedSeqI()
+{
+  const unsigned char seq[] = {0x65,0x05,0x55,0x01,0x06,0x56,0x00};
+  asn1::streams::ber ctx;
+  SeqI S;
+  memcpy(ctx.buffer(),seq,11);
+  S.decode(ctx);
+  int result = memcmp(ctx.buffer(),seq,7);
+  // CPPUNIT_ASSERT(result==0);
+  CPPUNIT_ASSERT( S.one.get_value()  == 6);
+}
+
+
+void TC_TEST_basic_types_tagged::decode_TaggedInSeq()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x0a,0xa0,0x03,0x02,0x01,0x06,0x43,0x03,0x02,0x01,0x09};
+  InSeq S;
+  memcpy(ctx.buffer(),seq,12);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.one.get_value()  == 6);
+}
+
+void TC_TEST_basic_types_tagged::decode_TaggedChoice()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x64,0x03,0x40,0x01,0x06};
+  Choice S;
+  memcpy(ctx.buffer(),seq,5);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.get_one()  == 6);
+}
+
+void TC_TEST_basic_types_tagged::decode_TaggedSetE()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x64,0x07,0x31,0x05,0x02,0x01,0x06,0x05,0x00};
+  TSetE S;
+  memcpy(ctx.buffer(),seq,9);
+  S.decode(ctx);
+  CPPUNIT_ASSERT( S.one  == 6);
+}
+
+
+
diff --git a/tests/UNIT-TEST-basic-types-tagged.h b/tests/UNIT-TEST-basic-types-tagged.h
new file mode 100644 (file)
index 0000000..4861a0a
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-basic-types-tagged.h"
+
+class TC_TEST_basic_types_tagged : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types_tagged );
+    CPPUNIT_TEST(encode_TaggedInteger);   
+    CPPUNIT_TEST(encode_TaggedSeq);
+    CPPUNIT_TEST(encode_TaggedSeqE1);
+    CPPUNIT_TEST(encode_TaggedSeqI);
+    CPPUNIT_TEST(encode_TaggedInSeq);
+    CPPUNIT_TEST(encode_TaggedChoice);
+    CPPUNIT_TEST(encode_TaggedChoiceSeqE);
+    CPPUNIT_TEST(encode_TaggedSetE);
+    CPPUNIT_TEST(encode_IntILT62);
+    CPPUNIT_TEST(encode_IntILT432);
+    CPPUNIT_TEST(encode_IntELT72);
+
+    CPPUNIT_TEST(decode_IntILT62);
+    CPPUNIT_TEST(decode_IntILT432);
+    CPPUNIT_TEST(decode_IntELT72);
+    CPPUNIT_TEST(decode_TaggedInteger);   
+    CPPUNIT_TEST(decode_TaggedSeq);
+    CPPUNIT_TEST(decode_TaggedSeqE1);
+    CPPUNIT_TEST(decode_TaggedSeqI);
+    CPPUNIT_TEST(decode_TaggedInSeq);
+    CPPUNIT_TEST(decode_TaggedChoice);
+    CPPUNIT_TEST(decode_TaggedSetE);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_TaggedInteger();
+    void encode_TaggedSeq();
+    void encode_TaggedSeqE1();
+    void encode_TaggedSeqI();
+    void encode_TaggedInSeq();
+    void encode_TaggedChoice();
+    void encode_TaggedChoiceSeqE();
+    void encode_TaggedSetE();
+    void encode_IntILT62();    
+    void encode_IntILT432();    
+    void encode_IntELT72();    
+
+    void decode_IntILT62();    
+    void decode_IntILT432();    
+    void decode_IntELT72();    
+    void decode_TaggedInteger();
+    void decode_TaggedSeq();
+    void decode_TaggedSeqE1();
+    void decode_TaggedSeqI();
+    void decode_TaggedInSeq();
+    void decode_TaggedChoice();
+    void decode_TaggedSetE();
+#if 0
+    void encode_TaggedSeq();
+    void decode_TaggedSeq();
+    void decode_TEST_Enum();
+    void decode_TEST_SeqEnum();
+#endif
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-basic-types.cpp b/tests/UNIT-TEST-basic-types.cpp
new file mode 100644 (file)
index 0000000..d2e7b23
--- /dev/null
@@ -0,0 +1,280 @@
+#include <cppunit/config/SourcePrefix.h>
+#include <string.h>
+#include <fstream>
+#define MAIN
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "TEST_basic_types.h"
+#include "UNIT-TEST-basic-types.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_basic_types);
+
+using namespace TEST_basic_types;
+
+void TC_TEST_basic_types::setUp()
+{
+
+}
+
+void TC_TEST_basic_types::encode_Test()
+{
+  std::string s("Jones");
+  asn1::prim::types::String ps = s;
+  VisibleString os =ps;
+  VString1 vs1(os);
+  VString2 str;
+  str = vs1;
+  asn1::streams::ber ctx;
+  unsigned char *table = ctx.buffer();
+  table[0] = '\02'; table[1] = '\01';table[2] = '\05';
+  TEST_basic_types::Test test;
+  //asn1::streams::ber::codec(ctx,test,asn1::CODEC_DECODE);
+  //test.codec(ctx,test,asn1::CODEC_DECODE);
+  test.decode(ctx);
+  ctx.nb_bits(-1*ctx.nb_read_bits());
+  //str.codec(ctx,str,CODEC_ENCODE);
+  str.encode(ctx);
+  CPPUNIT_ASSERT(test.get_value()==5);
+}
+
+void TC_TEST_basic_types::encode_TestI()
+{
+  const unsigned char seq[] = {0x02,0x01,0x01};
+  TEST_basic_types::TestI i;
+  i = TEST_basic_types::TestI::one;
+
+  asn1::streams::ber ctx;
+  
+  i.encode(ctx);
+  
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result == 0);
+}
+
+
+void TC_TEST_basic_types::encode_VString1()
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::String s("Jones");
+  VString1 str;
+  str = s;
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  
+  const unsigned char seq[] = {0x1a,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types::encode_VString2()
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::String s("Jones");
+  VString2 str;
+  str = VString1(s);
+  //codec<asn1::streams::ber>(ctx,str,asn1::CODEC_ENCODE);
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  
+  const unsigned char seq[] = {0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types::encode_VString3()
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::String s("Jones");
+  //    (VString2(VString1((std::string("Jones")))));
+  VString2 str2;
+  str2  = VString1(s);
+  VString3 str;
+  str = str2;
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  const unsigned char seq[] = {0xa2,0x07,0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types::encode_VString4()
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::String s("Jones");
+  //(VString3(VString2(VString1((std::string("Jones"))))));
+  VString2 str2;
+  str2  = VString1(s);
+  VString3 str3;
+  str3 = str2;
+  VString4 str;
+  str = str3;
+  //str = s; Fails during compilation
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  
+  const unsigned char seq[] = {0x67,0x07,0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  int result = memcmp(ctx.buffer(),seq,9);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_basic_types::encode_VString5()
+{
+  asn1::streams::ber ctx;
+  asn1::prim::types::String s("Jones");
+  VString5 str ;
+  VString2 str2;
+  VString1 str1(s);
+  str2 = str1;
+  str  = str2;
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  const unsigned char seq[] = {0x82,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+
+}
+
+void TC_TEST_basic_types::encode_BString()
+{
+  asn1::streams::ber ctx;
+  B_String str;
+  str[0]= 0x0a;
+  //str.codec(ctx,str,asn1::CODEC_ENCODE);
+  str.encode(ctx);
+  
+  const unsigned char seq[] = {0x03,0x02,0x04,0xa0}; 
+  //int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT_EQUAL((unsigned long)4,ctx.bytes());
+  CPPUNIT_ASSERT_EQUAL(0,memcmp(ctx.buffer(),seq,4));
+
+}
+
+// Decode string
+
+void TC_TEST_basic_types::decode_Test()
+{
+}
+
+void TC_TEST_basic_types::decode_TestI()
+{
+  const unsigned char seq[] = {0x02,0x01,0x02};
+  TEST_basic_types::TestI i;
+  asn1::streams::ber ctx;
+  
+  memcpy(ctx.buffer(),seq,3);
+  
+  i.decode(ctx);
+  
+  CPPUNIT_ASSERT(i.get_value() == 2);
+}
+
+void TC_TEST_basic_types::decode_VString1()
+{
+  const unsigned char seq[] = {0x1a,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),seq,7);
+  VString1 str;
+  //str.codec(ctx,str,asn1::CODEC_DECODE);
+  str.decode(ctx);
+  CPPUNIT_ASSERT(std::string("Jones").compare(str.get_sys_value())==0); 
+}
+void TC_TEST_basic_types::decode_VString2()
+{
+  const unsigned char seq[] = {0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),seq,7);
+  VString2 str;
+  //str.codec(ctx,str,asn1::CODEC_DECODE);
+  str.decode(ctx);
+  CPPUNIT_ASSERT(std::string("Jones").compare(str.get_sys_value())==0); 
+}
+void TC_TEST_basic_types::decode_VString3()
+{
+  const unsigned char seq[] = {0xa2,0x07,0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),seq,9);
+  VString3 str;
+  //str.codec(ctx,str,asn1::CODEC_DECODE);
+  str.decode(ctx);
+  CPPUNIT_ASSERT(std::string("Jones").compare(str.get_sys_value())==0); 
+}
+void TC_TEST_basic_types::decode_VString4()
+{
+  const unsigned char seq[] = {0x67,0x07,0x43,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),seq,9);
+  VString4 str;
+  //str.codec(ctx,str,asn1::CODEC_DECODE);
+  str.decode(ctx);
+  CPPUNIT_ASSERT(std::string("Jones").compare(str.get_sys_value())==0); 
+}
+void TC_TEST_basic_types::decode_VString5()
+{
+  const unsigned char seq[] = {0x82,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  memcpy(ctx.buffer(),seq,7);
+  VString5 str;
+  //str.codec(ctx,str,asn1::CODEC_DECODE);
+  str.decode(ctx);
+  CPPUNIT_ASSERT(std::string("Jones").compare(str.get_sys_value())==0); 
+}
+
+void TC_TEST_basic_types::decode_BString()
+{
+ const unsigned char seq[] = {0x03,0x02,0x04,0xa0};
+ asn1::streams::ber ctx;
+ B_String str;
+ memcpy(ctx.buffer(),seq,4);
+ //str.codec(ctx,str,asn1::CODEC_DECODE); 
+ str.decode(ctx);
+ CPPUNIT_ASSERT(str[0]==0x0a); 
+}
+
+/**
+ * OCTET STRING TESTS
+ */ 
+void TC_TEST_basic_types::ostring_equal()
+{
+  O_String a,b;
+  asn1::prim::types::String s("Jones");
+  a = s;
+  b = a;
+  CPPUNIT_ASSERT(a == b);
+  // b = std::string("toto");
+  //CPPUNIT_ASSERT(a != b);
+}
+
+void TC_TEST_basic_types::ostring_copy()
+{
+  O_String a,b;
+  a = std::string("toto");
+  b = a;
+  CPPUNIT_ASSERT(a == b);
+}
+
+/**
+ * OBJECT IDENTIFIER TESTS
+ */ 
+void TC_TEST_basic_types::oid_equal()
+{
+  TestOid a,b;
+  id_1   v;
+  a = id_1();
+  b = v;
+  std::cerr<<"ARRAY: a="<<a<<" b="<<b<<" v ="<<v<<std::endl;
+  CPPUNIT_ASSERT(a == b);
+}
+
+void TC_TEST_basic_types::oid_copy()
+{
+  TestOid a,b;
+  id_1   v;
+  a = id_1();
+  b = a;
+  CPPUNIT_ASSERT(a == b);
+}
diff --git a/tests/UNIT-TEST-basic-types.h b/tests/UNIT-TEST-basic-types.h
new file mode 100644 (file)
index 0000000..2b795a0
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+
+class TC_TEST_basic_types : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_basic_types );
+    CPPUNIT_TEST(encode_Test);
+    CPPUNIT_TEST(encode_TestI);
+    CPPUNIT_TEST(encode_VString1);   
+    CPPUNIT_TEST(encode_VString2);
+    CPPUNIT_TEST(encode_VString3);
+    CPPUNIT_TEST(encode_VString4);
+    CPPUNIT_TEST(encode_VString5);
+    CPPUNIT_TEST(encode_BString); 
+    
+    CPPUNIT_TEST(decode_Test);
+    CPPUNIT_TEST(decode_TestI);
+    CPPUNIT_TEST(decode_VString1);   
+    CPPUNIT_TEST(decode_VString2);
+    CPPUNIT_TEST(decode_VString3);
+    CPPUNIT_TEST(decode_VString4);
+    CPPUNIT_TEST(decode_VString5);
+    CPPUNIT_TEST(decode_BString);                       
+    
+    CPPUNIT_TEST(oid_equal);                       
+    CPPUNIT_TEST(oid_copy);                       
+    
+    CPPUNIT_TEST(ostring_equal);                       
+    CPPUNIT_TEST(ostring_copy);                       
+
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Test();
+    void encode_TestI();
+    void encode_VString1();
+    void encode_VString2();
+    void encode_VString3();
+    void encode_VString4();
+    void encode_VString5();
+    void encode_BString();
+    
+    void decode_Test();
+    void decode_TestI();
+    void decode_VString1();
+    void decode_VString2();
+    void decode_VString3();
+    void decode_VString4();
+    void decode_VString5();
+    void decode_BString();
+
+    void oid_equal();
+    void oid_copy();    
+    
+    void ostring_equal();
+    void ostring_copy();    
+  protected:
+    asn1::streams::ber m_ctx;
+    asn1::codecBER     m_codec;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-ber-primary-types.cpp b/tests/UNIT-TEST-ber-primary-types.cpp
new file mode 100644 (file)
index 0000000..be6fba6
--- /dev/null
@@ -0,0 +1,575 @@
+#include <cppunit/config/SourcePrefix.h>
+#include <string.h>
+#include <fstream>
+#define MAIN
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-ber-primary-types.h"
+#include "TEST_basic_types.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_primary_types);
+
+using namespace TEST_basic_types;
+
+void TC_TEST_primary_types::setUp()
+{
+
+}
+
+void TC_TEST_primary_types::encode_Null()
+{
+  const unsigned char seq[] = {0x05,0x00};
+  asn1::streams::ber ctx;
+  asn1::streams::ber ber;
+  Null i;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,2);
+  CPPUNIT_ASSERT(result==0);
+
+  ber.encode_null(i);
+  result = memcmp(ber.buffer(),seq,2);
+  CPPUNIT_ASSERT(result==0);
+  ber.reset();
+  m_codec.encode(ber,i);
+  result = memcmp(ber.buffer(),seq,2);
+  CPPUNIT_ASSERT(result==0);
+  
+  CPPUNIT_ASSERT(asn1::ok==m_codec.decode(ber,i));
+}
+
+void TC_TEST_primary_types::encode_Boolean()
+{
+  asn1::streams::ber ctx;
+  BOOLEAN b;
+  b = false;
+  b.encode(ctx);
+  ctx.reset();
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,b)) && ( b == false) );
+  ctx.reset(); b = true;
+  b.encode(ctx);
+  ctx.reset();
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,b)) && ( b == true) );
+
+}
+
+void TC_TEST_primary_types::encode_Integer()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x06};
+  const unsigned char iUByte[] = {0x02,0x01,0xFF}; // 255
+  const unsigned char iSByte[] = {0x02,0x01,0x81}; // -127
+  const unsigned char iUWord[] = {0x02,0x02,0xFF,0xFF};
+  const unsigned char iSWord[] = {0x02,0x01,0xFF,0xFF};
+  INTEGER i;
+  UInt64 ui64;
+  i = 6;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+  /* Check 255 */
+  i = 255 ; ctx.reset();
+  m_codec.encode(ctx,i); ctx.reset(); i = 0;
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,i)) && ( i == 255) );
+  /* Check 65536 */
+  i = 65536 ; ctx.reset();
+  m_codec.encode(ctx,i); ctx.reset(); i = 0;
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,i)) && ( i == 65536) );
+  /* Check Unsiged Dword*/
+  ui64 = 4294967295UL ; ctx.reset();
+  m_codec.encode(ctx,ui64); ctx.reset(); ui64 = 0UL;
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,ui64)) && ( ui64 == 4294967295UL) );
+  /* Check a negative value */
+  i = -127 ; ctx.reset();
+  m_codec.encode(ctx,i); ctx.reset(); i = 0;
+  CPPUNIT_ASSERT(( asn1::ok == m_codec.decode(ctx,i)) && ( i == -127) );
+}
+void TC_TEST_primary_types::encode_Integer1()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0xb4};
+  INTEGER i;
+  i = 180;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Integer127()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x7F};
+  INTEGER i;
+  i = 127;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Integer128()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0x80};
+  INTEGER i;
+  i = 128;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Integer256()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x01,0x00};
+  INTEGER i;
+  i = 256;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Integer_n128()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x80,0x34};
+  INTEGER i;
+  i = -128;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,3);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Integer_n129()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0xFF,0x7F};
+  INTEGER i;
+  i = -129;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+
+void TC_TEST_primary_types::encode_Integer235()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0xeb};
+  INTEGER i;
+  i = 235;
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Real()
+{
+  asn1::streams::ber ctx;
+  REAL i;
+  i = 4.5;
+  i.encode(ctx);
+  CPPUNIT_ASSERT(1==0);  
+}
+
+void TC_TEST_primary_types::encode_BitString()
+{
+  asn1::streams::ber ctx;
+  BIT_STRING str;
+  str[0] = 0x10;
+  str.encode(ctx);
+}
+
+void TC_TEST_primary_types::encode_OctetString()
+{
+  asn1::streams::ber ctx;
+  OCTET_STRING s(std::string("Jones"));
+  s.encode(ctx);
+}
+
+void TC_TEST_primary_types::encode_UTF8String()
+{
+  const unsigned char seq[] = {0x0c,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  UTF8String s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+
+
+}
+
+void TC_TEST_primary_types::encode_PrintableString()
+{
+  const unsigned char seq[] = {0x13,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  PrintableString s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_TeletexString()
+{
+  const unsigned char seq[] = {0x14,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  TeletexString s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_VideotexString()
+{
+  const unsigned char seq[] = {0x15,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  VideotexString s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_IA5String()
+{
+  const unsigned char seq[] = {0x16,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  IA5String s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_GraphicString()
+{
+  const unsigned char seq[] = {0x19,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  GraphicString s( "Jones" );
+  ber.encode_string(s);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_GeneralString()
+{
+  const unsigned char seq[] = {0x1b,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  GeneralString s( "Jones" );
+  ber.encode_string(s);
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_UniversalString()
+{
+  const unsigned char seq[] = {0x1d,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  UniversalString s( "Jones" );
+  ber.encode_string(s);
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_BMPString()
+{
+  const unsigned char seq[] = {0x1e,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ber;
+  BMPString s( "Jones" );
+  ber.encode_string(s);
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_primary_types::encode_VisibleString()
+{
+  const unsigned char seq[] = {0x1a,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::streams::ber ctx;
+  asn1::streams::ber ber;
+  asn1::prim::types::String s("Jones");
+  VisibleString vs(s);
+  vs.encode(ctx);
+  
+  ber.encode_string(vs);
+  
+  int result = memcmp(ber.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+
+  result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+
+}
+
+
+void TC_TEST_primary_types::encode_NumericString()
+{
+  const unsigned char seq[] = {0x12,0x04,0x31,0x32,0x33,0x34};
+  asn1::streams::ber ctx;
+  asn1::streams::ber ber;
+  //std::string s("Jones");
+  NumericString vs("1234");
+  vs.encode(ctx);
+
+  ber.encode_string(vs);
+  
+  int result = memcmp(ber.buffer(),seq,6);
+  CPPUNIT_ASSERT(result==0);
+  
+  result = memcmp(ctx.buffer(),seq,6);
+  CPPUNIT_ASSERT(result==0);
+}
+
+void TC_TEST_primary_types::encode_Oid()
+{
+  long oi[] = {1,3,7}; 
+  const unsigned char seq[] = {0x06,0x02,0x2b,0x07};
+  // {1.3.128}
+  long oid128[] = {1,3,128};
+  const unsigned char seq128[] = {0x06,0x03,0x2b,0x81,0x00};
+  
+  long lid_1[] =  { 1, 3, 6, 1, 5, 5, 7};
+  // id_1;
+  asn1::streams::ber ctx;
+  OBJECT_IDENTIFIER_NG i ;
+  OBJECT_IDENTIFIER_NG i1 ;
+  i.from_arc(3,oi);
+  i.encode(ctx);
+  int result = memcmp(ctx.buffer(),seq,4);
+  CPPUNIT_ASSERT(result==0);
+  i1.from_arc(7,lid_1);
+  CPPUNIT_ASSERT(i != i1);
+  i.from_arc(3,oid128);
+  ctx.reset();
+  i.encode(ctx);
+  CPPUNIT_ASSERT_EQUAL(0,memcmp(ctx.buffer(),seq128,5));
+}
+// decoding ...
+//
+
+
+void TC_TEST_primary_types::decode_Null()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x05,0x00};
+  Null i;
+  memcpy(ctx.buffer(),seq,2);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(ctx.nb_read_bits()==16);
+}
+
+void TC_TEST_primary_types::decode_Boolean()
+{
+  asn1::streams::ber ctx;
+  BOOLEAN b;
+  const unsigned char seq[] = {0x01,0x01,0xFF};
+  memcpy(ctx.buffer(),seq,3);
+  b.decode(ctx);
+  CPPUNIT_ASSERT(ctx.nb_read_bits()==24);
+  CPPUNIT_ASSERT(b==true);
+}
+
+void TC_TEST_primary_types::decode_Integer()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x0a};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,3);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==10);
+}
+void TC_TEST_primary_types::decode_Integer1()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0xb4};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,4);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==180);
+}
+void TC_TEST_primary_types::decode_Integer127()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x7F,0x34};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,3);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==127);
+}
+void TC_TEST_primary_types::decode_Integer128()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0x80};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,4);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==128);
+}
+void TC_TEST_primary_types::decode_Integer256()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x01,0x00};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,4);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==256);
+}
+void TC_TEST_primary_types::decode_Integer_n128()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x01,0x80};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,3);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i== -128);
+}
+void TC_TEST_primary_types::decode_Integer_n129()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0xFF,0x7F};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,4);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i== -129);
+}
+
+void TC_TEST_primary_types::decode_Integer235()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x02,0x02,0x00,0xeb};
+  INTEGER i;
+  memcpy(ctx.buffer(),seq,4);
+  i.decode(ctx);
+  CPPUNIT_ASSERT(i==235);
+}
+
+
+void TC_TEST_primary_types::decode_Real()
+{
+  asn1::streams::ber ctx;
+  REAL i;
+  //i.encode(ctx);
+  CPPUNIT_ASSERT(1==0);
+}
+
+void TC_TEST_primary_types::decode_BitString()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x03,0x07,0x04,0x0a,0x3B,0x5F,0x29,0x1c,0xd0};
+  BIT_STRING str;
+  memcpy(ctx.buffer(),seq,9);
+  str.decode(ctx);
+  std::cout<<" t[0]="<<std::hex<<(unsigned short)str[0]<<" "<<std::dec;
+  std::cout<<" t[1]="<<std::hex<<(unsigned short)str[1]<<" "<<std::dec;
+  std::cout<<" t[2]="<<std::hex<<(unsigned short)str[2]<<" "<<std::dec;
+  std::cout<<" t[3]="<<std::hex<<(unsigned short)str[3]<<" "<<std::dec;
+  std::cout<<" t[4]="<<std::hex<<(unsigned short)str[4]<<" "<<std::dec;
+  std::cout<<" t[5]="<<std::hex<<(unsigned short)str[5]<<" "<<std::dec;
+  CPPUNIT_ASSERT(str[0]==0xcd);
+}
+
+void TC_TEST_primary_types::decode_OctetString()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x04,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  OCTET_STRING s;
+  
+  memcpy(ctx.buffer(),seq,7);
+  s.decode(ctx);
+  
+  CPPUNIT_ASSERT(std::string("Jones").compare(s.get_sys_value())==0);
+}
+void TC_TEST_primary_types::decode_UTF8String()
+{
+}
+
+void TC_TEST_primary_types::decode_PrintableString()
+{
+}
+
+void TC_TEST_primary_types::decode_TeletexString()
+{
+}
+
+void TC_TEST_primary_types::decode_VideotexString()
+{
+}
+
+void TC_TEST_primary_types::decode_IA5String()
+{
+}
+
+void TC_TEST_primary_types::decode_GraphicString()
+{
+}
+
+void TC_TEST_primary_types::decode_GeneralString()
+{
+}
+
+void TC_TEST_primary_types::decode_UniversalString()
+{
+}
+
+void TC_TEST_primary_types::decode_BMPString()
+{
+}
+
+
+void TC_TEST_primary_types::decode_VisibleString()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x1a,0x05,0x4a,0x6f,0x6e,0x65,0x73};
+  asn1::prim::types::String s("Jones");
+  asn1::prim::types::String s1;
+  VisibleString vs;
+  memcpy(ctx.buffer(),seq,7);
+  vs.decode(ctx);
+  s1 = vs.get_value();
+  int result = s1.get_value().compare(s.get_value());
+ // int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_primary_types::decode_NumericString()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x12,0x05,0x31,0x32,0x33,0x34,0x35};
+  NumericString vs;
+  memcpy(ctx.buffer(),seq,7);
+  vs.decode(ctx);
+  CPPUNIT_ASSERT(std::string("12345").compare(vs.get_sys_value())==0);
+}
+
+void TC_TEST_primary_types::decode_Oid()
+{
+  asn1::streams::ber ctx;
+  // { 2.100.}
+  const unsigned char seq[] = {0x06,0x03,0x81,0x34,0x03,0x65,0x73};
+  // {1.3.128}
+  const unsigned char seq128[] = {0x06,0x03,0x2b,0x81,0x00};
+  // { 1.3.36.3.3.1.2}
+  const unsigned char seq2[] = {0x06,0x06,0x2B,0x24,0x03,0x03,0x01,0x02};
+  OBJECT_IDENTIFIER i;
+  //
+  memcpy(ctx.buffer(),seq2,8);
+  i.decode(ctx);
+  asn1::prim::types::ObjectIdentifier::array_type a;
+  i.to_arc(a);
+  asn1::prim::types::ObjectIdentifier::iterator it = a.begin();
+  CPPUNIT_ASSERT((*it)== 1);
+  ++it;
+   CPPUNIT_ASSERT((*it)== 3);
+  // Check 128
+  ctx.reset();
+  memcpy(ctx.buffer(),seq128,5);
+  i.decode(ctx);
+  a.clear();
+  i.to_arc(a); it = a.begin(); ++it; ++it;
+  CPPUNIT_ASSERT_EQUAL((long)128,*it);
+}
diff --git a/tests/UNIT-TEST-ber-primary-types.h b/tests/UNIT-TEST-ber-primary-types.h
new file mode 100644 (file)
index 0000000..df361bf
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "rtasn1/asn1.h"
+
+
+class TC_TEST_primary_types : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_primary_types );
+    CPPUNIT_TEST(encode_Null);   
+    CPPUNIT_TEST(encode_Boolean);   
+    CPPUNIT_TEST(encode_Integer);
+    CPPUNIT_TEST(encode_Integer1);
+    CPPUNIT_TEST(encode_Integer127);
+    CPPUNIT_TEST(encode_Integer128);
+    CPPUNIT_TEST(encode_Integer256);
+    CPPUNIT_TEST(encode_Integer_n128);
+    CPPUNIT_TEST(encode_Integer_n129);
+    CPPUNIT_TEST(encode_Integer235);
+    CPPUNIT_TEST(encode_Real);   
+    CPPUNIT_TEST(encode_BitString);
+    CPPUNIT_TEST(encode_OctetString);
+    CPPUNIT_TEST(encode_UTF8String);
+    CPPUNIT_TEST(encode_NumericString);
+    CPPUNIT_TEST(encode_PrintableString);
+    CPPUNIT_TEST(encode_TeletexString);
+    CPPUNIT_TEST(encode_VideotexString);
+    CPPUNIT_TEST(encode_IA5String);
+    CPPUNIT_TEST(encode_GraphicString);
+    CPPUNIT_TEST(encode_VisibleString);            
+    CPPUNIT_TEST(encode_GeneralString);            
+    CPPUNIT_TEST(encode_UniversalString);            
+    CPPUNIT_TEST(encode_BMPString);            
+    CPPUNIT_TEST(encode_Oid);            
+    CPPUNIT_TEST(decode_Null);   
+    CPPUNIT_TEST(decode_Boolean);   
+    CPPUNIT_TEST(decode_Integer);
+    CPPUNIT_TEST(decode_Integer1);
+    CPPUNIT_TEST(decode_Integer127);
+    CPPUNIT_TEST(decode_Integer128);
+    CPPUNIT_TEST(decode_Integer256);
+    CPPUNIT_TEST(decode_Integer_n128);
+    CPPUNIT_TEST(decode_Integer_n129);
+    CPPUNIT_TEST(decode_Integer235);
+    CPPUNIT_TEST(decode_Real);   
+    CPPUNIT_TEST(decode_BitString);
+    CPPUNIT_TEST(decode_OctetString);
+
+    CPPUNIT_TEST(decode_UTF8String);
+    CPPUNIT_TEST(decode_NumericString);
+    CPPUNIT_TEST(decode_PrintableString);
+    CPPUNIT_TEST(decode_TeletexString);
+    CPPUNIT_TEST(decode_VideotexString);
+    CPPUNIT_TEST(decode_IA5String);
+    CPPUNIT_TEST(decode_GraphicString);
+    CPPUNIT_TEST(decode_VisibleString);            
+    CPPUNIT_TEST(decode_GeneralString);            
+    CPPUNIT_TEST(decode_UniversalString);            
+    CPPUNIT_TEST(decode_BMPString);            
+    CPPUNIT_TEST(decode_Oid);            
+    CPPUNIT_TEST_SUITE_END();
+/**
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,12,OCTET_STRING> UTF8String;
+
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,18,OCTET_STRING> NumericString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,19,OCTET_STRING> PrintableString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,20,OCTET_STRING> TeletexString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,21,OCTET_STRING> VideotexString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,22,OCTET_STRING> IA5String;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,25,OCTET_STRING> GraphicString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,26,OCTET_STRING> VisibleString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,27,OCTET_STRING> GeneralString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,29,OCTET_STRING> UniversalString;
+    typedef asn1::types::EXPLICIT<asn1::types::UNIVERSAL,30,OCTET_STRING> BMPString;
+*/ 
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_Null();
+    void encode_Boolean();
+    void encode_Integer();
+    void encode_Integer1();
+    void encode_Integer127();
+    void encode_Integer128();
+    void encode_Integer256();
+    void encode_Integer_n128();
+    void encode_Integer_n129();
+    void encode_Integer235();
+    void encode_Real();
+    void encode_BitString();
+    void encode_OctetString();
+    void encode_UTF8String();
+    void encode_NumericString();
+    void encode_PrintableString();
+    void encode_TeletexString();
+    void encode_VideotexString();
+    void encode_IA5String();
+    void encode_GraphicString();
+    void encode_VisibleString();
+    void encode_GeneralString();
+    void encode_UniversalString();
+    void encode_BMPString();
+    void encode_Oid();
+                  
+    //decoging program
+    void decode_Null();
+    void decode_Boolean();
+    void decode_Integer();
+    void decode_Integer1();
+    void decode_Integer127();
+    void decode_Integer128();
+    void decode_Integer256();
+    void decode_Integer_n128();
+    void decode_Integer_n129();
+    void decode_Integer235();
+    void decode_Real();
+    void decode_BitString();
+    void decode_OctetString();
+    void decode_UTF8String();
+    void decode_NumericString();
+    void decode_PrintableString();
+    void decode_TeletexString();
+    void decode_VideotexString();
+    void decode_IA5String();
+    void decode_GraphicString();
+    void decode_VisibleString();
+    void decode_GeneralString();
+    void decode_UniversalString();
+    void decode_BMPString();
+    void decode_Oid();
+  protected:
+    asn1::codecBER m_codec;
+    asn1::streams::ber m_ctx;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-private-types-choice.cpp b/tests/UNIT-TEST-private-types-choice.cpp
new file mode 100644 (file)
index 0000000..56e38c5
--- /dev/null
@@ -0,0 +1,175 @@
+#include <cppunit/config/SourcePrefix.h>
+#include <string.h>
+#include <fstream>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-private-types-choice.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_private_types_choice);
+
+using namespace TEST_private_types_choice;
+
+void TC_TEST_private_types_choice::setUp()
+{
+
+}
+
+void TC_TEST_private_types_choice::encode_len()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x05,0x02,0x01,0x0b,0x05,0x00};
+  TEST_Sequence S;
+  S.device.set_tag(asn1::tag(asn1::types::UNIVERSAL,2));
+  S.device.get_len() = 11;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+
+
+void TC_TEST_private_types_choice::encode_number()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x05,0x80,0x01,0x0d,0x05,0x00};
+  TEST_Sequence S;
+  //TEST_Sequence::device_t dev(TEST_Sequence::device_t::typeof_number,asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+  TEST_Sequence_device dev(TEST_Sequence_device::typeof_number,asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+  dev.get_number()    = 13;
+  S.device.set_tag(asn1::tag(asn1::types::CONTEXT_SPECIFIC,0));
+  S.device  = dev;
+  //S.codec(ctx,S,asn1::CODEC_ENCODE);
+  S.encode(ctx);
+  
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result==0);
+}
+/**
+TEST-ChoiceCplx ::= CHOICE {
+  cseq SEQUENCE {
+    s1 INTEGER
+  },
+  cset SET {
+    s2 BOOLEAN,
+    s21 BOOLEAN
+  },
+  cchoice CHOICE {
+    s3 OCTET STRING,
+    s31 NULL
+  }
+}
+*/
+void TC_TEST_private_types_choice::encode_cseq()
+{
+  const unsigned char seq[] = {0xa1,0x05,0x30,0x03,0x02,0x01,0x09};
+  asn1::streams::ber ctx;
+  TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cseq);
+  
+  c.get_cseq().s1 = 9; 
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+
+  int result = memcmp(ctx.buffer(),seq,7);
+  CPPUNIT_ASSERT(result == 0);
+}
+
+void TC_TEST_private_types_choice::encode_cset()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0xa1,0x08,0x31,0x06,0x01,0x01,0xFF,0x01,0x1,0x00};
+  //TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cset,asn1::tag(0,TEST_ChoiceCplx::typeof_cset));
+  TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cset,asn1::tag(0,17));
+  
+  c.get_cset().s2 = true; 
+  c.get_cset().s21 = false; 
+  //c.encode(ctx);
+  //c.codec(ctx,c,asn1::CODEC_ENCODE);
+  c.encode(ctx);
+
+  int result = memcmp(ctx.buffer(),seq,10);
+  CPPUNIT_ASSERT(result == 0);
+}
+
+void TC_TEST_private_types_choice::encode_cchoice()
+{
+  const unsigned char seq[] = {0xa1,0x04,0xa2,0x02,0x81,0x00};
+  //const unsigned char seq[] = {0xa1,0x02,0x81,0x00,0x00,0x00};
+  asn1::streams::ber ctx;
+  TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cchoice,asn1::tag(2,2));
+  
+  c.get_cchoice().get_s31(); 
+  c.encode(ctx);
+
+  int result = memcmp(ctx.buffer(),seq,6);
+  CPPUNIT_ASSERT(result == 0);
+}
+// decoding 
+
+void TC_TEST_private_types_choice::decode_len()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x05,0x02,0x01,0x0d,0x05,0x00};
+  TEST_Sequence S;
+  memcpy(ctx.buffer(),seq,7);
+  //S.codec(ctx,S,asn1::CODEC_DECODE);
+  S.decode(ctx);
+  
+  CPPUNIT_ASSERT(S.device.get_len()==13);
+}
+void TC_TEST_private_types_choice::decode_number()
+{
+  asn1::streams::ber ctx;
+  const unsigned char seq[] = {0x30,0x05,0x80,0x01,0x0d,0x05,0x00};
+  TEST_Sequence S;
+  memcpy(ctx.buffer(),seq,7);
+  //S.codec(ctx,S,asn1::CODEC_DECODE);
+  S.decode(ctx);
+  
+  CPPUNIT_ASSERT(S.device.get_number()==13);
+}
+
+void TC_TEST_private_types_choice::decode_cseq()
+{
+  const unsigned char seq[] = {0xa1,0x05,0x30,0x03,0x02,0x01,0x08};
+  asn1::streams::ber ctx;
+  TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cseq);
+  
+  memcpy(ctx.buffer(),seq,7);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+
+  CPPUNIT_ASSERT(c.get_cseq().s1 == 8);
+}
+void TC_TEST_private_types_choice::decode_cset()
+{
+  const unsigned char seq[] = {0xa1,0x08,0x31,0x06,0x01,0x01,0xFF,0x01,0x1,0x00};
+  asn1::streams::ber ctx;
+  TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cseq);
+  
+  memcpy(ctx.buffer(),seq,10);
+  //c.codec(ctx,c,asn1::CODEC_DECODE);
+  c.decode(ctx);
+
+  CPPUNIT_ASSERT( (c.get_cset().s21 == false) && (c.get_cset().s2 == true));
+}
+
+/**
+ *
+ */ 
+void TC_TEST_private_types_choice::decode_cchoice()
+{
+  const unsigned char seq[] = {0xa1,0x04,0xa2,0x02,0x81,0x00};
+  asn1::streams::ber ctx;
+  //TEST_ChoiceCplx   c(TEST_ChoiceCplx::typeof_cchoice,asn1::tag(0,5));
+  TEST_ChoiceCplx   c;
+  
+  memcpy(ctx.buffer(),seq,6);
+  int res = c.decode(ctx);
+  std::cerr<<"Kind:"<<c.get_kind()<<std::endl;
+  CPPUNIT_ASSERT(res == asn1::ok);
+  CPPUNIT_ASSERT(c.get_kind() == TEST_ChoiceCplx::typeof_cchoice);
+  //CPPUNIT_ASSERT(0);
+}
diff --git a/tests/UNIT-TEST-private-types-choice.h b/tests/UNIT-TEST-private-types-choice.h
new file mode 100644 (file)
index 0000000..65add71
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "TEST_private_types_choice.h"
+
+
+class TC_TEST_private_types_choice : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_private_types_choice );
+    CPPUNIT_TEST(encode_len);
+    CPPUNIT_TEST(encode_number);
+    CPPUNIT_TEST(encode_cseq);
+    CPPUNIT_TEST(encode_cset);
+    CPPUNIT_TEST(encode_cchoice);
+    CPPUNIT_TEST(decode_len);
+    CPPUNIT_TEST(decode_number);
+    CPPUNIT_TEST(decode_cseq);
+    CPPUNIT_TEST(decode_cset);
+    CPPUNIT_TEST(decode_cchoice);
+   
+
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_len();
+    void encode_number();
+    void encode_cseq();
+    void encode_cset();
+    void encode_cchoice();
+    
+    void decode_len();
+    void decode_number();
+    void decode_cseq();
+    void decode_cset();
+    void decode_cchoice();
+  protected:
+    asn1::codecBER m_codec;
+    asn1::streams::ber m_ctx;
+};
+  
+#endif
diff --git a/tests/UNIT-TEST-type-parameter.h b/tests/UNIT-TEST-type-parameter.h
new file mode 100644 (file)
index 0000000..8d993f5
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TESTCASE_SIMPLETYPE_H
+#define TESTCASE_SIMPLETYPE_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "UNIT-TEST-type-parameter.h"
+
+class TC_TEST_type_parameter : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( TC_TEST_type_parameter );
+    CPPUNIT_TEST(encode_call);   
+    CPPUNIT_TEST(decode_call);
+    CPPUNIT_TEST_SUITE_END();
+
+    public:
+    void setUp();
+    protected:
+
+    void encode_call();
+    void decode_call();
+  protected:
+    asn1::codecBER m_codec;
+    asn1::streams::ber m_ctx;
+};
+  
+#endif
diff --git a/tests/main_asn1_type_sizes.cpp b/tests/main_asn1_type_sizes.cpp
new file mode 100644 (file)
index 0000000..302f272
--- /dev/null
@@ -0,0 +1,62 @@
+#include <string.h>
+#include <fstream>
+//#define MAIN
+#include "rtasn1/asn1_config.h"
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+#include "rtasn1/asn1_codec_jer.h"
+
+void test_codec()
+{
+  asn1::INTEGER i;
+  asn1::streams::ber ctx(500);
+  asn1::codecBER cb;
+
+  cb.encode(ctx,i);
+
+}
+
+void test_codec_jer()
+{
+  asn1::INTEGER i;
+  asn1::streams::jer ctx(500);
+  asn1::codecJER cb;
+
+  cb.encode(ctx,i);
+
+}
+
+
+/**
+ * The aim of this program is to display the 
+ * size of all basic objects.
+ */ 
+int main(int argc,char **argv)
+{
+  asn1::Set<asn1::INTEGER> setof;
+  asn1::Seq<asn1::OCTET_STRING> seqof;
+
+  std::cout<<"Asn1p runtime library, size of type"<<std::endl;
+#define ASN1_TYPE_CLS(PrimType,TagType,TagNum,Asn1Type) \
+  std::cout<<"size of asn1::"<<#Asn1Type<<"\t  = "<<sizeof(asn1::Asn1Type)<<std::endl;
+#include "rtasn1/asn1_types.inc"
+  
+  std::cout<<"size of SET_OF(INTEGER)\t  = "<<sizeof(setof)<<std::endl;
+  std::cout<<"size of SEQ_OF(OCTET_STRING)\t  = "<<sizeof(seqof)<<std::endl;
+  test_codec();
+  test_codec_jer();
+  std::cout<<"size of prim Boolean \t  = "<<sizeof(asn1::prim::types::Boolean)<<std::endl;
+  std::cout<<"size of prim Integer \t  = "<<sizeof(asn1::prim::types::Integer)<<std::endl;
+  std::cout<<"size of prim UInt8 \t  = "<<sizeof(asn1::prim::types::UInt8)<<std::endl;
+  std::cout<<"size of prim UInt16 \t  = "<<sizeof(asn1::prim::types::UInt16)<<std::endl;
+  std::cout<<"size of prim UInt32 \t  = "<<sizeof(asn1::prim::types::UInt32)<<std::endl;
+  std::cout<<"size of prim UInt64 \t  = "<<sizeof(asn1::prim::types::UInt64)<<std::endl;
+  std::cout<<"size of prim String  \t  = "<<sizeof(asn1::prim::types::String)<<std::endl;
+  std::cout<<"size of prim BitString  \t  = "<<sizeof(asn1::prim::types::BitString)<<std::endl;
+}
+
+/**
+ * vim: et sw=2 ts=3:
+ */ 
diff --git a/tests/main_test.cpp b/tests/main_test.cpp
new file mode 100644 (file)
index 0000000..5145701
--- /dev/null
@@ -0,0 +1,50 @@
+#include <iostream>
+
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+
+
+#include "rtasn1/asn1_config.h"
+#include "rtasn1/asn1.h"
+#include "rtasn1/asn1_codec.h"
+#include "rtasn1/asn1_codec_ber.h"
+
+int main(int argc,char **argv)
+{
+  asn1::types::debug_level = 9;
+  
+  if ( (argc > 1) && strcmp(argv[1],"-r") == 0) 
+    asn1::types::debug_level = 1;
+
+  // Create the event manager and test controller
+  CPPUNIT_NS::TestResult controller;
+
+  // Add a listener that colllects test result
+  CPPUNIT_NS::TestResultCollector result;
+  controller.addListener( &result );        
+
+  // Add a listener that print dots as test run.
+  CPPUNIT_NS::BriefTestProgressListener progress;
+  controller.addListener( &progress );      
+
+  // Add the top suite to the test runner
+  CPPUNIT_NS::TestRunner runner;
+  runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
+  runner.run( controller );
+
+  // Print test in a compiler compatible format.
+  CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() );
+  outputter.write(); 
+
+  // Test xml output
+  std::ofstream xmlFile("Asn1TestResults.xml");
+  CPPUNIT_NS::XmlOutputter xmlOutput(&result,xmlFile);
+  xmlOutput.write();
+  return result.wasSuccessful() ? 0 : 1;
+
+}
diff --git a/tests/modules.txt b/tests/modules.txt
new file mode 100644 (file)
index 0000000..1095751
--- /dev/null
@@ -0,0 +1,11 @@
+TEST-basic-types
+TEST-basic-types-integer-limits
+TEST-basic-types-implicit
+TEST-basic-types-explicit
+TEST-basic-types-sequence
+TEST-basic-types-set
+TEST-basic-types-enum
+TEST-basic-types-choice
+TEST-private-types-choice
+TEST-basic-types-tagged
+TEST-basic-types-optional
diff --git a/tests/poc-codec.h b/tests/poc-codec.h
new file mode 100644 (file)
index 0000000..d8f0dbc
--- /dev/null
@@ -0,0 +1,22 @@
+
+
+/**
+ * Should be initiliazed with an array of functions
+ *   constrains, 
+ *   each type of the project has is pair of encoding/decoding function
+ */ 
+class  PocCodecBER : public asn1::codecBER<PocCodecBER>
+{
+  public:
+    PocCodecBER();
+
+    void encode(asn1::context &ctx,const long l);
+
+    long &decode(asn1::context &ctx,long &l);
+
+
+};
+
+/*
+ * vim: et sw=2 ts=2 list:
+ */
diff --git a/tests/poc-codec.hpp b/tests/poc-codec.hpp
new file mode 100644 (file)
index 0000000..96173af
--- /dev/null
@@ -0,0 +1,4 @@
+
+template <>
+asn1::codecBER<long>::encode(asn1::context &ctx,long l)
+{ static_cast<PocCodecBER *>(this)->encode(ctx,l); };
diff --git a/tests/source.asn1 b/tests/source.asn1
new file mode 100644 (file)
index 0000000..6e4d23b
--- /dev/null
@@ -0,0 +1,872 @@
+--
+-- Test-basic-types
+--
+TEST-basic-types {iso(1) identified-organization(3)  1}
+DEFINITIONS ::=
+BEGIN
+Test::=INTEGER
+TestI ::=INTEGER { one(1), two(2) ,tree(3)}
+TestOid ::= OBJECT IDENTIFIER
+O-String::= OCTET STRING(SIZE(1..32))
+
+B-String ::= BIT STRING {
+  default(0),
+  one(1),
+  two(2)
+}
+
+VString1 ::= VisibleString
+
+VString2 ::= [APPLICATION 3] IMPLICIT VString1
+
+VString3 ::= [2] EXPLICIT VString2
+
+VString4 ::= [APPLICATION 7] IMPLICIT VString3
+
+VString5 ::= [2] IMPLICIT VString2
+
+id-1 OBJECT IDENTIFIER ::= { 1 3 6 1 5 5 7}
+id-2 OBJECT IDENTIFIER ::= { 1 3 }
+id-3 OBJECT IDENTIFIER ::= { 1 2 }
+END
+
+--
+-- Test-basic-types-integer-limits
+--
+TEST-basic-types-integer-limits {iso(1) identified-organization(3)  1 2}
+DEFINITIONS ::=
+BEGIN
+
+SByte ::=INTEGER(-127..128)
+UByte ::=INTEGER(0..255)
+
+SWord ::= INTEGER(-32767..3232768)
+UWord ::= INTEGER(0..65535)
+
+SDWord ::= INTEGER(-2147483647..2147483648)
+UDWord ::= INTEGER(0..4294967295)
+
+END
+
+
+--
+-- Test-basic-types-explicit
+--
+TEST-basic-values {iso(1) identified-organization(3) 2 }
+DEFINITIONS ::=
+BEGIN
+
+vi  INTEGER   ::= 8
+
+nul IA5String ::= { 0, 0}
+
+soh IA5String ::= { 0, 1}
+
+latinCapitalLetterA BMPString ::= {0,0,0,65}
+
+OpCode ::= CHOICE
+{
+       local   INTEGER,
+       global  OBJECT IDENTIFIER
+}
+
+gsr1 OpCode ::= local : 5
+
+gsr2 OpCode ::= global : { iso(1)  3}
+END
+
+--
+-- Test-basic-types-explicit
+--
+TEST-basic-types-explicit {iso(1) identified-organization(3) 3}
+DEFINITIONS ::=
+BEGIN
+Test::= [APPLICATION 0] EXPLICIT INTEGER
+
+O-String::= [APPLICATION 1] EXPLICIT OCTET STRING(SIZE(1..32))
+
+B-String::= [APPLICATION 2] EXPLICIT BIT STRING(SIZE(1..16))
+
+Bool-String::= [APPLICATION 3] EXPLICIT BOOLEAN 
+END
+
+--
+-- Test-basic-types-implicit
+--
+TEST-basic-types-implicit {iso(1) identified-organization(3) 4}
+DEFINITIONS ::=
+BEGIN
+Test::=INTEGER
+
+Ti ::= [8] IMPLICIT INTEGER
+
+TEST-Seq::= SEQUENCE {
+  t1 INTEGER OPTIONAL,
+  t2 [0] IMPLICIT INTEGER OPTIONAL,
+  t3 [1] IMPLICIT INTEGER OPTIONAL
+}
+
+TEST-Choice::= CHOICE {
+  c1 [0] IMPLICIT INTEGER ,
+  c2 [1] IMPLICIT INTEGER ,
+  c3 [2] IMPLICIT INTEGER 
+}
+
+
+
+TEST-IntegerList ::= SEQUENCE OF INTEGER
+
+NumberDigits    ::= IA5String
+DeviceInfo      ::= NULL
+AgentState      ::= NULL
+CSTAPrivateData ::= BOOLEAN
+ForwardingType  ::= ENUMERATED {
+  un(1)
+  , deux(2)
+}
+
+ListForwardParameters ::= SEQUENCE OF SEQUENCE 
+       {               forwardingType  ForwardingType,
+                       forwardDN       NumberDigits }
+
+QueryDeviceInformation  ::= CHOICE {
+    msgWaitingOn        [0] IMPLICIT BOOLEAN,
+    doNotDisturbOn      [1] IMPLICIT BOOLEAN,
+    forward         [2] IMPLICIT ListForwardParameters,
+    lastDialedNumber    [3] IMPLICIT NumberDigits,
+    deviceInfo      [4] IMPLICIT DeviceInfo,
+    agentState      [5] IMPLICIT AgentState }
+
+QueryDeviceResult   ::= --snacc isPdu:"TRUE" -- CHOICE
+     {   deviceInformation  [0] QueryDeviceInformation,
+         [1] SEQUENCE
+         {   deviceInfoBis   QueryDeviceInformation,
+             extensions  CSTAPrivateData OPTIONAL } }
+
+
+
+
+END
+
+--
+-- Test-basic-types-choice
+--
+TEST-basic-types-choice {iso(1) identified-organization(3) 5}
+DEFINITIONS ::=
+BEGIN
+
+IP4Address ::= SEQUENCE 
+{
+  address OCTET STRING (SIZE(4)),
+  portNumber INTEGER(0..65535) OPTIONAL
+}
+
+TEST-Choice::=CHOICE {
+  device INTEGER,
+  name   IA5String,
+  b1     BOOLEAN,
+  ip4    IP4Address
+}
+
+TEST-Choice1::=CHOICE {
+  device [0] IMPLICIT INTEGER,
+  i2   [1] IMPLICIT INTEGER,
+  b1   [2] IMPLICIT BOOLEAN,
+  bs1  [3] IMPLICIT BIT STRING,
+  os1  [4] IMPLICIT OCTET STRING,
+  nul  [5] IMPLICIT NULL
+}
+-- application level tags
+ChoiceA ::= CHOICE {
+  i     [APPLICATION 0] IMPLICIT INTEGER,
+  b     [APPLICATION 1] IMPLICIT BOOLEAN
+}
+-- context specific tags
+ChoiceB ::= CHOICE {
+ ib     [1] IMPLICIT INTEGER,
+ bb     [2] IMPLICIT BOOLEAN
+}
+-- Simulate csta acse apdu...
+ChoiceChoice ::= CHOICE {
+  -- Tag is required for ChoiceA because the underlying type is a Choice as 
+  -- well. 
+  choicea [0] ChoiceA,
+  choiceb [1] ChoiceB
+}
+
+
+END
+
+--
+-- Test-basic-types-sequence
+--
+TEST-basic-types-sequence {iso(1) identified-organization(3)  6}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Sequence::= SEQUENCE {
+  device INTEGER,
+  name   NULL
+}
+
+TEST-SeqSeq ::= SEQUENCE {
+  ss1 SEQUENCE {
+    ss2 IA5String
+  }
+}
+
+TEST-Implicit-Sequence ::= SEQUENCE {
+  s1 [0] IMPLICIT IA5String,
+  s2 [1] IMPLICIT IA5String OPTIONAL,
+  s3 [2] IMPLICIT IA5String OPTIONAL
+
+}
+
+TEST-IntegerList ::= SEQUENCE OF INTEGER
+
+TEST-SeqOfSeq ::= SEQUENCE OF SEQUENCE {
+  device INTEGER,
+  present BOOLEAN
+}
+
+TEST-CplxSeq ::= SEQUENCE {
+  s1 VisibleString(SIZE(0..64)),
+  i1 [0] IMPLICIT SEQUENCE OF INTEGER OPTIONAL,
+  i2 [1] IMPLICIT SEQUENCE OF SEQUENCE {
+    b1 BOOLEAN,
+    n  NULL
+  }
+}
+
+TEST-CplxSeqNm ::= SEQUENCE {
+  i2 [1] IMPLICIT SEQUENCE OF nmSeq SEQUENCE {
+    b1 BOOLEAN,
+    n  NULL
+  }
+}
+
+END
+
+--
+-- TEST-basic-types-set
+--
+TEST-basic-types-set {iso(1) identified-organization(3) 7}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Set::= SET {
+  device INTEGER,
+  name   NULL
+}
+
+TEST-Set1 ::= SET {
+  device INTEGER,
+  devices SEQUENCE OF INTEGER,
+  deviceSet SET OF INTEGER
+}
+
+Int ::= INTEGER
+
+OString ::= OCTET STRING (SIZE(0..64))
+
+TEST-SetOfOString ::= SET OF OString
+
+TEST-SetOfInt ::= SET SIZE(1..4) OF Int
+
+END
+
+--
+-- TEST-basic-types-enum
+--
+TEST-basic-types-enum {iso(1) identified-organization(3) 8}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Enum::= ENUMERATED {
+  null(0),
+  one(1),
+  two(2)
+}
+
+TEST-SeqEnum ::= SEQUENCE {
+  enum1 TEST-Enum,
+  enum2 ENUMERATED { no(0), yes(1)},
+  enum3 ENUMERATED {true } OPTIONAL
+}
+
+Presence ::= ENUMERATED {optional,conditional,mandatory}
+
+Criticality::= ENUMERATED {reject,ignore,notify}
+END
+
+--
+-- TEST-basic-types-tagged
+--
+TEST-basic-types-tagged {iso(1) identified-organization(3) 9}
+DEFINITIONS ::=
+BEGIN
+
+Int ::= [APPLICATION 3] INTEGER
+IntELT72 ::= [APPLICATION 72] INTEGER (0..255)
+
+SeqE ::= [APPLICATION 2] EXPLICIT SEQUENCE {
+  one INTEGER,
+  nu NULL
+}
+
+SeqE1 ::= [APPLICATION 4] EXPLICIT SEQUENCE {
+  one Int,
+  nu NULL
+}
+
+IntI      ::= [APPLICATION 21] IMPLICIT INTEGER
+OctI     ::= [APPLICATION 22] IMPLICIT OCTET STRING
+IntILT62  ::= [APPLICATION 62] IMPLICIT INTEGER
+IntILT432 ::= [APPLICATION 432] IMPLICIT INTEGER
+
+
+SeqI ::= [APPLICATION 5] IMPLICIT SEQUENCE {
+  one IntI,
+  two OctI
+}
+
+SeqI1 ::= [APPLICATION 6] IMPLICIT SEQUENCE {
+  one Int,
+  nu NULL
+}
+
+SeqP ::= [APPLICATION 5] SEQUENCE {
+  seq [APPLICATION 10] SEQUENCE {
+     one INTEGER,
+     two BOOLEAN
+    },
+  nu NULL
+}
+
+
+
+Choice ::= [APPLICATION 4] CHOICE {
+  one [APPLICATION 0] IMPLICIT INTEGER,
+  nu NULL,
+  seqe SeqE
+}
+
+InSeq ::=  SEQUENCE {
+  one [0 ] INTEGER,
+  nu Int
+}
+
+TSetE ::= [APPLICATION 4] SET {
+  one INTEGER,
+  nu NULL
+}
+
+TSetI ::= [APPLICATION 6] IMPLICIT SET {
+  one INTEGER,
+  nu NULL
+}
+END
+
+
+
+--
+-- TEST-private-types-choice
+--
+TEST-private-types-choice {iso(1) identified-organization(3) 10}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Sequence::= SEQUENCE {
+  device CHOICE {
+    len INTEGER,
+    number [0] IMPLICIT INTEGER
+  },
+  name   NULL
+}
+
+TEST-SeqChoiceSeq ::= SEQUENCE {
+  v CHOICE {
+    s1 [0] IMPLICIT SEQUENCE {
+      name VisibleString,
+      n    NULL
+    },
+    s2 [1] IMPLICIT SEQUENCE {
+      n NULL,
+      nm VisibleString
+    }
+    -- Does not  work yet !!!!
+     ,
+     s3 [2] IMPLICIT SEQUENCE OF SEQUENCE {
+      p  GraphicString,
+      pm VisibleString OPTIONAL
+     }
+  }
+}
+
+--
+-- Working on generator to support this case !!!!
+--  Main issue with CHOICE SET. SET does not handle private structure
+--   missing scope
+
+TEST-ChoiceCplx ::= [1] CHOICE {
+  cseq SEQUENCE {
+    s1 INTEGER
+  },
+  cset  SET {
+    s2 BOOLEAN,
+    s21 BOOLEAN
+  },
+  cchoice  [2] CHOICE {
+    s3  [0] IMPLICIT OCTET STRING,
+    s31 [1] IMPLICIT NULL
+  }
+}
+
+
+END
+
+TEST-private-types-seq-of {iso(1) identified-organization(3) 11}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Sequence::= SEQUENCE {
+  device CHOICE {
+    len INTEGER,
+    number [0] IMPLICIT INTEGER
+  },
+  name   NULL
+}
+
+TEST-SeqChoiceSeq ::= SEQUENCE {
+  v CHOICE {
+    s1 [0] IMPLICIT SEQUENCE {
+      name VisibleString,
+      n    NULL
+    },
+    s2 [1] IMPLICIT SET OF CHOICE {
+      n NULL,
+      nm VisibleString
+    },
+    s3 [2] IMPLICIT SEQUENCE OF SEQUENCE {
+      p  GraphicString,
+      pm VisibleString OPTIONAL
+    }
+  }
+
+
+}
+END
+
+
+--
+-- TEST-basic-types-selection
+--
+TEST-basic-types-selection {iso(1) identified-organization(3) 12}
+DEFINITIONS ::=
+BEGIN
+
+TEST-Selection::= SEQUENCE {
+ --   len nm < TEST-SeqSelectReference ,
+    number [0] IMPLICIT INTEGER,
+  name   NULL
+}
+
+TEST-SeqSelectReference ::= CHOICE {
+  name VisibleString,
+  n    NULL,
+  s2 [1] BOOLEAN,
+  nm VisibleString
+}
+
+
+END
+
+--
+-- Test optionnal
+--
+TEST-basic-types-optional {iso(1) identified-organization(3) 13}
+DEFINITIONS ::=
+BEGIN
+
+Request ::= SEQUENCE {
+  requestID    INTEGER,
+  extention Extension OPTIONAL
+}
+
+ReqDefaultInt ::= SEQUENCE {
+  extID  INTEGER DEFAULT 2,
+  nul    NULL
+}
+
+ReqDefaultBool ::= SEQUENCE {
+  extID  BOOLEAN DEFAULT FALSE,
+  nul    NULL
+}
+-- Still bug
+ReqDefaultString ::= SEQUENCE {
+  extID  IA5String DEFAULT "james" ,
+  nul    NULL
+}
+
+ReqOptInt ::= SEQUENCE {
+  extID  INTEGER OPTIONAL,
+  nul    NULL
+}
+
+ReqOptBool ::= SEQUENCE {
+  extID  BOOLEAN OPTIONAL,
+  nul    NULL
+}
+
+ReqOptString ::= SEQUENCE {
+  extID  IA5String OPTIONAL,
+  nul    NULL
+}
+
+Extension ::= SEQUENCE {
+  extID  INTEGER DEFAULT 2,
+  data   OCTET STRING,
+  bits   BitSTR DEFAULT {bit1} ,
+  boolean BOOLEAN   DEFAULT TRUE,
+  toto  BitSTR DEFAULT {}
+}
+
+BitSTR ::= BIT STRING {
+  nul(0),
+  bit1(1),
+  bit2(2),
+  bit3(3)
+}
+
+END
+
+
+--
+--- H323 needs parameterized support
+--
+
+--
+-- Simple parametered type
+--
+TEST-type-parameter {iso(1) identified-organization(3) 14}
+DEFINITIONS ::=
+BEGIN
+
+ Aa ::= INTEGER
+--TEST-PSeq{MyType}::= SEQUENCE {
+-- 2017/07/27 Still issue with otag. Suspect that 
+-- reparenting does not work with parameterized types
+-- in this case.
+--  device CHOICE {
+--    type [0] MyType,
+--    number [1] IMPLICIT INTEGER
+--  },
+--  name   NULL,
+--  simpler MyType
+-- }
+
+-- Call::=TEST-PSeq{INTEGER}
+MyType ::= INTEGER
+END
+
+--
+-- H323 actively uses extensible structures
+--
+TEST-type-extensible {iso(1) identified-organization(3) 15}
+DEFINITIONS ::=
+BEGIN
+
+TEST-ExtendSeq ::= SEQUENCE {
+  device SEQUENCE {
+    type MyType,
+    number [0] IMPLICIT INTEGER,
+    ...
+  },
+  name   NULL,
+  ...
+}
+
+TEST-ExtendSeqE ::= SEQUENCE {
+  device SEQUENCE {
+    typeE MyType,
+    numberE [0] IMPLICIT INTEGER,
+    ...
+  },
+  nameE   NULL,
+  ... ,
+  add1 BOOLEAN,
+  add2 INTEGER,
+  ...
+}
+
+
+TEST-ExtendChoice ::= CHOICE {
+  c1 INTEGER,
+  c2 SEQUENCE {
+    a1 INTEGER,
+    b1 BOOLEAN
+  },
+  ...
+}
+
+
+MyType ::= INTEGER
+END
+
+--
+-- basic type value constraint
+--
+TEST-basic-type-value-constraint {iso(1) identified-organization(3) 16}
+DEFINITIONS ::=
+BEGIN
+
+ Aa ::= INTEGER
+ Bb::= [1] INTEGER
+ Cc::= [2] INTEGER (0..6,...)
+ Dd::= [2] INTEGER (0..6,...,7)
+ Ee::= INTEGER (7..20)
+ Ff::= INTEGER {red(0), white(1), blue(2), green(3), purple(4)}
+ -- Value Assignements !!!! 
+ a Aa ::= 3
+ b Bb::= 4
+ c Cc::= 5
+ d Dd::= 6
+ e Ee::= 7
+ f Ff::= green
+ g INTEGER ::= 10
+
+W ::= SEQUENCE {w1 Aa DEFAULT a}
+x Aa ::= a
+Y ::= Aa(1..a)
+
+END
+
+--
+-- CSTA needs ROS supports
+--
+
+--
+-- Ros definition 
+--
+TEST-rose {iso (1) id(2)}
+DEFINITIONS ::=
+BEGIN
+
+OpCode ::= CHOICE
+{
+       local   INTEGER,
+       global  OBJECT IDENTIFIER
+}
+
+InvokeId ::= CHOICE {present  INTEGER,
+                     absent   NULL
+}
+
+ERROR ::= CLASS
+{
+  &ErrorCode
+}
+
+OPERATION ::= CLASS
+{
+       &ArgumentType                                                           OPTIONAL,
+       &argumentTypeOptional   BOOLEAN                 OPTIONAL,
+       &returnResult                           BOOLEAN                 DEFAULT TRUE,
+       &ResultType                                                                     OPTIONAL,
+       &resultTypeOptional             BOOLEAN                 OPTIONAL,
+       &Errors                                         ERROR           OPTIONAL,
+       &Linked                                         OPERATION       OPTIONAL,
+       &alwaysReturns                          BOOLEAN                 DEFAULT TRUE,
+       &operationCode                          OpCode                  UNIQUE OPTIONAL
+}
+WITH SYNTAX
+{
+       [ARGUMENT                       &ArgumentType  [OPTIONAL        &argumentTypeOptional]]
+       [RESULT                 &ResultType    [OPTIONAL        &resultTypeOptional]]
+       [RETURN RESULT          &returnResult]
+       [ERRORS                 &Errors]
+       [LINKED                 &Linked]
+       [ALWAYS RESPONDS        &alwaysReturns]
+       [CODE                   &operationCode]
+}
+
+ROS {InvokeId : IdSet , OPERATION : Invokable} ::= CHOICE {
+  invoke    [1]  Invoke{{IdSet},{Invokable}}
+}
+
+Invoke{InvokeId:InvokeIdSet,OPERATION:Operations,INTEGER:IntegerSet,INTEGER:integerValue} ::= SEQUENCE
+{
+  invokeId InvokeId(InvokeIdSet),
+  invokeI  INTEGER(IntegerSet),
+  opcode OPERATION.&operationCode
+}
+END
+
+
+--
+-- Test ROS operation
+--
+TEST-rose-operation {iso (1) id(2) 2}
+DEFINITIONS ::=
+BEGIN
+--IMPORTS OPERATION FROM Remote-Operations-Information-Objects {iso (1)};
+
+InvokeId ::= CHOICE {present  INTEGER,
+                     absent   NULL
+}
+
+Code ::= CHOICE
+{
+       local   INTEGER,
+       global  OBJECT IDENTIFIER
+}
+
+OpCode ::= CHOICE
+{
+       local   INTEGER,
+       global  OBJECT IDENTIFIER
+}
+
+Priority ::= INTEGER
+
+OPERATION ::= CLASS
+{
+       &ArgumentType                                                           OPTIONAL,
+       &argumentTypeOptional   BOOLEAN                 OPTIONAL,
+       &returnResult                           BOOLEAN                 DEFAULT TRUE,
+       &ResultType                                                                     OPTIONAL,
+       &resultTypeOptional             BOOLEAN                 OPTIONAL,
+       &Errors                                         ERROR           OPTIONAL,
+       &Linked                                         OPERATION       OPTIONAL,
+       &alwaysReturns                          BOOLEAN                 DEFAULT TRUE,
+       &operationCode                          OpCode                  UNIQUE OPTIONAL
+}
+WITH SYNTAX
+{
+       [ARGUMENT                       &ArgumentType  [OPTIONAL        &argumentTypeOptional]]
+       [RESULT                 &ResultType    [OPTIONAL        &resultTypeOptional]]
+       [RETURN RESULT          &returnResult]
+       [ERRORS                 &Errors]
+       [LINKED                 &Linked]
+       [ALWAYS RESPONDS        &alwaysReturns]
+       [CODE                   &operationCode]
+}
+ERROR ::= CLASS
+{
+       &ParameterType          OPTIONAL,
+       &parameterTypeOptional  BOOLEAN OPTIONAL,
+       &ErrorPriority          Priority OPTIONAL,
+       &errorCode              Code UNIQUE OPTIONAL
+}
+WITH SYNTAX
+{
+       [PARAMETER              &ParameterType  [OPTIONAL       &parameterTypeOptional]]
+       [PRIORITY                       &ErrorPriority]
+       [CODE                   &errorCode]
+}
+
+
+Invoke{InvokeId:InvokeIdSet,OPERATION:Operations,INTEGER:IntegerSet,INTEGER:integerValue} ::= SEQUENCE
+{
+  invokeId InvokeId(InvokeIdSet),
+  invokeI  INTEGER(IntegerSet),
+  opcode OPERATION.&operationCode
+}
+
+eventReport OPERATION ::= 
+{
+  ARGUMENT EventReportArgument
+  ALWAYS RESPONDS FALSE
+  CODE local:12
+}
+
+makeCall OPERATION ::= 
+{
+  ARGUMENT MakeCallArgument
+  RESULT   MakeCallResult
+  ERRORS   {failures}
+  CODE local:13
+}
+
+
+EventReportArgument ::= SEQUENCE  {
+  test INTEGER,
+  spec BOOLEAN
+}
+
+MakeCallArgument ::= SEQUENCE {
+  deviceID INTEGER
+}
+
+MakeCallResult ::= SEQUENCE {
+  ok BOOLEAN OPTIONAL
+}
+
+failures ERROR ::= {
+  PARAMETER LocalFailures
+  CODE local:1
+}
+
+LocalFailures ::=CHOICE {
+  num INTEGER
+}
+END
+
+--
+-- Test ValueSet
+--
+TEST-value-set {iso (1) id(2) 3}
+DEFINITIONS ::=
+BEGIN
+IMPORTS OPERATION FROM Remote-Operations-Information-Objects {iso (1) 2 2};
+
+ValueSet INTEGER ::= { 1 | 2 | 3 }
+
+ObjectValueSet OPERATION ::= { op1 | op2 | op3 }
+
+
+END
+
+
+--
+-- Test Container
+--
+TEST-container {iso (1) id(2) 4}
+DEFINITIONS ::=
+BEGIN
+IMPORTS OPERATION FROM Remote-Operations-Information-Objects {iso (1) 2 2};
+
+Counter ::= INTEGER(0..65535)
+
+TEST-CALL ::= CLASS {
+  &id    Counter UNIQUE,
+  &Value
+} WITH SYNTAX {
+  ID    &id
+  TYPE  &Value
+}
+
+ValueSet INTEGER ::= { 1 | 2 | 3 }
+
+MySeq ::= SEQUENCE {
+   is INTEGER,
+  vals Proto-Container { {ObjectValueSet } },
+  -- vals Proto-Container ( { {ObjectValueSet } }),
+  ...
+}
+
+
+ObjectValueSet TEST-CALL ::= { {ID 1 TYPE INTEGER}| {ID 2 TYPE BOOLEAN} | { ID 3 TYPE Counter} }
+
+Proto-Container {TEST-CALL : CallSet } ::= SEQUENCE OF Proto-Field {{CallSet}}
+
+Proto-Field { TEST-CALL : CallSet } ::= SEQUENCE{
+  id        TEST-CALL.&id ({CallSet}),
+  value     TEST-CALL.&Value({CallSet}{@id})
+}
+
+END
+
+