# Testing proper handling of char* c-strings as params and rv's given C++
# code that correctly copies the values.

# By copying cstring input param we become impervious to string pointers
# passed as params becoming invalidated if input string falls out of scope.

use strict;
use warnings;

use Test::More tests => 2;

use Inline CPP => 'DATA';

# Test verifying classes that store member c-string.

note( 'Subtest: Testing object instantiated by Class->new() syntax.' );

subtest 'Object instantiated with Class->new() syntax.' => sub {
    plan tests => 4;

    my $obj1 = CStrTest->new( 'Honest' );
    my $obj2 = CStrTest->new( 'Lucky'  );
    isa_ok( $obj1, 'CStrTest', '$obj1' );
    isa_ok( $obj2, 'CStrTest', '$obj2' );
    is( $obj1->get_name, 'Honest', "get_name on \$obj1 (Honest)" );
    is( $obj2->get_name, 'Lucky',  "get_name on \$obj2 (Lucky)"  );

};

note(
    'Subtest: Testing object instantiated by ' .
    'Test::More::new_ok() syntax.'
);

subtest 'Object instantiated with new_ok().' => sub {
    # The anonymous array ref falls out of scope after the call; pointer
    # to input param becomes invalidated.  This is why we must make a copy
    # of char * input (if we want it to live on after the constructor
    # exits.
    plan tests => 4;

    my $obj1 = new_ok( 'CStrTest', [ 'Mickey' ], '$obj1' );
    my $obj2 = new_ok( 'CStrTest', [ 'Donald' ], '$obj2' );
    is( $obj1->get_name, 'Mickey', "get_name on \$obj1 (Mickey)" );
    is( $obj2->get_name, 'Donald', "get_name on \$obj2 (Donald)" );
};

done_testing();


__DATA__
__CPP__

class CStrTest {
    public:
        CStrTest( char* a );
        ~CStrTest() { delete[] x; }
        char* get_name();
    private:
        size_t cslen( char *cs );
        char* cscopy( char *cs );
        char* x;
};

CStrTest::CStrTest( char* a ) {
    char* copy = cscopy( a );
    x = copy;
}

char* CStrTest::get_name() {
    return x;
}

size_t CStrTest::cslen( char *cs )
{
    size_t len = 0;
    while( *cs++ )
        len++;
    len += 1;
    return len;
}

char* CStrTest::cscopy ( char *cs )
{
    char *copy = 0;
    char *head = 0;
    size_t len = cslen( cs );
    copy = head = new char[ len ];
    while( *cs )
        *head++ = *cs++;
    *head = 0;
    return copy;
}
