using std::cout; using std::cerr; using std::endl; using std::to_string; #ifndef __CPP__INCLUDED__RPerl__DataStructure__Array_cpp #define __CPP__INCLUDED__RPerl__DataStructure__Array_cpp 0.007_000 #include <RPerl/DataStructure/Array.h> // -> NULL (relies on <vector> being included via Inline::CPP's AUTO_INCLUDE config option) /* * NEED FIX, CORRELATION #rp002: bug, possibly in Inline, causing inability to declare 3rd count_FOO argument to T_PACKEDARRAY; * temporarily fixed by changing typemap to set char** to T_PACKED; * may need Inline to add declaration of count_FOO to PREINIT section of auto-generated XS code * * eval_FOO.c: In function ‘void XS_main_XS_unpack_charPtrPtr(PerlInterpreter*, CV*)’: * eval_FOO.c:1322:36: error: ‘count_charPtrPtr’ was not declared in this scope */ // [[[ TYPE-CHECKING ]]] // [[[ TYPE-CHECKING ]]] // [[[ TYPE-CHECKING ]]] // DEV NOTE: for() loops are statements not expressions, so they can't be embedded in ternary operators, and thus this type-checking must be done with subroutines instead of macros void integer_arrayref_CHECK(SV* possible_integer_arrayref) { // DEV NOTE: the following two if() statements are functionally equivalent to the arrayref_CHECK() macro, but with integer-specific error codes if ( not( SvOK(possible_integer_arrayref) ) ) { croak( "\nERROR EIVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref value expected but undefined/null value found,\ncroaking" ); } if ( not( SvAROKp(possible_integer_arrayref) ) ) { croak( "\nERROR EIVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref value expected but non-arrayref value found,\ncroaking" ); } AV* possible_integer_array; integer possible_integer_array_length; integer i; SV** possible_integer_array_element; possible_integer_array = (AV*)SvRV(possible_integer_arrayref); possible_integer_array_length = av_len(possible_integer_array) + 1; for (i = 0; i < possible_integer_array_length; ++i) // incrementing iteration { possible_integer_array_element = av_fetch(possible_integer_array, i, 0); // DEV NOTE: the following two if() statements are functionally equivalent to the integer_CHECK() macro & subroutine, but with array-specific error codes if (not(SvOK(*possible_integer_array_element))) { croak("\nERROR EIVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref element value expected but undefined/null value found at index %"INTEGER",\ncroaking", i); } if (not(SvIOKp(*possible_integer_array_element))) { croak("\nERROR EIVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref element value expected but non-integer value found at index %"INTEGER",\ncroaking", i); } } } void integer_arrayref_CHECKTRACE(SV* possible_integer_arrayref, const char* variable_name, const char* subroutine_name) { if ( not( SvOK(possible_integer_arrayref) ) ) { croak( "\nERROR EIVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } if ( not( SvAROKp(possible_integer_arrayref) ) ) { croak( "\nERROR EIVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref value expected but non-arrayref value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } AV* possible_integer_array; integer possible_integer_array_length; integer i; SV** possible_integer_array_element; possible_integer_array = (AV*)SvRV(possible_integer_arrayref); possible_integer_array_length = av_len(possible_integer_array) + 1; for (i = 0; i < possible_integer_array_length; ++i) // incrementing iteration { possible_integer_array_element = av_fetch(possible_integer_array, i, 0); if (not(SvOK(*possible_integer_array_element))) { croak("\nERROR EIVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref element value expected but undefined/null value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } if (not(SvIOKp(*possible_integer_array_element))) { croak("\nERROR EIVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\ninteger_arrayref element value expected but non-integer value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } } } void number_arrayref_CHECK(SV* possible_number_arrayref) { if ( not( SvOK(possible_number_arrayref) ) ) { croak( "\nERROR ENVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but undefined/null value found,\ncroaking" ); } if ( not( SvAROKp(possible_number_arrayref) ) ) { croak( "\nERROR ENVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but non-arrayref value found,\ncroaking" ); } AV* possible_number_array; integer possible_number_array_length; integer i; SV** possible_number_array_element; possible_number_array = (AV*)SvRV(possible_number_arrayref); possible_number_array_length = av_len(possible_number_array) + 1; for (i = 0; i < possible_number_array_length; ++i) // incrementing iteration { possible_number_array_element = av_fetch(possible_number_array, i, 0); if (not(SvOK(*possible_number_array_element))) { croak("\nERROR ENVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref element value expected but undefined/null value found at index %"INTEGER",\ncroaking", i); } if (not(SvNOKp(*possible_number_array_element) || SvIOKp(*possible_number_array_element))) { croak("\nERROR ENVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref element value expected but non-number value found at index %"INTEGER",\ncroaking", i); } } } void number_arrayref_CHECKTRACE(SV* possible_number_arrayref, const char* variable_name, const char* subroutine_name) { if ( not( SvOK(possible_number_arrayref) ) ) { croak( "\nERROR ENVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } if ( not( SvAROKp(possible_number_arrayref) ) ) { croak( "\nERROR ENVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref value expected but non-arrayref value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } AV* possible_number_array; integer possible_number_array_length; integer i; SV** possible_number_array_element; possible_number_array = (AV*)SvRV(possible_number_arrayref); possible_number_array_length = av_len(possible_number_array) + 1; for (i = 0; i < possible_number_array_length; ++i) // incrementing iteration { possible_number_array_element = av_fetch(possible_number_array, i, 0); if (not(SvOK(*possible_number_array_element))) { croak("\nERROR ENVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref element value expected but undefined/null value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } if (not(SvNOKp(*possible_number_array_element) || SvIOKp(*possible_number_array_element))) { croak("\nERROR ENVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nnumber_arrayref element value expected but non-number value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } } } void string_arrayref_CHECK(SV* possible_string_arrayref) { if ( not( SvOK(possible_string_arrayref) ) ) { croak( "\nERROR EPVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref value expected but undefined/null value found,\ncroaking" ); } if ( not( SvAROKp(possible_string_arrayref) ) ) { croak( "\nERROR EPVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref value expected but non-arrayref value found,\ncroaking" ); } AV* possible_string_array; integer possible_string_array_length; integer i; SV** possible_string_array_element; possible_string_array = (AV*)SvRV(possible_string_arrayref); possible_string_array_length = av_len(possible_string_array) + 1; for (i = 0; i < possible_string_array_length; ++i) // incrementing iteration { possible_string_array_element = av_fetch(possible_string_array, i, 0); if (not(SvOK(*possible_string_array_element))) { croak("\nERROR EPVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref element value expected but undefined/null value found at index %"INTEGER",\ncroaking", i); } if (not(SvPOKp(*possible_string_array_element))) { croak("\nERROR EPVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref element value expected but non-string value found at index %"INTEGER",\ncroaking", i); } } } void string_arrayref_CHECKTRACE(SV* possible_string_arrayref, const char* variable_name, const char* subroutine_name) { if ( not( SvOK(possible_string_arrayref) ) ) { croak( "\nERROR EPVAVRV00, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref value expected but undefined/null value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } if ( not( SvAROKp(possible_string_arrayref) ) ) { croak( "\nERROR EPVAVRV01, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref value expected but non-arrayref value found,\nin variable %s from subroutine %s,\ncroaking", variable_name, subroutine_name ); } AV* possible_string_array; integer possible_string_array_length; integer i; SV** possible_string_array_element; possible_string_array = (AV*)SvRV(possible_string_arrayref); possible_string_array_length = av_len(possible_string_array) + 1; for (i = 0; i < possible_string_array_length; ++i) // incrementing iteration { possible_string_array_element = av_fetch(possible_string_array, i, 0); if (not(SvOK(*possible_string_array_element))) { croak("\nERROR EPVAVRV02, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref element value expected but undefined/null value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } if (not(SvPOKp(*possible_string_array_element))) { croak("\nERROR EPVAVRV03, TYPE-CHECKING MISMATCH, CPPOPS_PERLTYPES & CPPOPS_CPPTYPES:\nstring_arrayref element value expected but non-string value found at index %"INTEGER",\nin variable %s from subroutine %s,\ncroaking", i, variable_name, subroutine_name); } } } // [[[ TYPEMAP PACK/UNPACK FOR __CPP__TYPES ]]] // [[[ TYPEMAP PACK/UNPACK FOR __CPP__TYPES ]]] // [[[ TYPEMAP PACK/UNPACK FOR __CPP__TYPES ]]] # ifdef __CPP__TYPES // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing IVs))) to (C++ std::vector of integers) integer_arrayref XS_unpack_integer_arrayref(SV* input_avref) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_integer_arrayref(), top of subroutine\n"); // integer_arrayref_CHECK(input_avref); integer_arrayref_CHECKTRACE(input_avref, "input_avref", "XS_unpack_integer_arrayref()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; integer_arrayref output_vector; input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_integer_arrayref(), have input_av_length = %"INTEGER"\n", input_av_length); // DEV NOTE: VECTOR ELEMENT ASSIGNMENT OPTION information is not specific to this subroutine or packing/unpacking // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: vector has programmer-provided const size or compiler-guessable size, // resize() ahead of time to allow l-value subscript notation output_vector.resize((size_t)input_av_length); // VECTOR ELEMENT ASSIGNMENT, OPTION C, PUSH, KNOWN SIZE: vector has programmer-provided const size or compiler-guessable size, // reserve() ahead of time to avoid memory reallocation(s) (aka change in vector capacity) during element copying in for() loop // output_vector.reserve((size_t)input_av_length); // VECTOR ELEMENT ASSIGNMENT, OPTION E, ITERATOR, KNOWN SIZE: // output_vector.reserve((size_t)input_av_length); // if incrementing iteration // output_vector.resize((size_t)input_av_length); // if decrementing iteration for (i = 0; i < input_av_length; ++i) // incrementing iteration // for (i = (input_av_length - 1); i >= 0; --i) // decrementing iteration { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); // DEV NOTE: integer type-checking already done as part of integer_arrayref_CHECKTRACE() // integer_CHECK(*input_av_element); // integer_CHECKTRACE(*input_av_element, (char*)((string)"*input_av_element at index " + to_string(i)).c_str(), "XS_unpack_integer_hashref()"); // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: l-value subscript notation with no further resize(); utilizes i in assignment output_vector[i] = SvIV(*input_av_element); // VECTOR ELEMENT ASSIGNMENT, OPTION B, SUBSCRIPT, UNKNOWN SIZE: unpredictable value of i and thus unpredictable vector size, // call resize() every time we use l-value subscript; utilizes i in assignment // VECTOR_RESIZE_NOSHRINK(output_vector, (i + 1)); output_vector[i] = SvIV(*input_av_element); // VECTOR ELEMENT ASSIGNMENT, OPTIONS C & D, PUSH, KNOWN & UNKNOWN SIZE: push_back() calls resize(); does not utilize i in assignment; // only works for incrementing iteration!!! will reverse list order for decrementing iteration, there is no push_front() method // output_vector.push_back(SvIV(*input_av_element)); // VECTOR ELEMENT ASSIGNMENT, OPTION E, ITERATOR, KNOWN SIZE: utilizes i in assignment // output_vector.insert((i + output_vector.begin()), SvIV(*input_av_element)); // if incrementing iteration // output_vector.erase(i + output_vector.begin()); output_vector.insert((i + output_vector.begin()), SvIV(*input_av_element)); // if decrementing iteration // VECTOR ELEMENT ASSIGNMENT, OPTION F, ITERATOR, UNKNOWN SIZE: unpredictable value of i and thus unpredictable vector size, // call resize() every time we use insert(); utilizes i in assignment // VECTOR_RESIZE_NOSHRINK(output_vector, (i + 1)); output_vector.erase(i + output_vector.begin()); output_vector.insert((i + output_vector.begin()), SvIV(*input_av_element)); } // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_integer_arrayref(), after for() loop, have output_vector.size() = %"INTEGER"\n", output_vector.size()); // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_integer_arrayref(), bottom of subroutine\n"); return(output_vector); } // convert from (C++ std::vector of integers) to (Perl SV containing RV to (Perl AV of (Perl SVs containing IVs))) void XS_pack_integer_arrayref(SV* output_avref, integer_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_integer_arrayref(), top of subroutine\n"); AV* output_av = newAV(); // initialize output array to empty integer input_vector_length = input_vector.size(); integer i; SV* temp_sv_pointer; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_integer_arrayref(), have input_vector_length = %"INTEGER"\n", input_vector_length); if (input_vector_length > 0) { for (i = 0; i < input_vector_length; ++i) { av_push(output_av, newSViv(input_vector[i])); } } // else warn("in CPPOPS_CPPTYPES XS_pack_integer_arrayref(), array was empty, returning empty array via newAV()"); temp_sv_pointer = newSVrv(output_avref, NULL); // upgrade output stack SV to an RV SvREFCNT_dec(temp_sv_pointer); // discard temporary pointer SvRV(output_avref) = (SV*)output_av; // make output stack RV pointer at our output AV // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_integer_arrayref(), bottom of subroutine\n"); } // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing NVs))) to (C++ std::vector of numbers) number_arrayref XS_unpack_number_arrayref(SV* input_avref) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_number_arrayref(), top of subroutine\n"); // number_arrayref_CHECK(input_avref); number_arrayref_CHECKTRACE(input_avref, "input_avref", "XS_unpack_number_arrayref()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; number_arrayref output_vector; input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_number_arrayref(), have input_av_length = %"INTEGER"\n", input_av_length); // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: vector has programmer-provided const size or compiler-guessable size, // resize() ahead of time to allow l-value subscript notation output_vector.resize((size_t)input_av_length); for (i = 0; i < input_av_length; ++i) // incrementing iteration { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: l-value subscript notation with no further resize(); utilizes i in assignment output_vector[i] = SvNV(*input_av_element); } // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_number_arrayref(), after for() loop, have output_vector.size() = %"INTEGER"\n", output_vector.size()); // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_number_arrayref(), bottom of subroutine\n"); return(output_vector); } // convert from (C++ std::vector of numbers) to (Perl SV containing RV to (Perl AV of (Perl SVs containing NVs))) void XS_pack_number_arrayref(SV* output_avref, number_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_number_arrayref(), top of subroutine\n"); AV* output_av = newAV(); // initialize output array to empty integer input_vector_length = input_vector.size(); integer i; SV* temp_sv_pointer; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_number_arrayref(), have input_vector_length = %"INTEGER"\n", input_vector_length); if (input_vector_length > 0) { for (i = 0; i < input_vector_length; ++i) { av_push(output_av, newSVnv(input_vector[i])); } } // else warn("in CPPOPS_CPPTYPES XS_pack_number_arrayref(), array was empty, returning empty array via newAV()"); temp_sv_pointer = newSVrv(output_avref, NULL); // upgrade output stack SV to an RV SvREFCNT_dec(temp_sv_pointer); // discard temporary pointer SvRV(output_avref) = (SV*)output_av; // make output stack RV pointer at our output AV // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_number_arrayref(), bottom of subroutine\n"); } // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing PVs))) to (C++ std::vector of std::strings) string_arrayref XS_unpack_string_arrayref(SV* input_avref) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_string_arrayref(), top of subroutine\n"); // string_arrayref_CHECK(input_avref); string_arrayref_CHECKTRACE(input_avref, "input_avref", "XS_unpack_string_arrayref()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; string_arrayref output_vector; input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_string_arrayref(), have input_av_length = %"INTEGER"\n", input_av_length); // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: vector has programmer-provided const size or compiler-guessable size, // resize() ahead of time to allow l-value subscript notation output_vector.resize((size_t)input_av_length); for (i = 0; i < input_av_length; ++i) // incrementing iteration { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); // VECTOR ELEMENT ASSIGNMENT, OPTION A, SUBSCRIPT, KNOWN SIZE: l-value subscript notation with no further resize(); utilizes i in assignment output_vector[i] = SvPV_nolen(*input_av_element); } // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_string_arrayref(), after for() loop, have output_vector.size() = %"INTEGER"\n", output_vector.size()); // fprintf(stderr, "in CPPOPS_CPPTYPES XS_unpack_string_arrayref(), bottom of subroutine\n"); return(output_vector); } // convert from (C++ std::vector of std::strings) to (Perl SV containing RV to (Perl AV of (Perl SVs containing PVs))) void XS_pack_string_arrayref(SV* output_avref, string_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_string_arrayref(), top of subroutine\n"); AV* output_av = newAV(); // initialize output array to empty integer input_vector_length = input_vector.size(); integer i; SV* temp_sv_pointer; // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_string_arrayref(), have input_vector_length = %"INTEGER"\n", input_vector_length); if (input_vector_length > 0) { for (i = 0; i < input_vector_length; ++i) { av_push(output_av, newSVpv(input_vector[i].data(), input_vector[i].size())); } } // else warn("in CPPOPS_CPPTYPES XS_pack_string_arrayref(), array was empty, returning empty array via newAV()"); temp_sv_pointer = newSVrv(output_avref, NULL); // upgrade output stack SV to an RV SvREFCNT_dec(temp_sv_pointer); // discard temporary pointer SvRV(output_avref) = (SV*)output_av; // make output stack RV pointer at our output AV // fprintf(stderr, "in CPPOPS_CPPTYPES XS_pack_string_arrayref(), bottom of subroutine\n"); } # endif // [[[ STRINGIFY ]]] // [[[ STRINGIFY ]]] // [[[ STRINGIFY ]]] # ifdef __PERL__TYPES // DEV NOTE: direct manipulation of the Perl Stack shown in /* block comments */ // TODO: use Perl stack manipulation to enable support for variable number of arguments, multiple return values, not setting var to retval in Perl, etc. // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing IVs))) to Perl-parsable (Perl SV containing PV) //void integer_arrayref_to_string(SV* input_avref) SV* integer_arrayref_to_string(SV* input_avref) { // Inline_Stack_Vars; //define Inline_Stack_Vars dXSARGS // from INLINE.h // dXSARGS; // define dXSARGS dSP; dAXMARK; dITEMS // from XSUB.h /* dSP; dAXMARK; */ // dITEMS; // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref_to_string(), top of subroutine\n"); // integer_arrayref_CHECK(input_avref); integer_arrayref_CHECKTRACE(input_avref, "input_avref", "integer_arrayref_to_string()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; SV* output_sv = newSV(0); boolean i_is_0 = 1; input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref_to_string(), have input_av_length = %"INTEGER"\n", input_av_length); sv_setpvn(output_sv, "[", 1); for (i = 0; i < input_av_length; ++i) { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); // DEV NOTE: integer type-checking already done as part of integer_arrayref_CHECKTRACE() // integer_CHECK(*input_av_element); // integer_CHECKTRACE(*input_av_element, (char*)((string)"*input_av_element at index " + to_string(i)).c_str(), "integer_hashref_to_string()"); if (i_is_0) { i_is_0 = 0; } else { sv_catpvn(output_sv, ", ", 2); } // sv_catpvf(output_sv, "%"INTEGER"", (integer)SvIV(*input_av_element)); // NO UNDERSCORES sv_catsv(output_sv, integer_to_string(*input_av_element)); // YES UNDERSCORES } sv_catpvn(output_sv, "]", 1); // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref_to_string(), after for() loop, have output_sv =\n%s\n", SvPV_nolen(output_sv)); // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref_to_string(), bottom of subroutine\n"); // Inline_Stack_Reset; //define Inline_Stack_Reset sp = mark // from INLINE.h /* sp = mark; */ // Inline_Stack_Push(sv_2mortal(output_sv)); //define Inline_Stack_Push(x) XPUSHs(x) // from INLINE.h /* XPUSHs(sv_2mortal(output_sv)); // mortalize because we created output_sv with newSV() in this function */ return(output_sv); // Inline_Stack_Done; //define Inline_Stack_Done PUTBACK // from INLINE.h // PUTBACK; // Inline_Stack_Return(1); //define Inline_Stack_Return(x) XSRETURN(x) // from INLINE.h // XSRETURN(1); } // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing NVs))) to Perl-parsable (Perl SV containing PV) SV* number_arrayref_to_string(SV* input_avref) { // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref_to_string(), top of subroutine\n"); // number_arrayref_CHECK(input_avref); number_arrayref_CHECKTRACE(input_avref, "input_avref", "number_arrayref_to_string()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; SV* output_sv = newSV(0); boolean i_is_0 = 1; ostringstream temp_stream; temp_stream.precision(std::numeric_limits<double>::digits10); input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref_to_string(), have input_av_length = %"INTEGER"\n", input_av_length); temp_stream << "["; // sv_setpvn(output_sv, "[", 1); for (i = 0; i < input_av_length; ++i) { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); if (i_is_0) { i_is_0 = 0; } else { temp_stream << ", "; } // if (i_is_0) { i_is_0 = 0; } else { sv_catpvn(output_sv, ", ", 2); } temp_stream << (string)SvPV_nolen(number_to_string(*input_av_element)); // sv_catpvf(output_sv, "%Lf", (number)SvNV(*input_av_element)); // NEED ANSWER: can we make fprintf(stderr, )-like "%Lf" act like ostringstream's precision? } temp_stream << "]"; sv_setpv(output_sv, (char *)(temp_stream.str().c_str())); // sv_catpvn(output_sv, "]", 1); // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref_to_string(), after for() loop, have output_sv =\n%s\n", SvPV_nolen(output_sv)); // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref_to_string(), bottom of subroutine\n"); return(output_sv); } // convert from (Perl SV containing RV to (Perl AV of (Perl SVs containing PVs))) to Perl-parsable (Perl SV containing PV) SV* string_arrayref_to_string(SV* input_avref) { // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref_to_string(), top of subroutine\n"); // string_arrayref_CHECK(input_avref); string_arrayref_CHECKTRACE(input_avref, "input_avref", "string_arrayref_to_string()"); AV* input_av; integer input_av_length; integer i; SV** input_av_element; string input_av_element_string; size_t input_av_element_string_pos; SV* output_sv = newSV(0); boolean i_is_0 = 1; // ostringstream temp_stream; input_av = (AV*)SvRV(input_avref); input_av_length = av_len(input_av) + 1; // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref_to_string(), have input_av_length = %"INTEGER"\n", input_av_length); // temp_stream << "["; sv_setpvn(output_sv, "[", 1); for (i = 0; i < input_av_length; ++i) { // utilizes i in element retrieval input_av_element = av_fetch(input_av, i, 0); // if (i_is_0) { i_is_0 = 0; } else { temp_stream << ", "; } if (i_is_0) { i_is_0 = 0; } else { sv_catpvn(output_sv, ", ", 2); } // escape all back-slash \ and single-quote ' characters with a back-slash \ character input_av_element_string = string(SvPV_nolen(*input_av_element)); input_av_element_string_pos = 0; while((input_av_element_string_pos = input_av_element_string.find("\\", input_av_element_string_pos)) != string::npos) { input_av_element_string.replace(input_av_element_string_pos, 1, "\\\\"); input_av_element_string_pos += 2; } input_av_element_string_pos = 0; while((input_av_element_string_pos = input_av_element_string.find("'", input_av_element_string_pos)) != string::npos) { input_av_element_string.replace(input_av_element_string_pos, 1, "\\'"); input_av_element_string_pos += 2; } // temp_stream << "'" << SvPV_nolen(*input_av_element) << "'"; // sv_catpvf(output_sv, "'%s'", SvPV_nolen(*input_av_element)); sv_catpvf(output_sv, "'%s'", input_av_element_string.c_str()); } // temp_stream << "]"; // sv_setpv(output_sv, (char *)(temp_stream.str().c_str())); sv_catpvn(output_sv, "]", 1); // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref_to_string(), after for() loop, have output_sv =\n%s\n", SvPV_nolen(output_sv)); // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref_to_string(), bottom of subroutine\n"); return(output_sv); } # elif defined __CPP__TYPES // convert from (C++ std::vector of integers) to Perl-parsable (C++ std::string) string integer_arrayref_to_string(integer_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref_to_string(), top of subroutine\n"); ostringstream output_stream; integer input_vector_length = input_vector.size(); integer i; integer input_vector_element; boolean i_is_0 = 1; // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref_to_string(), have input_vector_length = %"INTEGER"\n", input_vector_length); output_stream << '['; for (i = 0; i < input_vector_length; ++i) { // utilizes i in element retrieval input_vector_element = input_vector[i]; if (i_is_0) { i_is_0 = 0; } else { output_stream << ", "; } // output_stream << input_vector_element; // NO UNDERSCORES output_stream << integer_to_string(input_vector_element); // YES UNDERSCORES } output_stream << ']'; // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref_to_string(), after for() loop, have output_stream =\n%s\n", (char *)(output_stream.str().c_str())); // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref_to_string(), bottom of subroutine\n"); return(output_stream.str()); } // convert from (C++ std::vector of numbers) to Perl-parsable (C++ std::string) string number_arrayref_to_string(number_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES number_arrayref_to_string(), top of subroutine\n"); ostringstream output_stream; integer input_vector_length = input_vector.size(); integer i; number input_vector_element; boolean i_is_0 = 1; // fprintf(stderr, "in CPPOPS_CPPTYPES number_arrayref_to_string(), have input_vector_length = %"INTEGER"\n", input_vector_length); output_stream.precision(std::numeric_limits<double>::digits10); output_stream << '['; for (i = 0; i < input_vector_length; ++i) { // utilizes i in element retrieval input_vector_element = input_vector[i]; if (i_is_0) { i_is_0 = 0; } else { output_stream << ", "; } // output_stream << input_vector_element; output_stream << number_to_string(input_vector_element); } output_stream << ']'; // fprintf(stderr, "in CPPOPS_CPPTYPES number_arrayref_to_string(), after for() loop, have output_stream =\n%s\n", (char *)(output_stream.str().c_str())); // fprintf(stderr, "in CPPOPS_CPPTYPES number_arrayref_to_string(), bottom of subroutine\n"); return(output_stream.str()); } // convert from (C++ std::vector of std::strings) to Perl-parsable (C++ std::string) string string_arrayref_to_string(string_arrayref input_vector) { // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref_to_string(), top of subroutine\n"); // ostringstream output_stream; string output_string; integer input_vector_length = input_vector.size(); integer i; string input_vector_element; size_t input_vector_element_pos; boolean i_is_0 = 1; // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref_to_string(), have input_vector_length = %"INTEGER"\n", input_vector_length); // output_stream << '['; output_string = "["; for (i = 0; i < input_vector_length; ++i) { // utilizes i in element retrieval input_vector_element = input_vector[i]; if (i_is_0) { i_is_0 = 0; } else { output_string += ", "; } // escape all back-slash \ and single-quote ' characters with a back-slash \ character input_vector_element_pos = 0; while((input_vector_element_pos = input_vector_element.find("\\", input_vector_element_pos)) != string::npos) { input_vector_element.replace(input_vector_element_pos, 1, "\\\\"); input_vector_element_pos += 2; } input_vector_element_pos = 0; while((input_vector_element_pos = input_vector_element.find("'", input_vector_element_pos)) != string::npos) { input_vector_element.replace(input_vector_element_pos, 1, "\\'"); input_vector_element_pos += 2; } // output_stream << "'" << input_vector_element << "'"; output_string += "'" + input_vector_element + "'"; } // output_stream << ']'; output_string += "]"; // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref_to_string(), after for() loop, have output_stream =\n%s\n", (char *)(output_stream.str().c_str())); // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref_to_string(), after for() loop, have output_string =\n%s\n", output_string.c_str()); // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref_to_string(), bottom of subroutine\n"); // return(output_stream.str()); return(output_string); } # else Purposefully_die_from_a_compile-time_error,_due_to_neither___PERL__TYPES_nor___CPP__TYPES_being_defined.__We_need_to_define_exactly_one! # endif // [[[ TYPE TESTING ]]] // [[[ TYPE TESTING ]]] // [[[ TYPE TESTING ]]] # ifdef __PERL__TYPES // DEV NOTE: direct manipulation of the Perl Stack shown in /* block comments */ /*void integer_arrayref__typetest0(SV* lucky_integers) */ SV* integer_arrayref__typetest0(SV* lucky_integers) { /* dSP; */ /* SV* output_sv; */ // integer_arrayref_CHECK(lucky_integers); integer_arrayref_CHECKTRACE(lucky_integers, "lucky_integers", "integer_arrayref__typetest0()"); // AV* lucky_integers_deref = (AV*)SvRV(lucky_integers); // integer how_lucky = av_len(lucky_integers_deref) + 1; // integer i; // for (i = 0; i < how_lucky; ++i) // { // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref__typetest0(), have lucky integer %"INTEGER"/%"INTEGER" = %"INTEGER", BARBAT\n", i, (how_lucky - 1), (integer)SvIV(*av_fetch(lucky_integers_deref, i, 0))); // } // ENTER; // SAVETMPS; /* integer_arrayref_to_string(lucky_integers); */ /* output_sv = integer_arrayref_to_string(lucky_integers); */ // SPAGAIN; /* output_sv = POPs; */ // PUTBACK; // FREETMPS; // LEAVE; /* sv_catpv(output_sv, "BARBAT"); */ /* fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref__typetest0(), have output_sv = %s\n", SvPV_nolen(output_sv)); */ /* // SPAGAIN; // PUSHMARK(SP); XPUSHs(output_sv); // do not mortalize because we receive value for output_sv from outside this function // PUTBACK; */ // SvREFCNT_inc(output_sv); /* return(output_sv); // do not mortalize because we receive value for output_sv from outside this function */ return(newSVpvf("%s%s", SvPV_nolen(integer_arrayref_to_string(lucky_integers)), "CPPOPS_PERLTYPES")); } // DEV NOTE: direct manipulation of the Perl Stack shown in /* block comments */ /*void integer_arrayref__typetest1(integer my_size) */ SV* integer_arrayref__typetest1(SV* my_size) { /* dSP; dAXMARK; */ // integer_CHECK(my_size); integer_CHECKTRACE(my_size, "my_size", "integer_arrayref__typetest1()"); AV* output_av = newAV(); integer i; av_extend(output_av, (I32)(SvIV(my_size) - 1)); for (i = 0; i < SvIV(my_size); ++i) { av_store(output_av, (I32)i, newSViv(i * 5)); // fprintf(stderr, "in CPPOPS_PERLTYPES integer_arrayref__typetest1(), setting element %"INTEGER"/%"INTEGER" = %"INTEGER", BARBAT\n", i, (integer)(SvIV(my_size) - 1), (integer)SvIV(*av_fetch(output_av, (I32)i, 0))); } /* sp = mark; XPUSHs(sv_2mortal(newRV_noinc((SV*) output_av))); // do mortalize because we create output_av with newAV() in this function */ return(newRV_noinc((SV*) output_av)); } SV* number_arrayref__typetest0(SV* lucky_numbers) { // number_arrayref_CHECK(lucky_numbers); number_arrayref_CHECKTRACE(lucky_numbers, "lucky_numbers", "number_arrayref__typetest0()"); // AV* lucky_numbers_deref = (AV*)SvRV(lucky_numbers); // integer how_lucky = av_len(lucky_numbers_deref) + 1; // integer i; // for (i = 0; i < how_lucky; ++i) // { // number_CHECK(*av_fetch(lucky_numbers_deref, i, 0)); // number_CHECKTRACE(*av_fetch(lucky_numbers_deref, i, 0), (char*)((string)"*av_fetch(lucky_numbers_deref, i, 0) at index " + to_string(i)).c_str(), "number_arrayref__typetest0()"); // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref__typetest0(), have lucky number %"INTEGER"/%"INTEGER" = %Lf, BARBAT\n", i, (how_lucky - 1), (number)SvNV(*av_fetch(lucky_numbers_deref, i, 0))); // } return(newSVpvf("%s%s", SvPV_nolen(number_arrayref_to_string(lucky_numbers)), "CPPOPS_PERLTYPES")); } SV* number_arrayref__typetest1(SV* my_size) { // integer_CHECK(my_size); integer_CHECKTRACE(my_size, "my_size", "number_arrayref__typetest1()"); AV* output_av = newAV(); integer i; av_extend(output_av, (I32)(SvIV(my_size) - 1)); for (i = 0; i < SvIV(my_size); ++i) { av_store(output_av, (I32)i, newSVnv(i * 5.123456789)); // fprintf(stderr, "in CPPOPS_PERLTYPES number_arrayref__typetest1(), setting element %"INTEGER"/%"INTEGER" = %Lf, BARBAT\n", i, (integer)(SvIV(my_size) - 1), (number)SvNV(*av_fetch(output_av, (I32)i, 0))); } return(newRV_noinc((SV*) output_av)); } SV* string_arrayref__typetest0(SV* people) { // string_arrayref_CHECK(people); string_arrayref_CHECKTRACE(people, "people", "string_arrayref__typetest0()"); // AV* people_deref = (AV*)SvRV(people); // integer i; // for (i = 0; i < (av_len(people_deref) + 1); ++i) // { // string_CHECK(*av_fetch(people_deref, i, 0)); // string_CHECKTRACE(*av_fetch(people_deref, i, 0), (char*)((string)"*av_fetch(people_deref, i, 0) at index " + to_string(i)).c_str(), "string_arrayref__typetest0()"); // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref__typetest0(), have person %"INTEGER" = '%s', BARBAR\n", i, (char *)SvPV_nolen(*av_fetch(people_deref, i, 0))); // } return(newSVpvf("%s%s", SvPV_nolen(string_arrayref_to_string(people)), "CPPOPS_PERLTYPES")); } SV* string_arrayref__typetest1(SV* my_size) { // integer_CHECK(my_size); integer_CHECKTRACE(my_size, "my_size", "string_arrayref__typetest1()"); AV* people = newAV(); integer i; av_extend(people, (I32)(SvIV(my_size) - 1)); for (i = 0; i < SvIV(my_size); ++i) { av_store(people, (I32)i, newSVpvf("Jeffy Ten! %"INTEGER"/%"INTEGER" CPPOPS_PERLTYPES", i, (integer)(SvIV(my_size) - 1))); // fprintf(stderr, "in CPPOPS_PERLTYPES string_arrayref__typetest1(), bottom of for() loop, have i = %"INTEGER", (integer)(SvIV(my_size) - 1) = %"INTEGER", just set another Jeffy, BARBAR\n", i, (integer)(SvIV(my_size) - 1)); } return(newRV_noinc((SV*) people)); } # elif defined __CPP__TYPES string integer_arrayref__typetest0(integer_arrayref lucky_integers) { integer how_lucky = lucky_integers.size(); integer i; // for (i = 0; i < how_lucky; ++i) // { // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref__typetest0(), have lucky number %"INTEGER"/%"INTEGER" = %"INTEGER", BARBAT\n", i, (how_lucky - 1), lucky_integers[i]); // } return(integer_arrayref_to_string(lucky_integers) + "CPPOPS_CPPTYPES"); } integer_arrayref integer_arrayref__typetest1(integer my_size) { integer_arrayref new_vec(my_size); integer i; for (i = 0; i < my_size; ++i) { new_vec[i] = i * 5; // fprintf(stderr, "in CPPOPS_CPPTYPES integer_arrayref__typetest1(), setting element %"INTEGER"/%"INTEGER" = %"INTEGER", BARBAT\n", i, (my_size - 1), new_vec[i]); } return(new_vec); } string number_arrayref__typetest0(number_arrayref lucky_numbers) { integer how_lucky = lucky_numbers.size(); integer i; // for (i = 0; i < how_lucky; ++i) // { // fprintf(stderr, "in CPPOPS_CPPTYPES number_arrayref__typetest0(), have lucky number %"INTEGER"/%"INTEGER" = %Lf, BARBAZ\n", i, (how_lucky - 1), lucky_numbers[i]); // } return(number_arrayref_to_string(lucky_numbers) + "CPPOPS_CPPTYPES"); } number_arrayref number_arrayref__typetest1(integer my_size) { number_arrayref new_vec(my_size); integer i; for (i = 0; i < my_size; ++i) { new_vec[i] = i * 5.123456789; // fprintf(stderr, "in CPPOPS_CPPTYPES typetest__number_in__number_arrayref_out(), setting element %"INTEGER"/%"INTEGER" = %Lf, BARBAZ\n", i, (my_size - 1), new_vec[i]); } return(new_vec); } //string string_arrayref__typetest0(string_arrayref people) { integer i; for (i = 0; i < people.size(); ++i) { fprintf(stderr, "in CPPOPS_CPPTYPES fprintf(stderr, ) string_arrayref__typetest0(), have person %"INTEGER" = '%s', BARBAR\n", i, people[i].c_str()); } return(string_arrayref_to_string(people) + "BARBAR"); } string string_arrayref__typetest0(string_arrayref people) { integer i; // for (i = 0; i < people.size(); ++i) // { // cout << "in CPPOPS_CPPTYPES string_arrayref__typetest0(), have person " << i << " = '" << people[i] << "', BARBAR\n"; // } return(string_arrayref_to_string(people) + "CPPOPS_CPPTYPES"); } string_arrayref string_arrayref__typetest1(integer my_size) { string_arrayref people; integer i; people.resize((size_t)my_size); for (i = 0; i < my_size; ++i) { people[i] = "Jeffy Ten! " + std::to_string(i) + "/" + std::to_string(my_size - 1) + " CPPOPS_CPPTYPES"; // fprintf(stderr, "in CPPOPS_CPPTYPES string_arrayref__typetest1(), bottom of for() loop, have i = %"INTEGER", (my_size - 1) = %"INTEGER", just set another Jeffy, BARBAR\n", i, (my_size - 1)); } return(people); } # endif #endif