Example #1
0
hashify_input_t hashify_parse_command_line( const char* const* cmdline )
{
	hashify_input_t input = {0};
	int arg, asize;

	input.check_only = false;

	error_context_push( "parsing command line", "" );
	for( arg = 1, asize = array_size( cmdline ); arg < asize; ++arg )
	{
		if( string_equal( cmdline[arg], "--validate" ) )
		{
			input.check_only = true;
			continue;
		}
		else if( string_equal( cmdline[arg], "--generate-string" ) )
		{
			if( arg < asize - 1 )
			{
				++arg;
				array_push( input.strings, string_clone( cmdline[arg] ) );
			}
			continue;
		}
		else if( string_equal( cmdline[arg], "--" ) )
			break; //Stop parsing cmdline options
		else if( ( string_length( cmdline[arg] ) > 2 ) && string_equal_substr( cmdline[arg], "--", 2 ) )
			continue; //Cmdline argument not parsed here			

		array_push( input.files, string_clone( cmdline[arg] ) );
	}
	error_context_pop();

	return input;
}
Example #2
0
int bin2hex_process_files( char const* const* input, char const* const* output, int columns )
{
    int result = BIN2HEX_RESULT_OK;
    unsigned int ifile, files_size;
    for( ifile = 0, files_size = array_size( input ); ( result == BIN2HEX_RESULT_OK ) && ( ifile < files_size ); ++ifile )
    {
        char* input_filename = 0;
        char* output_filename = 0;

        stream_t* input_file = 0;
        stream_t* output_file = 0;

        input_filename = path_clean( string_clone( input[ifile] ), path_is_absolute( input[ifile] ) );
        error_context_push( "parsing file", input_filename );

        output_filename = path_clean( string_clone( output[ifile] ), path_is_absolute( output[ifile] ) );

        log_infof( 0, "bin2hex %s -> %s", input_filename, output_filename );

        input_file = stream_open( input_filename, STREAM_IN | STREAM_BINARY );

        if( !input_file )
        {
            log_warnf( 0, WARNING_BAD_DATA, "Unable to open input file: %s", input_filename );
            result = BIN2HEX_RESULT_MISSING_INPUT_FILE;
        }
        else
        {
            output_file = stream_open( output_filename, STREAM_OUT );
            if( !output_file )
            {
                log_warnf( 0, WARNING_BAD_DATA, "Unable to open output file: %s", output_filename );
                result = BIN2HEX_RESULT_UNABLE_TO_OPEN_OUTPUT_FILE;
            }
        }

        if( input_file && output_file )
            result = bin2hex_process_file( input_file, output_file, columns );

        stream_deallocate( input_file );
        stream_deallocate( output_file );

        string_deallocate( output_filename );

        error_context_pop();
        string_deallocate( input_filename );
    }

    if( ( result == BIN2HEX_RESULT_OK ) && ( files_size > 0 ) )
        log_info( 0, "All files generated" );

    return result;
}
Example #3
0
char* path_merge( const char* first, const char* second )
{
	char* merged;
	if( !first )
		merged = string_clone( second );
	else if( !second )
		merged = string_clone( first );
	else
	{
		merged = string_format( "%s/", first );
		merged = string_append( merged, second );
	}
	merged = path_clean( merged, path_is_absolute( first ) );
	return merged;
}
Example #4
0
void
process_set_arguments(process_t* proc, const string_const_t* args, size_t num) {
	size_t ia;
	string_array_deallocate(proc->args);
	for (ia = 0; ia < num; ++ia)
		array_push(proc->args, string_clone(args[ia].str, args[ia].length));
}
Example #5
0
struct string *strlist_clone(struct strlist *list, size_t index)
{
    if (index >= list->size)
        return NULL;

    return string_clone(list->items[index]);
}
Example #6
0
void process_set_working_directory( process_t* proc, const char* path )
{
	if( !proc )
		return;
	string_deallocate( proc->wd );
	proc->wd = string_clone( path );
}
Example #7
0
void process_set_executable_path( process_t* proc, const char* path )
{
	if( !proc )
		return;
	string_deallocate( proc->path );
	proc->path = string_clone( path );
}
Example #8
0
bin2hex_input_t bin2hex_parse_command_line( char const* const* cmdline )
{
    bin2hex_input_t input = {0};
    int arg, asize;

    error_context_push( "parsing command line", "" );
    for( arg = 1, asize = array_size( cmdline ); arg < asize; ++arg )
    {
        if( string_equal( cmdline[arg], "--columns" ) )
        {
            if( arg < ( asize - 1 ) )
                input.columns = string_to_int( cmdline[++arg] );
        }
        else if( string_equal( cmdline[arg], "--" ) )
            break; //Stop parsing cmdline options
        else if( ( string_length( cmdline[arg] ) > 2 ) && string_equal_substr( cmdline[arg], "--", 2 ) )
            continue; //Cmdline argument not parsed here
        else
        {
            array_push( input.input_files, string_clone( cmdline[arg] ) );
            array_push( input.output_files, string_format( "%s.hex", cmdline[arg] ) );
        }
    }
    error_context_pop();

    return input;
}
Example #9
0
char* path_file_name( const char* path )
{
	unsigned int end = string_find_last_of( path, "/\\", STRING_NPOS );
	if( end == STRING_NPOS )
		return string_clone( path );
	return string_substr( path, end + 1, STRING_NPOS );
}
Example #10
0
shaderparameter_t* shader_get_param(shaderprogram_t* program, const char* name, ShaderParamType type)
{
	GLint paramIndex = 0;
	GLint paramSize = 0;
	GLenum paramType;

	switch(type)
	{
		default:
		case ShaderParamType_Uniform:
		{
			GLsizei nameLength;
			paramIndex = glGetUniformLocation(program->program, name);
			glGetActiveUniform(program->program, paramIndex, 0, &nameLength, &paramSize, &paramType, nullptr);
			FOUNDATION_ASSERT(paramSize > 0);
		}

    	case ShaderParamType_UniformBlock:
    	{
    		paramIndex = glGetUniformBlockIndex(program->program, name);
    		glGetActiveUniformBlockiv(program->program, paramIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &paramSize);
    		FOUNDATION_ASSERT(paramSize > 0);
    	}
	}

	shaderparameter_t* param = (shaderparameter_t*) memory_allocate(sizeof(shaderparameter_t), 4, MEMORY_PERSISTENT);
	param->index = paramIndex;
	param->size = paramSize;
	param->gltype = paramType;
	param->name = string_clone(name);
	param->type = type;
	return param;
}
Example #11
0
static stream_t* _stream_std_clone( stream_t* stream )
{
	stream_std_t* clone = memory_allocate_zero_context( MEMORYCONTEXT_STREAM, sizeof( stream_std_t ), 8, MEMORY_PERSISTENT );
	memcpy( clone, stream, sizeof( stream_std_t ) );
	clone->path = string_clone( stream->path );
	return (stream_t*)clone;
}
Example #12
0
char* path_file_extension( const char* path )
{
	unsigned int start = string_find_last_of( path, "/\\", STRING_NPOS );
	unsigned int end = string_rfind( path, '.', STRING_NPOS );
	if( ( end != STRING_NPOS ) && ( ( start == STRING_NPOS ) || ( end > start ) ) )
		return string_substr( path, end + 1, STRING_NPOS );
	return string_clone( "" );
}
Example #13
0
static obj_t string_copy_fn(obj_t args, Reporter rep)
{
	string str;
	if (!args_match(rep, args, 1, is_string))
		return unspecific;
	str = fetch_string(list_ref(args, 0));
	return make_string(string_clone(str));
}
Example #14
0
void process_set_verb( process_t* proc, const char* verb )
{
	if( !proc )
		return;
#if FOUNDATION_PLATFORM_WINDOWS
	string_deallocate( proc->verb );
	proc->verb = string_clone( verb );
#endif
}
Example #15
0
char* path_prepend( char* tail, const char* base )
{
	if( !tail )
		return path_clean( string_clone( base ), path_is_absolute( base ) );
	tail = string_prepend( tail, "/" );
	tail = string_prepend( tail, base );
	tail = path_clean( tail, path_is_absolute( tail ) );
	return tail;
}
Example #16
0
char* path_append( char* base, const char* tail )
{
	if( !base )
		return path_clean( string_clone( tail ), path_is_absolute( tail ) );
	base = string_append( base, "/" );
	base = string_append( base, tail );
	base = path_clean( base, path_is_absolute( base ) );
	return base;
}
Example #17
0
void process_set_arguments( process_t* proc, const char** args, unsigned int num )
{
	unsigned int ia;
	if( !proc )
		return;
	string_array_deallocate( proc->args );
	for( ia = 0; ia < num; ++ia )
		array_push( proc->args, string_clone( args[ia] ) );
}
Example #18
0
char* path_subdirectory_name( const char* path, const char* root )
{
	char* subpath;
	char* testpath;
	char* testroot;
	char* pathofpath;
	unsigned int pathprotocol, rootprotocol;
	char* cpath = string_clone( path );
	char* croot = string_clone( root );

	cpath = path_clean( cpath, path_is_absolute( cpath ) );
	croot = path_clean( croot, path_is_absolute( croot ) );

	pathofpath = path_directory_name( cpath );

	testpath = pathofpath;
	pathprotocol = string_find_string( testpath, "://", 0 );
	if( pathprotocol != STRING_NPOS )
		testpath += pathprotocol + 2; // add two to treat as absolute path

	testroot = croot;
	rootprotocol = string_find_string( testroot, "://", 0 );
	if( rootprotocol != STRING_NPOS )
		testroot += rootprotocol + 2;

	if( ( rootprotocol != STRING_NPOS ) && ( ( pathprotocol == STRING_NPOS ) || ( pathprotocol != rootprotocol ) || !string_equal_substr( cpath, croot, rootprotocol ) ) )
		subpath = string_allocate( 0 );
	else if( !string_equal_substr( testpath, testroot, string_length( testroot ) ) )
		subpath = string_allocate( 0 );
	else
	{
		char* filename = path_file_name( cpath );

		subpath = string_substr( testpath, string_length( testroot ), STRING_NPOS );
		subpath = path_clean( path_append( subpath, filename ), false );

		string_deallocate( filename );
	}
	string_deallocate( pathofpath );
	string_deallocate( cpath );
	string_deallocate( croot );

	return subpath;
}
Example #19
0
DECLARE_TEST(environment, workingdir) {
	char buffer[BUILD_MAX_PATHLEN];
	string_const_t working_dir = environment_current_working_directory();
	string_const_t new_working_dir = path_directory_name(STRING_ARGS(working_dir));
	string_t working_dir_copy = string_clone(STRING_ARGS(working_dir));
	string_t new_working_dir_copy;

	if (string_equal(STRING_ARGS(working_dir), STRING_CONST("/"))) {
		string_t tmpwork = path_make_temporary(buffer, sizeof(buffer));
		new_working_dir = path_directory_name(STRING_ARGS(tmpwork));
	}

	new_working_dir_copy = string_clone(STRING_ARGS(new_working_dir));
	new_working_dir = string_to_const(new_working_dir_copy);

	EXPECT_CONSTSTRINGNE(working_dir, new_working_dir);

#if FOUNDATION_PLATFORM_PNACL
	EXPECT_FALSE(environment_set_current_working_directory(STRING_ARGS(new_working_dir)));
	EXPECT_CONSTSTRINGEQ(environment_current_working_directory(),
	                     string_const(STRING_ARGS(working_dir_copy)));
#else
	EXPECT_TRUE(environment_set_current_working_directory(STRING_ARGS(new_working_dir)));
	EXPECT_CONSTSTRINGEQ(environment_current_working_directory(), new_working_dir);

	environment_set_current_working_directory(STRING_ARGS(working_dir_copy));
	EXPECT_CONSTSTRINGEQ(environment_current_working_directory(),
	                     string_const(STRING_ARGS(working_dir_copy)));
	{
		log_enable_stdout(false);
		bool ret = environment_set_current_working_directory(STRING_CONST("/invalid/path/which/does/not/exist"));
		log_enable_stdout(true);
		EXPECT_FALSE(ret);
	}
	EXPECT_CONSTSTRINGEQ(environment_current_working_directory(),
	                     string_const(STRING_ARGS(working_dir_copy)));
#endif

	string_deallocate(new_working_dir_copy.str);
	string_deallocate(working_dir_copy.str);

	return 0;
}
Example #20
0
hashify_input_t
hashify_parse_command_line(const string_const_t* cmdline) {
	hashify_input_t input;
	size_t arg, asize;

	memset(&input, 0, sizeof(input));
	input.check_only = false;

	error_context_push(STRING_CONST("parsing command line"), STRING_CONST(""));
	for (arg = 1, asize = array_size(cmdline); arg < asize; ++arg) {
		if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--help"))) {
			hashify_print_usage();
			continue;
		}
		else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--validate"))) {
			input.check_only = true;
			continue;
		}
		else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--generate-string"))) {
			if (arg < asize - 1) {
				++arg;
				array_push(input.strings, string_clone(STRING_ARGS(cmdline[arg])));
			}
			continue;
		}
		else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--debug"))) {
			log_set_suppress(0, ERRORLEVEL_NONE);
			continue;
		}
		else if (string_equal(STRING_ARGS(cmdline[arg]), STRING_CONST("--")))
			break; //Stop parsing cmdline options
		else if ((cmdline[arg].length > 2) && string_equal(cmdline[arg].str, 2, STRING_CONST("--")))
			continue; //Cmdline argument not parsed here

		array_push(input.files, string_clone(STRING_ARGS(cmdline[arg])));
	}
	error_context_pop();

	if (array_size(cmdline) <= 1)
		hashify_print_usage();

	return input;
}
Example #21
0
stream_t* stream_open_stdin( void )
{
	stream_std_t* stream = memory_allocate_zero_context( MEMORYCONTEXT_STREAM, sizeof( stream_std_t ), 8, MEMORY_PERSISTENT );
	_stream_initialize( (stream_t*)stream, system_byteorder() );
	stream->sequential = 1;
	stream->mode = STREAM_IN;
	stream->type = STREAMTYPE_STDSTREAM;
	stream->vtable = &_stream_stdin_vtable;
	stream->path = string_clone( "stdin://" );
	stream->std = stdin;
	return (stream_t*)stream;
}
Example #22
0
static NOINLINE char* _expand_string( hash_t section_current, char* str )
{
	char* expanded;
	char* variable;
	unsigned int var_pos, var_end_pos, variable_length, separator, var_offset;
	hash_t section, key;

	expanded = str;
	var_pos = string_find_string( expanded, "$(", 0 );

	while( var_pos != STRING_NPOS )
	{
		var_end_pos = string_find( expanded, ')', var_pos + 2 );
		FOUNDATION_ASSERT_MSG( var_end_pos != STRING_NPOS, "Malformed config variable statement" );
		variable = string_substr( expanded, var_pos, ( var_end_pos != STRING_NPOS ) ? ( 1 + var_end_pos - var_pos ) : STRING_NPOS );

		section = section_current;
		key = 0;
		variable_length = string_length( variable );
		separator = string_find( variable, ':', 0 );
		if( separator != STRING_NPOS )
		{
			if( separator != 2 )
				section = hash( variable + 2, separator - 2 );
			var_offset = separator + 1;
		}
		else
		{
			var_offset = 2;
		}
		key = hash( variable + var_offset, variable_length - ( var_offset + ( variable[ variable_length - 1 ] == ')' ? 1 : 0 ) ) );

		if( expanded == str )
			expanded = string_clone( str );

		if( section != HASH_ENVIRONMENT )
			expanded = string_replace( expanded, variable, config_string( section, key ), false );
		else
			expanded = string_replace( expanded, variable, _expand_environment( key, variable + var_offset ), false );
		string_deallocate( variable );

		var_pos = string_find_string( expanded, "$(", 0 );
	}
#if BUILD_ENABLE_DEBUG_CONFIG
	if( str != expanded )
		log_debugf( HASH_CONFIG, "Expanded config value \"%s\" to \"%s\"", str, expanded );
#endif

	return expanded;
}
Example #23
0
blast_reader_t*
blast_reader_open(string_t source) {
    void* addr;
    int64_t size;
    blast_reader_t* reader;
    int fd;

    fd = _open(source.str, O_RDONLY);
    if (fd == 0)
        return 0;

    size = _lseek(fd, 0, SEEK_END);
    if (size <= 0) {
        _close(fd);
        return 0;
    }
    _lseek(fd, 0, SEEK_SET);

    addr = memory_allocate(HASH_BLAST, (size_t)size, 0, MEMORY_PERSISTENT);
    _read(fd, addr, (int)size);
    _close(fd);
    /*addr = mmap( 0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0 );
    if( addr == MAP_FAILED )
    {
        int err = system_error();
        log_warnf( HASH_BLAST, WARNING_SYSTEM_CALL_FAIL, "Unable to mmap file '%s' (%d) size %d: %s (%d)", source, fd, size, system_error_message( err ), err );
        close( fd );
        return 0;
    }

    log_infof( HASH_BLAST, "Mapped '%s' size %lld to memory region 0x%" PRIfixPTR, source, size, addr );*/

    reader = memory_allocate(HASH_BLAST, sizeof(blast_reader_t), 0,
                             MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED);

    string_const_t filename = path_file_name(STRING_ARGS(source));
    reader->name = string_clone(STRING_ARGS(filename));
    reader->data = addr;
    //reader->id = fd;
    reader->size = (uint64_t)size;
    reader->cache = blast_reader_cache;
    reader->uncache = blast_reader_uncache;
    reader->map = blast_reader_map;
    reader->unmap = blast_reader_unmap;

    return reader;
}
Example #24
0
char* path_directory_name( const char* path )
{
	char* pathname;
	unsigned int pathprotocol;
	unsigned int pathstart = 0;
	unsigned int end = string_find_last_of( path , "/\\", STRING_NPOS );
	if( end == 0 )
		return string_clone( "/" );
	if( end == STRING_NPOS )
		return string_allocate( 0 );
	pathprotocol = string_find_string( path, "://", 0 );
	if( pathprotocol != STRING_NPOS )
		pathstart = pathprotocol +=2; // add two to treat as absolute path
	pathname = string_substr( path, pathstart, end - pathstart );
	pathname = path_clean( pathname, path_is_absolute( pathname ) );
	return pathname;
}
Example #25
0
void config_set_string( hash_t section, hash_t key, const char* value )
{
	config_key_t* key_val = config_key( section, key, true );
	if( !FOUNDATION_VALIDATE( key_val ) ) return;
	if( key_val->expanded != key_val->sval )
		string_deallocate( key_val->expanded );
	if( ( key_val->type != CONFIGVALUE_STRING_CONST ) && ( key_val->type != CONFIGVALUE_STRING_CONST_VAR ) )
		string_deallocate( key_val->sval );

	key_val->sval = string_clone( value );
	key_val->expanded = 0;
	key_val->type = ( ( string_find_string( key_val->sval, "$(", 0 ) != STRING_NPOS ) ? CONFIGVALUE_STRING_VAR : CONFIGVALUE_STRING );

	if( key_val->type == CONFIGVALUE_STRING )
	{
		bool is_true = string_equal( key_val->sval, "true" );
		key_val->bval = ( string_equal( key_val->sval, "false" ) || string_equal( key_val->sval, "0" ) || !string_length( key_val->sval ) ) ? false : true;
		key_val->ival = is_true ? 1 : _config_string_to_int( key_val->sval );
		key_val->rval = is_true ? REAL_C(1.0) : _config_string_to_real( key_val->sval );
	}
}
Example #26
0
PluginData* PluginHandler_reloadPlugin(PluginData* pluginData) {
    const char* filename = pluginData->filename;
    const char* fullName = string_clone(pluginData->fullFilename);

    printf("removing plugin...\n");

    removePlugin(pluginData);

    printf("adding plugin...%s\n", filename);

    PluginHandler_addPlugin(OBJECT_DIR, filename);

    printf("finding plugin\n");

    printf("trying to find %s\n", fullName);

    PluginData* newPluginData = PluginHandler_findPluginByFilename(fullName);

    printf("found plugin %p\n", newPluginData);

    return newPluginData;
}
Example #27
0
DECLARE_TEST( string, prepend )
{
	const char* nullstr = 0;
	const char* emptystr = "";
	const char* shortstr = "short";
	const char* longstr = "long long long long long long long long long";
	char* val;

	val = 0;
	val = string_prepend( val, nullstr );
	EXPECT_STREQ( val, "" );
	string_deallocate( val );

	val = 0;
	val = string_prepend( val, emptystr );
	EXPECT_STREQ( val, "" );
	string_deallocate( val );

	val = string_clone( emptystr );
	val = string_prepend( val, nullstr );
	EXPECT_STREQ( val, "" );
	string_deallocate( val );

	val = string_clone( emptystr );
	val = string_prepend( val, emptystr );
	EXPECT_STREQ( val, "" );
	string_deallocate( val );

	val = 0;
	val = string_prepend( val, shortstr );
	EXPECT_STREQ( val, "short" );
	string_deallocate( val );

	val = string_clone( shortstr );
	val = string_prepend( val, nullstr );
	EXPECT_STREQ( val, "short" );
	string_deallocate( val );

	val = string_clone( emptystr );
	val = string_prepend( val, shortstr );
	EXPECT_STREQ( val, "short" );
	string_deallocate( val );

	val = string_clone( shortstr );
	val = string_prepend( val, emptystr );
	EXPECT_STREQ( val, "short" );
	string_deallocate( val );

	val = string_clone( shortstr );
	val = string_prepend( val, shortstr );
	EXPECT_STREQ( val, "shortshort" );
	string_deallocate( val );

	val = 0;
	val = string_prepend( val, longstr );
	EXPECT_STREQ( val, "long long long long long long long long long" );
	string_deallocate( val );

	val = string_clone( longstr );
	val = string_prepend( val, nullstr );
	EXPECT_STREQ( val, "long long long long long long long long long" );
	string_deallocate( val );

	val = string_clone( emptystr );
	val = string_prepend( val, longstr );
	EXPECT_STREQ( val, "long long long long long long long long long" );
	string_deallocate( val );

	val = string_clone( longstr );
	val = string_prepend( val, emptystr );
	EXPECT_STREQ( val, "long long long long long long long long long" );
	string_deallocate( val );

	val = string_clone( shortstr );
	val = string_prepend( val, longstr );
	EXPECT_STREQ( val, "long long long long long long long long longshort" );
	string_deallocate( val );

	val = string_clone( longstr );
	val = string_prepend( val, shortstr );
	EXPECT_STREQ( val, "shortlong long long long long long long long long" );
	string_deallocate( val );

	val = string_clone( longstr );
	val = string_prepend( val, longstr );
	EXPECT_STREQ( val, "long long long long long long long long longlong long long long long long long long long" );
	string_deallocate( val );

	return 0;
}
Example #28
0
int process_spawn( process_t* proc )
{
	static char unescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.:/\\";
	int i, num_args;
	int size;
#if FOUNDATION_PLATFORM_WINDOWS
	wchar_t* wcmdline;
	wchar_t* wwd;
	char* cmdline = 0;
#endif

	if( !proc )
		return PROCESS_INVALID_ARGS;
	
	proc->code = PROCESS_INVALID_ARGS;

	if( !string_length( proc->path ) )
		return proc->code;

	//Always escape path on Windows platforms
#if FOUNDATION_PLATFORM_POSIX
	if( string_find_first_not_of( proc->path, unescaped, 0 ) != STRING_NPOS )
#endif
	{
		if( proc->path[0] != '"' )
			proc->path = string_prepend( proc->path, "\"" );
		if( proc->path[ string_length( proc->path ) - 1 ] != '"' )
			proc->path = string_append( proc->path, "\"" );
	}

	size = array_size( proc->args );
	for( i = 0, num_args = 0; i < size; ++i )
	{
		char* arg = proc->args[i];
		
		if( !string_length( arg ) )
			continue;
		
		++num_args;
		
		if( string_find_first_not_of( arg, unescaped, 0 ) != STRING_NPOS )
		{
			if( arg[0] != '"' )
			{
				//Check if we need to escape " characters
				unsigned int pos = string_find( arg, '"', 0 );
				while( pos != STRING_NPOS )
				{
					if( arg[ pos - 1 ] != '\\' )
					{
						char* escarg = string_substr( arg, 0, pos );
						char* left = string_substr( arg, pos, STRING_NPOS );
						escarg = string_append( escarg, "\\" );
						escarg = string_append( escarg, left );
						string_deallocate( left );
						string_deallocate( arg );
						arg = escarg;
					}
					pos = string_find( arg, '"', pos + 2 );
				}
				arg = string_prepend( arg, "\"" );
				arg = string_append( arg, "\"" );

				proc->args[i] = arg;
			}
		}
	}

#if FOUNDATION_PLATFORM_WINDOWS

#  ifndef SEE_MASK_NOASYNC
#    define SEE_MASK_NOASYNC           0x00000100
#  endif

	if( !( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE ) ) //Don't prepend exe path to parameters if using ShellExecute
		cmdline = string_clone( proc->path );
	
	//Build command line string
	for( i = 0; i < size; ++i )
	{
		char* arg = proc->args[i];
		
		if( !string_length( arg ) )
			continue;

		if( cmdline )
			cmdline = string_append( cmdline, " " );
		cmdline = string_append( cmdline, arg );
	}
	
	if( !string_length( proc->wd ) )
		proc->wd = string_clone( environment_current_working_directory() );

	wcmdline = wstring_allocate_from_string( cmdline, 0 );
	wwd = wstring_allocate_from_string( proc->wd, 0 );
	
	if( proc->flags & PROCESS_WINDOWS_USE_SHELLEXECUTE )
	{
		SHELLEXECUTEINFOW sei;
		wchar_t* wverb;
		wchar_t* wpath;

		wverb = ( proc->verb && string_length( proc->verb ) ) ? wstring_allocate_from_string( proc->verb, 0 ) : 0;
		wpath = wstring_allocate_from_string( proc->path, 0 );

		ZeroMemory( &sei, sizeof( sei ) );

		sei.cbSize          = sizeof(SHELLEXECUTEINFOW);
		sei.hwnd            = 0;
		sei.fMask           = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
		sei.lpVerb          = wverb;
		sei.lpFile          = wpath;
		sei.lpParameters    = wcmdline;
		sei.lpDirectory     = wwd;
		sei.nShow           = SW_SHOWNORMAL;

		if( !( proc->flags & PROCESS_CONSOLE ) )
			sei.fMask      |= SEE_MASK_NO_CONSOLE;

		if( proc->flags & PROCESS_STDSTREAMS )
			log_warnf( 0, WARNING_UNSUPPORTED, "Unable to redirect standard in/out through pipes when using ShellExecute for process spawning" );

		log_debugf( 0, "Spawn process (ShellExecute): %s %s", proc->path, cmdline );

		if( !ShellExecuteExW( &sei ) )
		{
			log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (ShellExecute) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) );
		}
		else
		{
			proc->hp   = sei.hProcess;
			proc->ht   = 0;
			proc->code = 0;
		}

		wstring_deallocate( wverb );
		wstring_deallocate( wpath );
	}
	else
	{
		STARTUPINFOW si;
		PROCESS_INFORMATION pi;
		BOOL inherit_handles = FALSE;

		memset( &si, 0, sizeof( si ) );
		memset( &pi, 0, sizeof( pi ) );
		si.cb = sizeof( si );

		if( proc->flags & PROCESS_STDSTREAMS )
		{
			proc->pipeout = pipe_allocate();
			proc->pipein = pipe_allocate();

			si.dwFlags |= STARTF_USESTDHANDLES;
			si.hStdOutput = pipe_write_handle( proc->pipeout );
			si.hStdError = pipe_write_handle( proc->pipeout );
			si.hStdInput = pipe_read_handle( proc->pipein );

			//Don't inherit wrong ends of pipes
			SetHandleInformation( pipe_read_handle( proc->pipeout ), HANDLE_FLAG_INHERIT, 0 );
			SetHandleInformation( pipe_write_handle( proc->pipein ), HANDLE_FLAG_INHERIT, 0 );

			inherit_handles = TRUE;
		}

		log_debugf( 0, "Spawn process (CreateProcess): %s %s", proc->path, cmdline );

		if( !CreateProcessW( 0/*wpath*/, wcmdline, 0, 0, inherit_handles, ( proc->flags & PROCESS_CONSOLE ) ? CREATE_NEW_CONSOLE : 0, 0, wwd, &si, &pi ) )
		{
			log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to spawn process (CreateProcess) for executable '%s': %s", proc->path, system_error_message( GetLastError() ) );

			stream_deallocate( proc->pipeout );
			stream_deallocate( proc->pipein );

			proc->pipeout = 0;
			proc->pipein = 0;
		}
		else
		{
			proc->hp = pi.hProcess;
			proc->ht = pi.hThread;
			proc->code = 0;
		}

		if( proc->pipeout )
			pipe_close_write( proc->pipeout );
		if( proc->pipein )
			pipe_close_read( proc->pipein );
	}

	wstring_deallocate( wcmdline );
	wstring_deallocate( wwd );
	string_deallocate( cmdline );
	
	if( proc->code < 0 )
		return proc->code; //Error

#endif

#if FOUNDATION_PLATFORM_MACOSX
	
	if( proc->flags & PROCESS_OSX_USE_OPENAPPLICATION )
	{
		proc->pid = 0;
		
		LSApplicationParameters params;
		ProcessSerialNumber psn;
		FSRef* fsref = memory_allocate( 0, sizeof( FSRef ), 0, MEMORY_TEMPORARY | MEMORY_ZERO_INITIALIZED );
		
		memset( &params, 0, sizeof( LSApplicationParameters ) );
		memset( &psn, 0, sizeof( ProcessSerialNumber ) );
		
		char* pathstripped = string_strip( string_clone( proc->path ), "\"" );
		
		OSStatus status = 0;
		status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 );
		if( status < 0 )
		{
			pathstripped = string_append( pathstripped, ".app" );
			status = FSPathMakeRef( (uint8_t*)pathstripped, fsref, 0 );
		}
		
		CFStringRef* args = 0;
		for( i = 0, size = array_size( proc->args ); i < size; ++i ) //App gets executable path automatically, don't include
			array_push( args, CFStringCreateWithCString( 0, proc->args[i], kCFStringEncodingUTF8 ) );
		
		CFArrayRef argvref = CFArrayCreate( 0, (const void**)args, (CFIndex)array_size( args ), 0 );
		
		params.flags = kLSLaunchDefaults;
		params.application = fsref;
		params.argv = argvref;

		log_debugf( 0, "Spawn process (LSOpenApplication): %s", pathstripped );
		
		status = LSOpenApplication( &params, &psn );
		if( status != 0 )
		{
			proc->code = status;
			log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process for executable '%s': %s", proc->path, system_error_message( status ) );
		}
		
		CFRelease( argvref );
		for( i = 0, size = array_size( args ); i < size; ++i )
			CFRelease( args[i] );
		
		memory_deallocate( fsref );
		string_deallocate( pathstripped );
		
		if( status == 0 )
		{
			pid_t pid = 0;
			GetProcessPID( &psn, &pid );
			
			proc->pid = pid;

			//Always "detached" with LSOpenApplication, not a child process at all
			//Setup a kqueue to watch when process terminates so we can emulate a wait
			proc->kq = kqueue();
			if( proc->kq < 0 )
			{
				log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create kqueue for process watch: %s (%d)", proc->kq, system_error_message( proc->kq ) );
				proc->kq = 0;
			}
			else
			{
				struct kevent changes;
				EV_SET( &changes, (pid_t)pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, 0 );
				int ret = kevent( proc->kq, &changes, 1, &changes, 1, 0 );
				if( ret != 1 )
				{
					log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to setup kqueue for process watch, failed to add event to kqueue (%d)", ret );
					close( proc->kq );
					proc->kq = 0;
				}
			}
		}
		
		goto exit;
	}
#endif

#if FOUNDATION_PLATFORM_POSIX

	//Insert executable arg at start and null ptr at end
	int argc = array_size( proc->args ) + 1;
	array_grow( proc->args, 2 );
	for( int arg = argc - 1; arg > 0; --arg )
		proc->args[arg] = proc->args[arg-1];
	proc->args[0] = string_clone( proc->path );
	proc->args[argc] = 0;

	if( proc->flags & PROCESS_STDSTREAMS )
	{
		proc->pipeout = pipe_allocate();
		proc->pipein = pipe_allocate();
	}
	
	proc->pid = 0;	
	pid_t pid = fork();

	if( pid == 0 )
	{
		//Child
		if( string_length( proc->wd ) )
		{
			log_debugf( 0, "Spawned child process, setting working directory to %s", proc->wd );
			environment_set_current_working_directory( proc->wd );
		}

		log_debugf( 0, "Child process executing: %s", proc->path );

		if( proc->flags & PROCESS_STDSTREAMS )
		{
			pipe_close_read( proc->pipeout );
			dup2( pipe_write_fd( proc->pipeout ), STDOUT_FILENO );

			pipe_close_write( proc->pipein );
			dup2( pipe_read_fd( proc->pipein ), STDIN_FILENO );
		}

		int code = execv( proc->path, proc->args );
		if( code < 0 ) //Will always be true since this point will never be reached if execve() is successful
			log_warnf( 0, WARNING_BAD_DATA, "Child process failed execve() : %s : %s", proc->path, system_error_message( errno ) );
		
		//Error
		process_exit( -1 );
	}

	if( pid > 0 )
	{		
		log_debugf( 0, "Child process forked, pid %d", pid );

		proc->pid = pid;

		if( proc->pipeout )
			pipe_close_write( proc->pipeout );
		if( proc->pipein )
			pipe_close_read( proc->pipein );
		
		if( proc->flags & PROCESS_DETACHED )
		{
			int cstatus = 0;
			pid_t err = waitpid( pid, &cstatus, WNOHANG );
			if( err == 0 )
			{
				//TODO: Ugly wait to make sure process spawned correctly
				thread_sleep( 500 );
				err = waitpid( pid, &cstatus, WNOHANG );
			}
			if( err > 0 )
			{
				//Process exited, check code
				proc->code = (int)((char)WEXITSTATUS( cstatus ));
				log_debugf( 0, "Child process returned: %d", proc->code );
				return proc->code;
			}
		}
	}
	else
	{
		//Error
		proc->code = errno;
		log_warnf( 0, WARNING_BAD_DATA, "Unable to spawn process: %s : %s", proc->path, system_error_message( proc->code ) );

		if( proc->pipeout )
			stream_deallocate( proc->pipeout );
		if( proc->pipein )
			stream_deallocate( proc->pipein );

		proc->pipeout = 0;
		proc->pipein = 0;
		
		return proc->code;
	}	

#endif

#if !FOUNDATION_PLATFORM_WINDOWS && !FOUNDATION_PLATFORM_POSIX
	FOUNDATION_ASSERT_FAIL( "Process spawning not supported on platform" );
#endif
	
#if FOUNDATION_PLATFORM_MACOSX
exit:
#endif

	if( proc->flags & PROCESS_DETACHED )
		return PROCESS_STILL_ACTIVE;

	return process_wait( proc );
}
Example #29
0
DECLARE_TEST( string, utility )
{
	{
		char* path1 = string_clone( "" );
		char* path2 = string_clone( "/" );
		char* path3 = string_clone( "/." );
		char* path4 = string_clone( "./" );
		char* path5 = string_clone( "./." );
		char* path6 = string_clone( "././" );
		char* path7 = string_clone( "././//" );
		char* path8 = string_clone( "././//./////././////.//////.//." );
		char* path9 = string_clone( "http://././//./////././////.//////.//." );
		char* path10 = string_clone( "" );
		char* path11 = string_clone( "\\" );
		char* path12 = string_clone( "/\\." );
		char* path13 = string_clone( ".\\/" );
		char* path14 = string_clone( "./\\." );
		char* path15 = string_clone( ".\\.//\\" );
		char* path16 = string_clone( ".\\.\\\\\\" );
		char* path17 = string_clone( ".\\.\\\\\\.\\\\////\\///\\\\.\\.\\\\\\\\\\.\\\\\\\\\\\\.\\\\." );
		char* path18 = string_clone( "http://\\.\\.\\\\\\.\\\\\\\\//\\.\\.\\\\\\\\//\\.\\\\\\\\\\\\.\\\\." );
		
		char* path19 = string_clone( "testing/path/ext" );
		char* path20 = string_clone( "testing/path/extend" );
		char* path21 = string_clone( "testing/path/extend/dyn" );
		char* path22 = string_clone( "testing/./\\\\/\\/./path/././//./extend/\\\\" );

		path1 = path_clean( path1, true );
		path2 = path_clean( path2, true );
		path3 = path_clean( path3, true );
		path4 = path_clean( path4, true );
		path5 = path_clean( path5, true );
		path6 = path_clean( path6, true );
		path7 = path_clean( path7, true );
		path8 = path_clean( path8, true );
		path9 = path_clean( path9, true );
		path10 = path_clean( path10, true );
		path11 = path_clean( path11, true );
		path12 = path_clean( path12, true );
		path13 = path_clean( path13, true );
		path14 = path_clean( path14, true );
		path15 = path_clean( path15, true );
		path16 = path_clean( path16, true );
		path17 = path_clean( path17, true );
		path18 = path_clean( path18, true );
		path19 = path_clean( path19, true );
		path20 = path_clean( path20, true );
		path21 = path_clean( path21, true );
		path22 = path_clean( path22, true );

		EXPECT_TRUE( string_equal( path1, "/" ) );
		EXPECT_TRUE( string_equal( path2, "/" ) );
		EXPECT_TRUE( string_equal( path3, "/" ) );
		EXPECT_TRUE( string_equal( path4, "/" ) );
		EXPECT_TRUE( string_equal( path5, "/" ) );
		EXPECT_TRUE( string_equal( path6, "/" ) );
		EXPECT_TRUE( string_equal( path7, "/" ) );
		EXPECT_TRUE( string_equal( path8, "/" ) );
		EXPECT_TRUE( string_equal( path9, "http://" ) );
		EXPECT_TRUE( string_equal( path10, "/" ) );
		EXPECT_TRUE( string_equal( path11, "/" ) );
		EXPECT_TRUE( string_equal( path12, "/" ) );
		EXPECT_TRUE( string_equal( path13, "/" ) );
		EXPECT_TRUE( string_equal( path14, "/" ) );
		EXPECT_TRUE( string_equal( path15, "/" ) );
		EXPECT_TRUE( string_equal( path16, "/" ) );
		EXPECT_TRUE( string_equal( path17, "/" ) );
		EXPECT_TRUE( string_equal( path18, "http://" ) );
		EXPECT_TRUE( string_equal( path19, "/testing/path/ext" ) );
		EXPECT_TRUE( string_equal( path20, "/testing/path/extend" ) );
		EXPECT_TRUE( string_equal( path21, "/testing/path/extend/dyn" ) );
		EXPECT_TRUE( string_equal( path22, "/testing/path/extend" ) );

		string_deallocate( path1 );
		string_deallocate( path2 );
		string_deallocate( path3 );
		string_deallocate( path4 );
		string_deallocate( path5 );
		string_deallocate( path6 );
		string_deallocate( path7 );
		string_deallocate( path8 );
		string_deallocate( path9 );
		string_deallocate( path10 );
		string_deallocate( path11 );
		string_deallocate( path12 );
		string_deallocate( path13 );
		string_deallocate( path14 );
		string_deallocate( path15 );
		string_deallocate( path16 );
		string_deallocate( path17 );
		string_deallocate( path18 );
		string_deallocate( path19 );
		string_deallocate( path20 );
		string_deallocate( path21 );
		string_deallocate( path22 );
	}
	{
		char** explodearr = 0;
		char* explodestr = string_clone( "  .,testing,    .,utility.,string  methods ..., like,,,finds  split..merge     .,.explode.and. .., ., similar   .,,,. " );
		
		char* mergestr = string_clone( "    testing   merge string   " );
		char* mergestr2 = string_clone( " ., testing, .merge.string,. " );
		char* merged = 0;
		char** mergearr, **mergearr2, **mergearr3;

		char* splitstr = string_clone( " testing split" );
		char* splitright = 0, *splitleft = 0;
		char* splitright2 = 0, *splitleft2 = 0;

		char* substrtest = string_clone( "testing substr" );
		char* substr = 0;
		
		explodearr = string_explode( explodestr, " ,.", false );
		mergearr = string_explode( mergestr, " .,", true );
		mergearr2 = string_explode( mergestr, " .,", false );
		mergearr3 = string_explode( mergestr, " .,", true );
		merged = string_merge( (const char* const*)mergearr, array_size( mergearr ), " " );

		string_split( splitstr, " ", &splitleft, &splitright, false );
		string_split( splitstr, " ", &splitleft2, &splitright2, true );
		
		EXPECT_EQ( array_size( explodearr ), 11 );
		EXPECT_TRUE( string_equal( explodearr[0], "testing" ) );
		EXPECT_TRUE( string_equal( explodearr[1], "utility" ) );
		EXPECT_TRUE( string_equal( explodearr[2], "string" ) );
		EXPECT_TRUE( string_equal( explodearr[3], "methods" ) );
		EXPECT_TRUE( string_equal( explodearr[4], "like" ) );
		EXPECT_TRUE( string_equal( explodearr[5], "finds" ) );
		EXPECT_TRUE( string_equal( explodearr[6], "split" ) );
		EXPECT_TRUE( string_equal( explodearr[7], "merge" ) );
		EXPECT_TRUE( string_equal( explodearr[8], "explode" ) );
		EXPECT_TRUE( string_equal( explodearr[9], "and" ) );
		EXPECT_TRUE( string_equal( explodearr[10], "similar" ) );

		EXPECT_EQ( array_size( mergearr ), 12 );
		EXPECT_TRUE( string_equal( mergearr[0], "" ) );
		EXPECT_TRUE( string_equal( mergearr[1], "" ) );
		EXPECT_TRUE( string_equal( mergearr[2], "" ) );
		EXPECT_TRUE( string_equal( mergearr[3], "" ) );
		EXPECT_TRUE( string_equal( mergearr[4], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr[5], "" ) );
		EXPECT_TRUE( string_equal( mergearr[6], "" ) );
		EXPECT_TRUE( string_equal( mergearr[7], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr[8], "string" ) );
		EXPECT_TRUE( string_equal( mergearr[9], "" ) );
		EXPECT_TRUE( string_equal( mergearr[10], "" ) );
		EXPECT_TRUE( string_equal( mergearr[11], "" ) );

		EXPECT_EQ( array_size( mergearr2 ), 3 );
		EXPECT_TRUE( string_equal( mergearr2[0], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr2[1], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr2[2], "string" ) );
		EXPECT_TRUE( string_equal( merged, mergestr ) );

		EXPECT_EQ( array_size( mergearr3 ), 12 );
		EXPECT_TRUE( string_equal( mergearr3[0], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[1], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[2], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[3], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[4], "testing" ) );
		EXPECT_TRUE( string_equal( mergearr3[5], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[6], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[7], "merge" ) );
		EXPECT_TRUE( string_equal( mergearr3[8], "string" ) );
		EXPECT_TRUE( string_equal( mergearr3[9], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[10], "" ) );
		EXPECT_TRUE( string_equal( mergearr3[11], "" ) );

		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 4 ), "test" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 14 ), "testing substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 0, 20 ), "testing substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 20 ), "ting substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 11 ), "ting substr" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 1 ), "t" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 3, 0 ), "" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 0 ), "" ) ); string_deallocate( substr );
		EXPECT_TRUE( string_equal( substr = string_substr( substrtest, 20, 20 ), "" ) ); string_deallocate( substr );

		EXPECT_TRUE( string_equal( splitleft, "testing" ) );
		EXPECT_TRUE( string_equal( splitright, "split" ) );
		EXPECT_TRUE( string_equal( splitleft2, "" ) );
		EXPECT_TRUE( string_equal( splitright2, "testing split" ) );
		{
			char* replacestr = string_clone( "testing replace" );
			char* replacestr2 = string_clone( "testing replace" );
			char* replacestr3 = string_clone( "testing replacelace" );
			char* replacestr4 = string_clone( "" );
			char* replacestr5 = string_clone( "repppppppppp" );

			replacestr = string_replace( replacestr, "rep", "testrep", false );
			replacestr2 = string_replace( replacestr2, "rep", "testrep", true );
			replacestr3 = string_replace( replacestr3, "replace", "testrep", true );
			replacestr4 = string_replace( replacestr4, "foo", "bar", true );
			replacestr5 = string_replace( replacestr5, "rep", "re", true );
		
			EXPECT_TRUE( string_equal( replacestr, "testing testreplace" ) );
			EXPECT_TRUE( string_equal( replacestr2, "testing testreplace" ) );
			EXPECT_TRUE( string_equal( replacestr3, "testing testtestrep" ) );
			EXPECT_TRUE( string_equal( replacestr4, "" ) );
			EXPECT_TRUE( string_equal( replacestr5, "re" ) );

			string_deallocate( replacestr );
			string_deallocate( replacestr2 );
			string_deallocate( replacestr3 );
			string_deallocate( replacestr4 );
			string_deallocate( replacestr5 );
		}
		{
			char* stripstr = string_clone( "   testing strip :   " );
			char* stripstr2 = string_clone( "   testing strip :   " );
			char* stripstr3 = string_clone( "   testing strip :   " );

			stripstr = string_strip( stripstr, " tp:   " );
			stripstr2 = string_strip( stripstr2, "" );
			stripstr3 = string_strip( stripstr3, " tesingrp:" );
		
			EXPECT_TRUE( string_equal( stripstr, "esting stri" ) );
			EXPECT_TRUE( string_equal( stripstr2, "   testing strip :   " ) );
			EXPECT_TRUE( string_equal( stripstr3, "" ) );

			string_deallocate( stripstr );
			string_deallocate( stripstr2 );
			string_deallocate( stripstr3 );
		}
		string_array_deallocate( explodearr );
		string_deallocate( explodestr );
		
		string_deallocate( mergestr );
		string_deallocate( mergestr2 );
		string_deallocate( merged );
		string_array_deallocate( mergearr );
		string_array_deallocate( mergearr2 );
		string_array_deallocate( mergearr3 );

		string_deallocate( splitstr );
		string_deallocate( splitright );
		string_deallocate( splitleft );
		string_deallocate( splitright2 );
		string_deallocate( splitleft2 );

		string_deallocate( substrtest );
	}
	{
		#define SHORTSTRING "short"
		#define LONGSTRING  "long string with dynamic buffer storage but with no real useful data"
		char* clonestr = string_clone( "" );
		char* clonestr2 = string_clone( SHORTSTRING );
		char* clonestr3 = string_clone( LONGSTRING );

		char* teststr = string_clone( clonestr );
		char* teststr2 = string_clone( clonestr2 );
		char* teststr3 = string_clone( clonestr3 );

		char* concatstr = string_concat( clonestr, teststr );
		char* concatstr2 = string_concat( clonestr, teststr2 );
		char* concatstr3 = string_concat( teststr2, clonestr );
		char* concatstr4 = string_concat( clonestr2, teststr2 );
		char* concatstr5 = string_concat( clonestr, teststr3 );
		char* concatstr6 = string_concat( teststr3, clonestr );
		char* concatstr7 = string_concat( clonestr2, teststr3 );
		char* concatstr8 = string_concat( teststr3, clonestr2 );
		char* concatstr9 = string_concat( clonestr3, teststr3 );
		char* concatstr10 = string_concat( teststr3, clonestr3 );
		
		EXPECT_NE( teststr, clonestr );
		EXPECT_TRUE( string_equal( teststr, clonestr ) );
		
		EXPECT_NE( teststr2, clonestr2 );
		EXPECT_TRUE( string_equal( teststr2, clonestr2 ) );

		EXPECT_NE( teststr3, clonestr3 );
		EXPECT_TRUE( string_equal( teststr3, clonestr3 ) );

		EXPECT_TRUE( string_equal( concatstr, "" ) );
		EXPECT_TRUE( string_equal( concatstr2, SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr3, SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr4, SHORTSTRING SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr5, LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr6, LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr7, SHORTSTRING LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr8, LONGSTRING SHORTSTRING ) );
		EXPECT_TRUE( string_equal( concatstr9, LONGSTRING LONGSTRING ) );
		EXPECT_TRUE( string_equal( concatstr10, LONGSTRING LONGSTRING ) );
		
		string_deallocate( teststr );
		string_deallocate( clonestr );
		string_deallocate( teststr2 );
		string_deallocate( clonestr2 );
		string_deallocate( teststr3 );
		string_deallocate( clonestr3 );
		string_deallocate( concatstr );
		string_deallocate( concatstr2 );
		string_deallocate( concatstr3 );
		string_deallocate( concatstr4 );
		string_deallocate( concatstr5 );
		string_deallocate( concatstr6 );
		string_deallocate( concatstr7 );
		string_deallocate( concatstr8 );
		string_deallocate( concatstr9 );
		string_deallocate( concatstr10 );
		#undef SHORTSTRING
		#undef LONGSTRING
	}
	return 0;
}
Example #30
0
struct strlist *strlist_append(struct strlist *list, struct string *str)
{
    list = strlist_ensure(list, list->size + 1);
    list->items[list->size++] = string_clone(str);
    return list;
}