コード例 #1
0
ファイル: main.c プロジェクト: rampantpixels/foundation_lib
int
hashify_write_file(stream_t* generated_file, string_t output_filename) {
	bool need_update = false;
	stream_t* output_file = 0;
	int result = HASHIFY_RESULT_OK;

	output_file = stream_open(STRING_ARGS(output_filename), STREAM_OUT | STREAM_IN);
	if (!output_file) {
		need_update = true;
		output_file = stream_open(STRING_ARGS(output_filename), STREAM_OUT);
		if (!output_file) {
			log_warnf(0, WARNING_INVALID_VALUE, STRING_CONST("Unable to open output file: %.*s"),
			          STRING_FORMAT(output_filename));
			return HASHIFY_RESULT_MISSING_OUTPUT_FILE;
		}
	}

	if (!need_update)
		need_update = !uint128_equal(stream_md5(generated_file), stream_md5(output_file));

	if (need_update) {
		char local_buffer[1024];
		size_t read = 0;
		size_t written = 0;
		uint64_t total_written = 0;

		stream_seek(generated_file, 0, STREAM_SEEK_BEGIN);
		stream_seek(output_file, 0, STREAM_SEEK_BEGIN);

		while (!stream_eos(generated_file)) {
			read = stream_read(generated_file, local_buffer, 1024);
			if (!read)
				break;

			written = stream_write(output_file, local_buffer, read);
			total_written += written;

			if (written != read) {
				log_errorf(0, ERROR_SYSTEM_CALL_FAIL,
				           STRING_CONST("Unable to write to output file '%.*s': %" PRIsize " of %" PRIsize " bytes written"),
				           STRING_FORMAT(output_filename), written, read);
				result = HASHIFY_RESULT_OUTPUT_FILE_WRITE_FAIL;
				break;
			}
		}

		if (result == HASHIFY_RESULT_OK) {
			stream_truncate(output_file, (size_t)total_written);
			log_infof(0, STRING_CONST("  wrote %.*s : %" PRIu64 " bytes"), STRING_FORMAT(output_filename),
			          total_written);
		}
	}
	else {
		log_info(0, STRING_CONST("  hash file already up to date"));
	}

	stream_deallocate(output_file);

	return result;
}
コード例 #2
0
ファイル: Fl_XmlTokenizer.cpp プロジェクト: GustavoMOG/efltk
int Fl_XmlDefaultTokenizer::stream_read(char *buf, int length)
{
    if(!stream_eos()) {
        int readed = ((Fl_IO*)io_ctx)->read(buf, length);
        if(readed>0) return readed;
    }
    return -1;
}
コード例 #3
0
ファイル: stream.c プロジェクト: haifenghuang/foundation_lib
string_t
stream_read_line(stream_t* stream, char delimiter) {
	char buffer[128];
	char* outbuffer = 0;
	size_t outsize = 0;
	size_t cursize = 0;
	size_t read, i;
	size_t want_read = 128;

	if (!(stream->mode & STREAM_IN))
		return (string_t) { 0, 0 };

	//Need to read one byte at a time since we can't scan back if overreading
	if (stream_is_sequential(stream))
		want_read = 1;

	while (!stream_eos(stream)) {
		read = stream->vtable->read(stream, buffer, want_read);
		if (!read)
			break;
		for (i = 0; i < read; ++i) {
			if (buffer[i] == delimiter)
				break;
		}
		if (cursize + i > outsize) {
			size_t nextsize;
			if (!outbuffer) {
				nextsize = (i >= 32 ? i + 1 : (i > 1 ? i + 1 : 32));
				outbuffer = memory_allocate(0, nextsize, 0, MEMORY_PERSISTENT);
			}
			else {
				nextsize = (outsize < 511 ? 512 : outsize + 513);   //Always aligns to 512 multiples
				FOUNDATION_ASSERT(!(nextsize % 512));
				outbuffer = memory_reallocate(outbuffer, nextsize, 0, outsize + 1);
			}
			outsize = nextsize - 1;
		}
		if (i) {
			memcpy(outbuffer + cursize, buffer, i); //lint !e613
			cursize += i;
		}
		if (i < read) {
			if ((i + 1) < read) {
				//Sequential should never end up here reading one byte at a time
				FOUNDATION_ASSERT(!stream_is_sequential(stream));
				stream_seek(stream, (ssize_t)(1 + i) - (ssize_t)read, STREAM_SEEK_CURRENT);
			}
			break;
		}
	}

	if (outbuffer)
		outbuffer[cursize] = 0;

	return (string_t) { outbuffer, cursize };
}
コード例 #4
0
ファイル: stream.c プロジェクト: sunfirefox/foundation_lib
char* stream_read_line( stream_t* stream, char delimiter )
{
	char buffer[128];
	char* outbuffer;
	int outsize = 32;
	int cursize = 0;
	int read, i;
	int want_read = 128;

	FOUNDATION_ASSERT( stream );
	if( !( stream->mode & STREAM_IN ) )
		return 0;

	FOUNDATION_ASSERT( stream->vtable->read );

	if( stream_is_sequential( stream ) ) //Need to read one byte at a time since we can't scan back if overreading
		want_read = 1;

	outbuffer = memory_allocate( outsize + 1, 0, MEMORY_PERSISTENT );
	while( !stream_eos( stream ) )
	{
		read = (int)stream->vtable->read( stream, buffer, want_read );
		if( !read )
			break;
		for( i = 0; i < read; ++i )
		{
			if( buffer[i] == delimiter )
				break;
		}
		if( cursize + i > outsize )
		{
			outsize += 512;
			outbuffer = memory_reallocate( outbuffer, outsize + 1, 0, cursize );
		}
		memcpy( outbuffer + cursize, buffer, i );
		cursize += i;
		if( i < read )
		{
			if( ( i + 1 ) < read )
			{
				FOUNDATION_ASSERT( !stream_is_sequential( stream ) ); //Sequential should never end up here reading one byte at a time
				stream_seek( stream, 1 + i - read, STREAM_SEEK_CURRENT );
			}
			break;
		}
	}

	outbuffer[cursize] = 0;

	return outbuffer;
}
コード例 #5
0
ファイル: stream.c プロジェクト: sunfirefox/foundation_lib
uint64_t stream_read_line_buffer( stream_t* stream, char* dest, unsigned int count, char delimiter )
{
	int i, read, total, limit;

	FOUNDATION_ASSERT( stream );
	FOUNDATION_ASSERT( dest );
	if( !( stream->mode & STREAM_IN ) || ( count < 2 ) )
		return 0;

	FOUNDATION_ASSERT( stream->vtable->read );

	total = 0;

	--count;
	while( !stream_eos( stream ) )
	{
		limit = count - total;
		if( limit > 128 )
			limit = 128;
		if( !limit )
			break;

		if( stream_is_sequential( stream ) ) //Need to read one byte at a time since we can't scan back if overreading
			limit = 1;

		read = (int)stream->vtable->read( stream, dest + total, limit );
		if( !read )
			break;
		for( i = 0; i < read; ++i )
		{
			if( dest[total+i] == delimiter )
				break;
		}
		total += i;
		if( i < read )
		{
			if( ( i + 1 ) < read )
			{
				FOUNDATION_ASSERT( !stream_is_sequential( stream ) ); //Sequential should never end up here reading one byte at a time
				stream_seek( stream, 1 + i - read, STREAM_SEEK_CURRENT );
			}
			break;
		}
	}

	dest[total] = 0;

	return total;
}
コード例 #6
0
ファイル: main.c プロジェクト: rampantpixels/foundation_lib
int
hashify_generate_preamble(stream_t* output_file, string_t output_filename) {
	//Read and preserve everything before #pragma once in case it contains header comments to be preserved
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];
	size_t capacity = 1024;
	string_t preamble = string_allocate(0, capacity);
	stream_t* prev_file = stream_open(STRING_ARGS(output_filename), STREAM_IN);

	memset(line_buffer, 0, sizeof(line_buffer));
	while (prev_file && !stream_eos(prev_file)) {
		string_t line;
		string_const_t stripped_line;

		line = stream_read_line_buffer(prev_file, line_buffer, sizeof(line_buffer), '\n');
		stripped_line = string_strip(STRING_ARGS(line), STRING_CONST("\n\r"));

		if ((string_find_string(STRING_ARGS(stripped_line), STRING_CONST("pragma"), 0) != STRING_NPOS) &&
		        (string_find_string(STRING_ARGS(stripped_line), STRING_CONST("once"), 0) != STRING_NPOS))
			break;

		if (preamble.length + stripped_line.length + 1 >= capacity) {
			size_t newcapacity = capacity + 1024 + stripped_line.length;
			preamble.str = memory_reallocate(preamble.str, newcapacity, 0, capacity);
			capacity = newcapacity;
		}

		preamble = string_append(STRING_ARGS(preamble), capacity, STRING_ARGS(stripped_line));
		if (line.length < sizeof(line_buffer))
			preamble = string_append(STRING_ARGS(preamble), capacity, STRING_CONST(STRING_NEWLINE));
	}
	stream_deallocate(prev_file);

	stream_seek(output_file, 0, STREAM_SEEK_BEGIN);
	if (preamble.length)
		stream_write_string(output_file, STRING_ARGS(preamble));
	stream_write_string(output_file, STRING_CONST(
	                        "#pragma once\n\n"
	                        "#include <foundation/hash.h>\n\n"
	                        "/* ****** AUTOMATICALLY GENERATED, DO NOT EDIT ******\n"
	                        "    Edit corresponding definitions file and rerun\n"
	                        "    the foundation hashify tool to update this file */\n\n"
	                    ));

	string_deallocate(preamble.str);

	return 0;
}
コード例 #7
0
ファイル: stream.c プロジェクト: haifenghuang/foundation_lib
string_t
stream_read_line_buffer(stream_t* stream, char* dest, size_t count, char delimiter) {
	size_t i, read, total, limit, hardlimit;

	if (!(stream->mode & STREAM_IN) || !dest || (count < 2)) {
		if (dest && count)
			dest[0] = 0;
		return (string_t) { dest, 0 };
	}

	total = 0;
	hardlimit = stream_is_sequential(stream) ? 1 : 128;
	//Need to read one byte at a time since we can't scan back if overreading in sequential streams

	--count;
	while (!stream_eos(stream)) {
		limit = count - total;
		if (limit > hardlimit)
			limit = hardlimit;
		if (!limit)
			break;

		//This will initialize range [total,total+read) in dest array, making
		//access of potentially uninitialized dest array safe (see coverity markup below)
		read = stream->vtable->read(stream, dest + total, limit);
		if (!read)
			break;
		for (i = 0; i < read; ++i) {
			/* coverity[read_parm] */
			if (dest[total + i] == delimiter)
				break;
		}
		total += i;
		if (i < read) {
			if ((i + 1) < read) {
				//Sequential should never end up here reading one byte at a time
				FOUNDATION_ASSERT(!stream_is_sequential(stream));
				stream_seek(stream, (ssize_t)(1 + i) - (ssize_t)read, STREAM_SEEK_CURRENT);
			}
			break;
		}
	}

	dest[total] = 0;

	return (string_t) { dest, total };
}
コード例 #8
0
ファイル: import.c プロジェクト: rampantpixels/render_lib
static renderimport_type_t
render_import_shader_guess_type(stream_t* stream) {
	renderimport_type_t type = IMPORTTYPE_UNKNOWN;
	char buffer[1024];
	while (!stream_eos(stream)) {
		string_t line = stream_read_line_buffer(stream, buffer, sizeof(buffer), '\n');
		if (string_find_string(STRING_ARGS(line), STRING_CONST("gl_FragColor"), 0) != STRING_NPOS) {
			type = IMPORTTYPE_GLSL_PIXELSHADER;
			break;
		}
		else if (string_find_string(STRING_ARGS(line), STRING_CONST("gl_Position"), 0) != STRING_NPOS) {
			type = IMPORTTYPE_GLSL_VERTEXSHADER;
			break;
		}
	}

	stream_seek(stream, 0, STREAM_SEEK_BEGIN);

	return type;
}
コード例 #9
0
ファイル: main.c プロジェクト: apprisi/foundation_lib
int bin2hex_process_file( stream_t* input, stream_t* output, int columns )
{
    uint8_t block[512];
    int64_t read, byte;

    if( !columns )
        columns = 32;
    if( columns > 512 )
        columns = 512;

    while( !stream_eos( input ) )
    {
        read = stream_read( input, block, columns );
        if( !read )
            break;

        for( byte = 0; byte < read; ++byte )
            stream_write_format( output, "0x%02x, ", (unsigned int)block[byte] );
        stream_write_endl( output );
    }
    return BIN2HEX_RESULT_OK;
}
コード例 #10
0
ファイル: main.c プロジェクト: rampantpixels/foundation_lib
int
hashify_read_hashes(stream_t* file, hashify_string_t** hashes) {
	//Read in hashes in file
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];
	string_const_t tokens[32];

	memset(line_buffer, 0, sizeof(line_buffer));
	do {
		string_t line = stream_read_line_buffer(file, line_buffer, sizeof(line_buffer), '\n');
		string_const_t stripped_line = string_strip(STRING_ARGS(line), STRING_CONST("\n\r"));
		if ((string_find_string(STRING_ARGS(stripped_line), STRING_CONST("define"), 0) != STRING_NPOS) &&
		        (string_find_string(STRING_ARGS(stripped_line), STRING_CONST("static_hash"), 0) != STRING_NPOS)) {
			//Format is: #define HASH_<hashstring> static_hash_string( "<string>", 0x<hashvalue>ULL )
			size_t num_tokens = string_explode(STRING_ARGS(stripped_line), STRING_CONST(" \t"), tokens, 32,
			                                   false);

			if (num_tokens >= 6) {
				hashify_string_t hash_string;
				string_const_t stripped = string_strip(STRING_ARGS(tokens[3]), STRING_CONST(","));
				stripped = string_strip(STRING_ARGS(stripped), STRING_CONST("\""));
				hash_string.string = string_copy(hash_string.buffer, HASHIFY_STRING_LENGTH, STRING_ARGS(stripped));
				hash_string.hash = string_to_uint64(STRING_ARGS(tokens[4]), true);

				if (hash(STRING_ARGS(hash_string.string)) != hash_string.hash) {
					log_errorf(0, ERROR_INVALID_VALUE,
					           STRING_CONST("  hash output file is out of date, %.*s is set to 0x%" PRIx64 " but should be 0x%"
					                        PRIx64),
					           STRING_FORMAT(hash_string.string), hash_string.hash, hash(STRING_ARGS(hash_string.string)));
					return HASHIFY_RESULT_OUTPUT_FILE_OUT_OF_DATE;
				}

				array_push_memcpy(*hashes, &hash_string);
			}
		}
	}
	while (!stream_eos(file));

	return 0;
}
コード例 #11
0
ファイル: main.c プロジェクト: NocturnDragon/foundation_lib
int hashify_read_hashes( stream_t* file, hashify_string_t** hashes )
{
	//Read in hashes in file
	char* line;
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];

	do
	{
		stream_read_line_buffer( file, line_buffer, HASHIFY_LINEBUFFER_LENGTH-1, '\n' );
		line = string_strip( line_buffer, "\n\r" );
		if( ( string_find_string( line, "define", 0 ) != STRING_NPOS ) && ( string_find_string( line, "static_hash", 0 ) != STRING_NPOS ) )
		{
			//Format is: #define HASH_<hashstring> static_hash_string( "<string>", 0x<hashvalue>ULL )
			char** tokens = string_explode( line, " \t", false );

			if( array_size( tokens ) >= 6 )
			{
				hashify_string_t hash_string;

				string_copy( hash_string.string, string_strip( string_strip( tokens[3], "," ), "\"" ), HASHIFY_STRING_LENGTH );
				hash_string.hash = string_to_uint64( tokens[4], true );

				if( hash( hash_string.string, string_length( hash_string.string ) ) != hash_string.hash )
				{
					log_errorf( ERROR_INVALID_VALUE, "  hash output file is out of date, %s is set to 0x%llx but should be 0x%llx ", hash_string.string, hash_string.hash, hash( hash_string.string, string_length( hash_string.string ) ) );
					string_array_deallocate( tokens );
					return HASHIFY_RESULT_OUTPUT_FILE_OUT_OF_DATE;
				}

				array_push_memcpy( *hashes, &hash_string );
			}

			string_array_deallocate( tokens );
		}
	} while( !stream_eos( file ) );

	return 0;
}
コード例 #12
0
ファイル: main.c プロジェクト: NocturnDragon/foundation_lib
int hashify_generate_preamble( stream_t* output_file )
{
	//Read and preserve everything before #pragma once in case it contains header comments to be preserved
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];
	char* preamble = 0;

	while( !stream_eos( output_file ) )
	{
		char* line;
		uint64_t read;

		read = stream_read_line_buffer( output_file, line_buffer, HASHIFY_LINEBUFFER_LENGTH-1, '\n' );
		line = string_strip( line_buffer, "\n\r" );

		if( ( string_find_string( line, "pragma", 0 ) != STRING_NPOS ) && ( string_find_string( line, "once", 0 ) != STRING_NPOS ) )
			break;

		preamble = string_append( preamble, line );
		if( read < HASHIFY_LINEBUFFER_LENGTH )
			preamble = string_append( preamble, "\n" );
	}

	stream_seek( output_file, 0, STREAM_SEEK_BEGIN );
	stream_write_string( output_file, preamble );
	stream_write_string( output_file,
		"#pragma once\n\n"
		"#include <foundation/foundation.h>\n\n"
		"/* ****** AUTOMATICALLY GENERATED, DO NOT EDIT ******\n"
		"    Edit corresponding definitions file and rerun\n"
		"    the foundation hashify tool to update this file */\n\n"
	);

	string_deallocate( preamble );
	
	return 0;
}
コード例 #13
0
ファイル: import.c プロジェクト: rampantpixels/render_lib
static int
render_import_shader(stream_t* stream, const uuid_t uuid) {
	char buffer[1024];
	char pathbuf[BUILD_MAX_PATHLEN];
	resource_source_t source;
	resource_platform_t platformdecl = {-1, -1, -1, -1, -1, -1};
	uint64_t platform;
	tick_t timestamp;
	int ret = 0;

	resource_source_initialize(&source);
	resource_source_read(&source, uuid);

	platform = resource_platform(platformdecl);
	timestamp = time_system();

	while (!stream_eos(stream)) {
		uuid_t shaderuuid;
		string_const_t target, ref, fullpath;
		string_t line = stream_read_line_buffer(stream, buffer, sizeof(buffer), '\n');
		string_split(STRING_ARGS(line), STRING_CONST(" \t"),
		             &target, &ref, false);

		ref = string_strip(STRING_ARGS(ref), STRING_CONST(STRING_WHITESPACE));
		shaderuuid = string_to_uuid(STRING_ARGS(ref));
		if (uuid_is_null(shaderuuid)) {
			if (path_is_absolute(STRING_ARGS(ref))) {
				fullpath = ref;
			}
			else {
				string_t full;
				string_const_t path = stream_path(stream);
				path = path_directory_name(STRING_ARGS(path));
				full = path_concat(pathbuf, sizeof(pathbuf),
				                   STRING_ARGS(path), STRING_ARGS(ref));
				full = path_absolute(STRING_ARGS(full), sizeof(pathbuf));
				fullpath = string_const(STRING_ARGS(full));
			}

			resource_signature_t sig = resource_import_lookup(STRING_ARGS(fullpath));
			if (uuid_is_null(sig.uuid)) {
				if (!resource_import(STRING_ARGS(fullpath), uuid_null())) {
					log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS,
					          STRING_CONST("Unable to import linked shader: %.*s"),
					          STRING_FORMAT(fullpath));
					ret = -1;
					goto finalize;
				}
				sig = resource_import_lookup(STRING_ARGS(fullpath));
				if (uuid_is_null(sig.uuid)) {
					log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS,
					          STRING_CONST("Import linked shader gave no UUID: %.*s"),
					          STRING_FORMAT(fullpath));
					ret = -1;
					goto finalize;
				}
			}
			shaderuuid = sig.uuid;
		}

		if (!uuid_is_null(shaderuuid)) {
			resource_platform_t targetplatformdecl =
			    render_import_parse_target(STRING_ARGS(target), platformdecl);
			uint64_t targetplatform = resource_platform(targetplatformdecl);

			if (resource_autoimport_need_update(shaderuuid, targetplatform))
				resource_autoimport(shaderuuid);

			const string_const_t uuidstr = string_from_uuid_static(shaderuuid);
			resource_source_set(&source, timestamp, HASH_SHADER,
			                    targetplatform, STRING_ARGS(uuidstr));
			resource_source_set_dependencies(uuid, targetplatform, &shaderuuid, 1);
		}
	}

	resource_source_set(&source, timestamp, HASH_RESOURCE_TYPE,
	                    0, STRING_CONST("shader"));

	if (!resource_source_write(&source, uuid, false)) {
		string_const_t uuidstr = string_from_uuid_static(uuid);
		log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Failed writing imported shader: %.*s"),
		          STRING_FORMAT(uuidstr));
		ret = -1;
		goto finalize;
	}
	else {
		string_const_t uuidstr = string_from_uuid_static(uuid);
		log_infof(HASH_RESOURCE, STRING_CONST("Wrote imported shader: %.*s"),
		          STRING_FORMAT(uuidstr));
	}

finalize:
	resource_source_finalize(&source);

	return 0;
}
コード例 #14
0
ファイル: stream.c プロジェクト: sunfirefox/foundation_lib
uint128_t stream_md5( stream_t* stream )
{
	int64_t cur, ic, offset, lastc, num;
	md5_t* md5;
	uint128_t ret = {0};
	unsigned char buf[1025];
	bool ignore_lf = false;

	FOUNDATION_ASSERT( stream );
	if( stream->vtable->md5 )
		return stream->vtable->md5( stream );

	if( !stream || stream_is_sequential( stream ) || !( stream->mode & STREAM_IN ) )
		return ret;

	FOUNDATION_ASSERT( stream->vtable->read );

	cur = stream_tell( stream );
	stream_seek( stream, 0, STREAM_SEEK_BEGIN );

	md5 = md5_allocate();

	while( !stream_eos( stream ) )
	{
		num = (int64_t)stream->vtable->read( stream, buf, 1024 );
		if( !num )
			continue;
		if( stream->mode & STREAM_BINARY )
			md5_digest_raw( md5, buf, (size_t)num );
		else
		{
			//If last buffer ended with CR, ignore a leading LF
			offset = 0;
			lastc = 0;
			if( ignore_lf && ( buf[0] == '\n' ) )
				offset = 1;
			ignore_lf = false;

			//Treat all line endings (LF, CR, CR+LF) as Unix style LF. If file has mixed line endings (for example, one line ending in a single CR and next ending in a single LF), it will not work!
			for( ic = 0; ic < num; ++ic )
			{
				bool was_cr = ( buf[ic] == '\r' );
				bool was_lf = ( buf[ic] == '\n' );
				if( was_cr || was_lf )
				{
					if( was_cr && ( ic >= 1023 ) )
						ignore_lf = true;
					buf[ic] = '\n';
					md5_digest_raw( md5, buf + lastc, (size_t)( ic - lastc + 1 ) ); //Include the LF
					if( was_cr && ( buf[ic+1] == '\n' ) ) //Check for CR+LF
						++ic;
					lastc = ic + 1;
				}
			}
			if( lastc < num )
				md5_digest_raw( md5, buf + lastc, (size_t)( num - lastc ) );
		}
	}
	
	stream_seek( stream, cur, STREAM_SEEK_BEGIN );

	md5_finalize( md5 );
	ret = md5_get_digest_raw( md5 );

	md5_deallocate( md5 );

	return ret;
}
コード例 #15
0
ファイル: stream.c プロジェクト: sunfirefox/foundation_lib
uint64_t stream_read_string_buffer( stream_t* stream, char* outbuffer, uint64_t size )
{
	char buffer[128];
	int cursize = 0;
	int read, i;
	bool binary = stream_is_binary( stream );

	FOUNDATION_ASSERT( stream );
	if( !( stream->mode & STREAM_IN ) || !size )
		return 0;

	FOUNDATION_ASSERT( stream->vtable->read );
	
	--size;

	//TODO: Implement per-byte reading for sequential streams
	if( !binary )
	{
		//Consume whitespace
		while( !stream_eos( stream ) )
		{
			read = (int)stream->vtable->read( stream, buffer, 16 );
			if( !read )
				break;
			for( i = 0; i < read; ++i )
			{
				char c = buffer[i];
				if( ( c != ' ' ) && ( c != '\n' ) && ( c != '\r' ) && ( c != '\t' ) )
					break;
			}
			if( i < read )
			{
				stream_seek( stream, i - read, STREAM_SEEK_CURRENT );
				break;
			}
		}
	}

	while( !stream_eos( stream ) && ( cursize < (int)size ) )
	{
		read = (int)stream->vtable->read( stream, buffer, 128 );
		if( !read )
			break;
		for( i = 0; i < read; ++i )
		{
			char c = buffer[i];
			if( !c )
				break;
			if( !binary && ( ( c == ' ' ) || ( c == '\n' ) || ( c == '\r' ) || ( c == '\t' ) ) )
				break;
		}
		if( !i )
			break;
		if( cursize + i > (int)size )
			i = (int)size - cursize;
		memcpy( outbuffer + cursize, buffer, i );
		cursize += i;
		if( i < 128 )
		{
			if( ( i + 1 ) < read )
				stream_seek( stream, 1 + i - read, STREAM_SEEK_CURRENT );
			break;
		}
	}
	
	outbuffer[cursize] = 0;

	return cursize;
}
コード例 #16
0
ファイル: stream.c プロジェクト: sunfirefox/foundation_lib
char* stream_read_string( stream_t* stream )
{
	char buffer[128];
	char* outbuffer;
	int outsize = 128;
	int cursize = 0;
	int read, i;
	bool binary = stream_is_binary( stream );

	FOUNDATION_ASSERT( stream );
	if( !( stream->mode & STREAM_IN ) )
		return 0;

	FOUNDATION_ASSERT( stream->vtable->read );

	outbuffer = memory_allocate( outsize, 0, MEMORY_PERSISTENT );

	if( stream_is_sequential( stream ) )
	{
		//Single byte reading since we can't seek backwards (and don't want to block on network sockets)
		char c;
		if( !binary )
		{
			//Consume whitespace
			while( !stream_eos( stream ) )
			{
				read = (int)stream->vtable->read( stream, &c, 1 );
				if( !read )
					break;
				if( ( c != ' ' ) && ( c != '\n' ) && ( c != '\r' ) && ( c != '\t' ) )
				{
					outbuffer[cursize++] = c;
					break;
				}
			}
		}

		while( !stream_eos( stream ) )
		{
			read = (int)stream->vtable->read( stream, &c, 1 );
			if( !read )
				break;
			if( !c )
				break;
			if( !binary && ( ( c == ' ' ) || ( c == '\n' ) || ( c == '\r' ) || ( c == '\t' ) ) )
				break;
			if( cursize + 1 > outsize )
			{
				outsize += 512;
				outbuffer = memory_reallocate( outbuffer, outsize, 0, cursize );
			}
			outbuffer[cursize++] = c;
		}
	
		outbuffer[cursize] = 0;
	}
	else
	{
		if( !binary )
		{
			//Consume whitespace
			while( !stream_eos( stream ) )
			{
				read = (int)stream->vtable->read( stream, buffer, 16 );
				if( !read )
					break;
				for( i = 0; i < read; ++i )
				{
					char c = buffer[i];
					if( ( c != ' ' ) && ( c != '\n' ) && ( c != '\r' ) && ( c != '\t' ) )
						break;
				}
				if( i < read )
				{
					stream_seek( stream, i - read, STREAM_SEEK_CURRENT );
					break;
				}
			}
		}

		while( !stream_eos( stream ) )
		{
			read = (int)stream->vtable->read( stream, buffer, 128 );
			if( !read )
				break;
			for( i = 0; i < read; ++i )
			{
				char c = buffer[i];
				if( !c )
					break;
				if( !binary && ( ( c == ' ' ) || ( c == '\n' ) || ( c == '\r' ) || ( c == '\t' ) ) )
					break;
			}
			if( i )
			{
				if( cursize + i > outsize )
				{
					outsize += 512;
					outbuffer = memory_reallocate( outbuffer, outsize, 0, cursize );
				}
				memcpy( outbuffer + cursize, buffer, i );
				cursize += i;
			}
			if( i < 128 )
			{
				if( ( i + 1 ) < read )
					stream_seek( stream, 1 + i - read, STREAM_SEEK_CURRENT );
				break;
			}
		}
	
		outbuffer[cursize] = 0;
	}
	return outbuffer;
}
コード例 #17
0
ファイル: stream.c プロジェクト: haifenghuang/foundation_lib
string_t
stream_read_string(stream_t* stream) {
	char buffer[128];
	char* outbuffer = buffer;
	size_t outsize = sizeof(buffer);
	size_t cursize = 0;
	size_t read, i;
	bool binary = stream_is_binary(stream);

	if (!(stream->mode & STREAM_IN))
		return (string_t) { 0, 0 };

	if (stream_is_sequential(stream)) {
		//Single byte reading since we can't seek backwards (and don't want to block on network sockets)
		char c;
		if (!binary) {
			//Consume whitespace
			while (!stream_eos(stream)) {
				read = stream->vtable->read(stream, &c, 1);
				if (!read)
					break;
				if ((c != ' ') && (c != '\n') && (c != '\r') && (c != '\t')) {
					buffer[cursize++] = c;
					break;
				}
			}
		}

		if (cursize > 0) {
			while (!stream_eos(stream)) {
				read = stream->vtable->read(stream, &c, 1);
				if (!read)
					break;
				if (!c)
					break;
				if (!binary && ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')))
					break;
				if (cursize + 1 >= outsize) {
					outsize += 512;
					if (outbuffer != buffer) {
						outbuffer = memory_reallocate(outbuffer, outsize, 0, cursize);
					}
					else {
						outbuffer = memory_allocate(0, outsize, 0, MEMORY_PERSISTENT);
						memcpy(outbuffer, buffer, sizeof(buffer));
					}
				}
				outbuffer[cursize++] = c;
			}

			outbuffer[cursize] = 0; //lint !e661
		}
	}
	else {
		if (!binary) {
			//Consume whitespace
			while (!stream_eos(stream)) {
				read = stream->vtable->read(stream, buffer, 16);
				if (!read)
					break;
				for (i = 0; i < read; ++i) {
					char c = buffer[i];
					if ((c != ' ') && (c != '\n') && (c != '\r') && (c != '\t'))
						break;
				}
				if (i < read) {
					stream_seek(stream, (ssize_t)i - (ssize_t)read, STREAM_SEEK_CURRENT);
					break;
				}
			}
		}

		while (!stream_eos(stream)) {
			if (outbuffer != buffer)
				read = stream->vtable->read(stream, buffer, sizeof(buffer));
			else
				read = stream->vtable->read(stream, buffer + cursize, sizeof(buffer) - cursize);
			if (!read)
				break;
			for (i = 0; i < read; ++i) {
				char c = buffer[i];
				if (!c)
					break;
				if (!binary && ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')))
					break;
			}
			if (i) {
				if (cursize + i >= outsize) {
					outsize += 512;
					if (outbuffer != buffer) {
						outbuffer = memory_reallocate(outbuffer, outsize, 0, cursize);
					}
					else {
						FOUNDATION_ASSERT(cursize == 0);   //Or internal assumptions about code flow is incorrect
						outbuffer = memory_allocate(0, outsize, 0, MEMORY_PERSISTENT);
						memcpy(outbuffer, buffer, i);
					}
				}
				else if (outbuffer != buffer)
					memcpy(outbuffer + cursize, buffer, i);
				cursize += i;
			}
			if (i < sizeof(buffer)) {
				if ((i + 1) < read)
					stream_seek(stream, (ssize_t)(1 + i) - (ssize_t)read, STREAM_SEEK_CURRENT);
				break;
			}
		}

		outbuffer[cursize] = 0;
	}

	if (outbuffer == buffer) {
		if (cursize == 0)
			return (string_t) { 0, 0 };
		outbuffer = memory_allocate(0, cursize + 1, 0, MEMORY_PERSISTENT);
		memcpy(outbuffer, buffer, cursize);
		outbuffer[cursize] = 0;
	}

	return (string_t) { outbuffer, cursize };
}
コード例 #18
0
ファイル: stream.c プロジェクト: haifenghuang/foundation_lib
uint128_t
stream_md5(stream_t* stream) {
	size_t cur, ic, lastc, num, limit;
	md5_t md5;
	uint128_t ret = uint128_null();
	unsigned char buf[1025];
	bool ignore_lf = false;

	if (stream->vtable->md5)
		return stream->vtable->md5(stream);

	if (stream_is_sequential(stream) || !(stream->mode & STREAM_IN))
		return ret;

	cur = stream_tell(stream);
	stream_seek(stream, 0, STREAM_SEEK_BEGIN);

	md5_initialize(&md5);
	limit = sizeof(buf)-1;
	buf[limit] = 0;

	while (!stream_eos(stream)) {
		num = stream->vtable->read(stream, buf, limit);
		if (!num)
			continue;
		if (stream->mode & STREAM_BINARY)
			md5_digest(&md5, buf, (size_t)num);
		else {
			//If last buffer ended with CR, ignore a leading LF
			lastc = 0;
			if (ignore_lf && (buf[0] == '\n'))
				lastc = 1;
			ignore_lf = false;

			//Digest one line at a time
			//Treat all line endings (LF, CR, CR+LF) as Unix style LF. If file has mixed line endings
			//(for example, one line ending in a single CR and next is empty and ending in a single LF),
			//it will not work!
			/*lint -e{850} */
			for (ic = lastc; ic < num && ic < limit; ++ic) {
				bool was_cr = (buf[ic] == '\r');
				bool was_lf = (buf[ic] == '\n');
				if (was_cr || was_lf) {
					if (was_cr && (ic == limit-1))
						ignore_lf = true; //Make next buffer ignore leading LF as it is part of CR+LF
					buf[ic] = '\n';
					md5_digest(&md5, buf + lastc, (size_t)((ic - lastc) + 1)); //Include the LF
					if (was_cr && (buf[ic + 1] == '\n'))  //Check for CR+LF
						++ic;
					lastc = ic + 1;
				}
			}
			if (lastc < num)
				md5_digest(&md5, buf + lastc, (size_t)(num - lastc));
		}
	}

	stream_seek(stream, (ssize_t)cur, STREAM_SEEK_BEGIN);

	md5_digest_finalize(&md5);
	ret = md5_get_digest_raw(&md5);
	md5_finalize(&md5);

	return ret;
}
コード例 #19
0
unsigned int stacktrace_capture( void** trace, unsigned int max_depth, unsigned int skip_frames )
{
	unsigned int num_frames = 0;
	
	if( !trace )
		return 0;

	if( !max_depth )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;
		
	if( max_depth > BUILD_SIZE_STACKTRACE_DEPTH )
		max_depth = BUILD_SIZE_STACKTRACE_DEPTH;

	if( !_stackwalk_initialized )
	{
		if( !_initialize_stackwalker() )
		{
			memset( trace, 0, sizeof( void* ) * max_depth );
			return num_frames;
		}
	}
		
#if FOUNDATION_PLATFORM_WINDOWS && ( FOUNDATION_COMPILER_MSVC || FOUNDATION_COMPILER_INTEL )
	// Add 1 skip frame for this function call
	++skip_frames;
#  if USE_CAPTURESTACKBACKTRACE
	if( CallRtlCaptureStackBackTrace )
	{
		void* local_trace[BUILD_SIZE_STACKTRACE_DEPTH];
		if( max_depth + skip_frames > BUILD_SIZE_STACKTRACE_DEPTH )
			max_depth = BUILD_SIZE_STACKTRACE_DEPTH - skip_frames;
		num_frames = (unsigned int)CallRtlCaptureStackBackTrace( skip_frames, max_depth, local_trace, 0 );
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, local_trace, sizeof( void* ) * num_frames );
		memset( trace + num_frames, 0, sizeof( void* ) * ( max_depth - num_frames ) );
	}
	else
	{
#  else
	{
#  endif
#  if FOUNDATION_PLATFORM_ARCH_X86_64
	// Raise an exception so helper has access to context record.
	__try
	{
		RaiseException(	0,			// Application-defined exception code.
						0,			// Zero indicates continuable exception.
						0,			// Number of arguments in args array (ignored if args is null)
						0 );		// Array of arguments
	}
	__except( _capture_stack_trace_helper( trace, max_depth, skip_frames, (GetExceptionInformation())->ContextRecord ) )
	{
	}
#  else
	// Use a bit of inline assembly to capture the information relevant to stack walking which is
	// basically EIP and EBP.
	CONTEXT context;
	memset( &context, 0, sizeof( CONTEXT ) );
	context.ContextFlags = CONTEXT_FULL;

	log_warnf( WARNING_DEPRECATED, "********** REIMPLEMENT FALLBACK STACKTRACE **********" );
	/* Use a fake function call to pop the return address and retrieve EIP.*/
	__asm
	{
		call FakeStackTraceCall
		FakeStackTraceCall: 
		pop eax
		mov context.Eip, eax
		mov context.Ebp, ebp
		mov context.Esp, esp
	}

	// Capture the back trace.
	_capture_stack_trace_helper( trace, max_depth, skip_frames, &context );
#  endif
	}
#elif FOUNDATION_PLATFORM_APPLE
	//TODO: Implement
#elif FOUNDATION_PLATFORM_POSIX
	// Add 1 skip frames for this function call
	skip_frames += 1;

	void* localframes[BUILD_SIZE_STACKTRACE_DEPTH];
	num_frames = (unsigned int)backtrace( localframes, BUILD_SIZE_STACKTRACE_DEPTH );

	if( num_frames > skip_frames )
	{
		num_frames -= skip_frames;
		if( num_frames > max_depth )
			num_frames = max_depth;
		memcpy( trace, localframes + skip_frames, sizeof( void* ) * num_frames );
	}
	else
		trace[0] = 0;
#endif

	return num_frames;
}


static bool _symbol_resolve_initialized = false;

static bool _initialize_symbol_resolve()
{
	if( _symbol_resolve_initialized )
		return true;

#if FOUNDATION_PLATFORM_WINDOWS
	{
		unsigned int options;
		void* dll = LoadLibraryA( "PSAPI.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallEnumProcesses = (EnumProcessesFn)GetProcAddress( dll, "EnumProcesses" );
		CallEnumProcessModules = (EnumProcessModulesFn)GetProcAddress(  dll, "EnumProcessModules" );
		CallGetModuleFileNameEx = (GetModuleFileNameExFn)GetProcAddress(  dll, "GetModuleFileNameExA" );
		CallGetModuleBaseName = (GetModuleBaseNameFn)GetProcAddress(  dll, "GetModuleBaseNameA" );
		CallGetModuleInformation = (GetModuleInformationFn)GetProcAddress( dll, "GetModuleInformation" );

		if( !CallEnumProcesses || !CallEnumProcessModules || !CallGetModuleFileNameEx || !CallGetModuleBaseName || !CallGetModuleInformation )
			return _symbol_resolve_initialized;

		dll = LoadLibraryA( "DBGHELP.DLL" );
		if( !dll )
			return _symbol_resolve_initialized;

		CallSymInitialize = (SymInitializeFn)GetProcAddress( dll, "SymInitialize" );
		CallSymSetOptions = (SymSetOptionsFn)GetProcAddress( dll, "SymSetOptions" );
		CallSymGetOptions = (SymGetOptionsFn)GetProcAddress( dll, "SymGetOptions" );
		CallSymLoadModule64 = (SymLoadModule64Fn)GetProcAddress( dll, "SymLoadModule64" );
		CallSymSetSearchPath = (SymSetSearchPathFn)GetProcAddress( dll, "SymSetSearchPath" );
		CallSymGetModuleInfo64 = (SymGetModuleInfo64Fn)GetProcAddress( dll, "SymGetModuleInfo64" );
		CallSymGetLineFromAddr64 = (SymGetLineFromAddr64Fn)GetProcAddress( dll, "SymGetLineFromAddr64" );
		CallSymGetSymFromAddr64 = (SymGetSymFromAddr64Fn)GetProcAddress( dll, "SymGetSymFromAddr64" );
		CallSymGetModuleBase64 = (SymGetModuleBase64Fn)GetProcAddress( dll, "SymGetModuleBase64" );
		CallSymFunctionTableAccess64 = (SymFunctionTableAccess64Fn)GetProcAddress( dll, "SymFunctionTableAccess64" );

		if( !CallSymInitialize || !CallSymSetOptions || !CallSymGetOptions || !CallSymLoadModule64 || !CallSymSetSearchPath || !CallSymGetModuleInfo64 || !CallSymGetLineFromAddr64 || !CallSymGetSymFromAddr64  || !CallSymGetModuleBase64 || !CallSymFunctionTableAccess64 )
			return _symbol_resolve_initialized;

		options = CallSymGetOptions();
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_DEBUG;
		options |= SYMOPT_UNDNAME;
		options |= SYMOPT_LOAD_LINES;
		options |= SYMOPT_FAIL_CRITICAL_ERRORS;
		options |= SYMOPT_DEFERRED_LOADS;
		options |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS;
		options |= SYMOPT_EXACT_SYMBOLS;
		options |= SYMOPT_CASE_INSENSITIVE;
		CallSymSetOptions( options );

		CallSymInitialize( GetCurrentProcess(), 0, TRUE );
	}
	
	_load_process_modules();

	_symbol_resolve_initialized = true;

#else
	
	_symbol_resolve_initialized = true;
	
#endif

	return _symbol_resolve_initialized;
}


static NOINLINE char** _resolve_stack_frames( void** frames, unsigned int max_frames )
{
#if FOUNDATION_PLATFORM_WINDOWS
	char**              lines = 0;
	char                symbol_buffer[ sizeof( IMAGEHLP_SYMBOL64 ) + 512 ];
	PIMAGEHLP_SYMBOL64  symbol;
	DWORD               displacement = 0;
	uint64_t            displacement64 = 0;
	unsigned int        iaddr = 0;
	unsigned int        last_error;
	bool                found = false;
	HANDLE              process_handle = GetCurrentProcess();
	int                 buffer_offset = 0;
	bool                last_was_main = false;
	IMAGEHLP_LINE64     line64;
	IMAGEHLP_MODULE64   module64;

	for( iaddr = 0; ( iaddr < max_frames ) && !last_was_main; ++iaddr )
	{
		char* resolved = 0;
		const char* function_name = "??";
		const char* file_name = "??";
		const char* module_name = "??";
		unsigned int line_number = 0;

		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;

		// Initialize symbol.
		symbol = (PIMAGEHLP_SYMBOL64)symbol_buffer;
		memset( symbol, 0, sizeof( symbol_buffer ) );
		symbol->SizeOfStruct = sizeof( symbol_buffer );
		symbol->MaxNameLength = 512;

		// Get symbol from address.
		if( CallSymGetSymFromAddr64 && CallSymGetSymFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement64, symbol ) )
		{
			int offset = 0;
			while( symbol->Name[offset] < 32 )
				++offset;
			function_name = symbol->Name + offset;
		}
		else
		{
			// No symbol found for this address.
			last_error = GetLastError();
		}

		memset( &line64, 0, sizeof( line64 ) );
		line64.SizeOfStruct = sizeof( line64 );
		if( CallSymGetLineFromAddr64 && CallSymGetLineFromAddr64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &displacement, &line64 ) )
		{
			file_name = line64.FileName;
			line_number = line64.LineNumber;
		}

		memset( &module64, 0, sizeof( module64 ) );
		module64.SizeOfStruct = sizeof( module64 );
		if( CallSymGetModuleInfo64 && CallSymGetModuleInfo64( process_handle, (uint64_t)((uintptr_t)frames[iaddr]), &module64 ) )
		{
			int last_slash = STRING_NPOS;
			module_name = module64.ImageName;
			last_slash = string_rfind( module_name, '\\', STRING_NPOS );
			if( last_slash != STRING_NPOS )
				module_name += last_slash + 1;
		}

		resolved = string_format( "[" STRING_FORMAT_POINTER "] %s (%s:%d +%d bytes) [in %s]", frames[iaddr], function_name, file_name, line_number, displacement, module_name );
		array_push( lines, resolved );
	
		if( string_equal( function_name, "main" ) )
			last_was_main = true;
	}

	return lines;

#elif FOUNDATION_PLATFORM_LINUX

	char** addrs = 0;
	char** lines = 0;
	const char** args = 0;
	process_t* proc = process_allocate();
	unsigned int num_frames = 0;
	unsigned int requested_frames = 0;
	bool last_was_main = false;

	if( !string_length( environment_executable_path() ) )
	{
		for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
		{
			//Allow first frame to be null in case of a function call to a null pointer
			if( iaddr && !frames[iaddr] )
				break;
		
			array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]", frames[iaddr] ) );
		}
		return lines;
	}
	
	array_push( args, "-e" );
	array_push( args, environment_executable_path() );
	array_push( args, "-f" );

	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		char* addr = string_format( STRING_FORMAT_POINTER, frames[iaddr] );
		array_push( addrs, addr );
		array_push( args, addr );

		++requested_frames;
	}
	
	process_set_working_directory( proc, environment_initial_working_directory() );
	process_set_executable_path( proc, "/usr/bin/addr2line" );
	process_set_arguments( proc, args, array_size( args ) );
	process_set_flags( proc, PROCESS_ATTACHED | PROCESS_STDSTREAMS );

	process_spawn( proc );

	stream_t* procout = process_stdout( proc );
	while( !stream_eos( procout ) && ( num_frames < requested_frames ) && !last_was_main )
	{
		char* function = stream_read_line( procout, '\n' );
		char* filename = stream_read_line( procout, '\n' );

		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "] %s (%s)",
			frames[num_frames],
			function && string_length( function ) ? function : "??",
			filename && string_length( filename ) ? filename : "??"
		) );
	
		if( string_equal( function, "main" ) )
			last_was_main = true;

		string_deallocate( function );
		string_deallocate( filename );

		++num_frames;
	}
	
	process_wait( proc );
	process_deallocate( proc );
	
	string_array_deallocate( addrs );
	array_deallocate( args );	
	
	return lines;
	
#else

	char** lines = 0;
	for( unsigned int iaddr = 0; iaddr < max_frames; ++iaddr )
	{
		//Allow first frame to be null in case of a function call to a null pointer
		if( iaddr && !frames[iaddr] )
			break;
		
		array_push( lines, string_format( "[" STRING_FORMAT_POINTER "]\n", frames[iaddr] ) );
	}
		
	return lines;

#endif
}
コード例 #20
0
ファイル: config.c プロジェクト: apprisi/foundation_lib
void config_parse( stream_t* stream, hash_t filter_section, bool overwrite )
{
	char* buffer;
	hash_t section = 0;
	hash_t key = 0;
	unsigned int line = 0;

#if BUILD_ENABLE_DEBUG_CONFIG
	log_debugf( HASH_CONFIG, "Parsing config stream: %s", stream_path( stream ) );
#endif
	buffer = memory_allocate_zero( 1024ULL, 0, MEMORY_TEMPORARY );
	while( !stream_eos( stream ) )
	{
		++line;
		stream_read_line_buffer( stream, buffer, 1024, '\n' );
		string_strip( buffer, " \t\n\r" );
		if( !string_length( buffer ) || ( buffer[0] == ';' ) || ( buffer[0] == '#' ) )
			continue;
		if( buffer[0] == '[' )
		{
			//Section declaration
			unsigned int endpos = string_rfind( buffer, ']', string_length( buffer ) - 1 );
			if( ( endpos == STRING_NPOS ) || ( endpos < 1 ) )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid section declaration on line %d in config stream '%s'", line, stream_path( stream ) );
				continue;
			}
			buffer[endpos] = 0;
			section = hash( buffer + 1, endpos - 1 );
#if BUILD_ENABLE_DEBUG_CONFIG
			log_debugf( HASH_CONFIG, "  config: section set to '%s' (0x%llx)", buffer + 1, section );
#endif
		}
		else if( !filter_section || ( filter_section == section ) )
		{
			//name=value declaration
			char* name;
			char* value;
			unsigned int separator = string_find( buffer, '=', 0 );
			if( separator == STRING_NPOS )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', missing assignment operator '=': %s", line, stream_path( stream ), buffer );
				continue;
			}
			
			name = string_strip_substr( buffer, " \t", separator );
			value = string_strip( buffer + separator + 1, " \t" );
			if( !string_length( name ) )
			{
				log_warnf( HASH_CONFIG, WARNING_BAD_DATA, "Invalid value declaration on line %d in config stream '%s', empty name string", line, stream_path( stream ) );
				continue;
			}

			key = hash( name, string_length( name ) );

			if( overwrite || !config_key( section, key, false ) )
			{
#if BUILD_ENABLE_DEBUG_CONFIG
				log_debugf( HASH_CONFIG, "  config: %s (0x%llx) = %s", name, key, value );
#endif

				if( !string_length( value ) )
					config_set_string( section, key, "" );
				else if( string_equal( value, "false" ) )
					config_set_bool( section, key, false );
				else if( string_equal( value, "true" ) )
					config_set_bool( section, key, true );
				else if( ( string_find( value, '.', 0 ) != STRING_NPOS ) && ( string_find_first_not_of( value, "0123456789.", 0 ) == STRING_NPOS ) && ( string_find( value, '.', string_find( value, '.', 0 ) + 1 ) == STRING_NPOS ) ) //Exactly one "."
					config_set_real( section, key, string_to_real( value ) );
				else if( string_find_first_not_of( value, "0123456789", 0 ) == STRING_NPOS )
					config_set_int( section, key, string_to_int64( value ) );
				else
					config_set_string( section, key, value );
			}
		}
	}
	memory_deallocate( buffer );
}
コード例 #21
0
ファイル: main.c プロジェクト: NocturnDragon/foundation_lib
int hashify_write_file( stream_t* generated_file, const char* output_filename )
{
	bool need_update = false;
	stream_t* output_file = 0;
	int result = HASHIFY_RESULT_OK;

	output_file = stream_open( output_filename, STREAM_OUT | STREAM_IN );
	if( !output_file )
	{
		need_update = true;
		output_file = stream_open( output_filename, STREAM_OUT );
		if( !output_file )
		{
			log_warnf( WARNING_BAD_DATA, "Unable to open output file: %s", output_filename );
			return HASHIFY_RESULT_MISSING_OUTPUT_FILE;
		}
	}

	if( !need_update )
		need_update = !uint128_equal( stream_md5( generated_file ), stream_md5( output_file ) );

	if( need_update )
	{
		char local_buffer[1024];
		uint64_t read = 0;
		uint64_t written = 0;
		uint64_t total_written = 0;

		stream_seek( generated_file, 0, STREAM_SEEK_BEGIN );
		stream_seek( output_file, 0, STREAM_SEEK_BEGIN );

		while( !stream_eos( generated_file ) )
		{
			read = stream_read( generated_file, local_buffer, 1024 );
			if( !read )
				break;

			written = stream_write( output_file, local_buffer, read );
			total_written += written;

			if( written != read )
			{
				log_errorf( ERROR_SYSTEM_CALL_FAIL, "Unable to write to output file '%s': %llu of %llu bytes written", output_filename, written, read );
				result = HASHIFY_RESULT_OUTPUT_FILE_WRITE_FAIL;
				break;
			}
		}

		if( result == HASHIFY_RESULT_OK )
		{
			stream_truncate( output_file, total_written );
			log_infof( "  wrote %s : %llu bytes", output_filename, total_written );
		}
	}
	else
	{
		log_infof( "  hash file already up to date" );
	}

	stream_deallocate( output_file );

	return result;
}
コード例 #22
0
ファイル: import.c プロジェクト: rampantpixels/render_lib
static int
render_import_program(stream_t* stream, const uuid_t uuid) {
	char buffer[1024];
	char pathbuf[BUILD_MAX_PATHLEN];
	resource_source_t source;
	resource_platform_t platformdecl = {-1, -1, -1, -1, -1, -1};
	uint64_t platform;
	tick_t timestamp;
	int ret = 0;

	resource_source_initialize(&source);
	resource_source_read(&source, uuid);

	platform = resource_platform(platformdecl);
	timestamp = time_system();

	while (!stream_eos(stream)) {
		string_const_t type, ref;
		string_const_t fullpath;
		string_const_t uuidstr;
		uuid_t shaderuuid;
		hash_t typehash;
		string_t line = stream_read_line_buffer(stream, buffer, sizeof(buffer), '\n');
		string_split(STRING_ARGS(line), STRING_CONST(" \t"),
		             &type, &ref, false);

		type = string_strip(STRING_ARGS(type), STRING_CONST(STRING_WHITESPACE));
		ref = string_strip(STRING_ARGS(ref), STRING_CONST(STRING_WHITESPACE));
		if (!type.length || !ref.length)
			continue;

		typehash = hash(STRING_ARGS(type));
		if ((typehash != HASH_VERTEXSHADER) && (typehash != HASH_PIXELSHADER)) {
			log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Ignore invalid line: %.*s"),
			          STRING_FORMAT(line));
			continue;
		}

		shaderuuid = string_to_uuid(STRING_ARGS(ref));
		if (uuid_is_null(shaderuuid)) {
			if (path_is_absolute(STRING_ARGS(ref))) {
				fullpath = ref;
			}
			else {
				string_t full;
				string_const_t path = stream_path(stream);
				path = path_directory_name(STRING_ARGS(path));
				full = path_concat(pathbuf, sizeof(pathbuf),
				                   STRING_ARGS(path), STRING_ARGS(ref));
				full = path_absolute(STRING_ARGS(full), sizeof(pathbuf));
				fullpath = string_const(STRING_ARGS(full));
			}

			resource_signature_t sig = resource_import_lookup(STRING_ARGS(fullpath));
			if (uuid_is_null(sig.uuid)) {
				if (!resource_import(STRING_ARGS(fullpath), uuid_null())) {
					log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Unable to import linked shader: %.*s"),
					          STRING_FORMAT(fullpath));
					ret = -1;
					goto finalize;
				}
				sig = resource_import_lookup(STRING_ARGS(fullpath));
				if (uuid_is_null(sig.uuid)) {
					log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS,
					          STRING_CONST("Import linked shader gave no UUID: %.*s"),
					          STRING_FORMAT(fullpath));
					ret = -1;
					goto finalize;
				}
			}
			shaderuuid = sig.uuid;
		}

		if (!uuid_is_null(shaderuuid)) {
			uuidstr = string_from_uuid_static(shaderuuid);
			resource_source_set(&source, timestamp, typehash,
			                    platform, STRING_ARGS(uuidstr));
		}
	}

	resource_source_set(&source, timestamp, HASH_RESOURCE_TYPE,
	                    0, STRING_CONST("program"));

	if (!resource_source_write(&source, uuid, false)) {
		string_const_t uuidstr = string_from_uuid_static(uuid);
		log_warnf(HASH_RESOURCE, WARNING_SUSPICIOUS, STRING_CONST("Failed writing imported program: %.*s"),
		          STRING_FORMAT(uuidstr));
		ret = -1;
		goto finalize;
	}
	else {
		string_const_t uuidstr = string_from_uuid_static(uuid);
		log_infof(HASH_RESOURCE, STRING_CONST("Wrote imported program: %.*s"),
		          STRING_FORMAT(uuidstr));
	}

finalize:
	resource_source_finalize(&source);

	return ret;
}
コード例 #23
0
ファイル: stream.c プロジェクト: haifenghuang/foundation_lib
string_t
stream_read_string_buffer(stream_t* stream, char* outbuffer, size_t size) {
	char buffer[128];
	size_t cursize = 0;
	size_t read, i;
	bool binary = stream_is_binary(stream);

	if (!(stream->mode & STREAM_IN) || !outbuffer || !size) {
		if (outbuffer && size)
			outbuffer[0] = 0;
		return (string_t) { outbuffer, 0 };
	}

	--size;

	if (stream_is_sequential(stream)) {
		//Single byte reading since we can't seek backwards (and don't want to block on network sockets)
		char c;
		if (!binary) {
			//Consume whitespace
			while (!stream_eos(stream)) {
				read = stream->vtable->read(stream, &c, 1);
				if (!read)
					break;
				if ((c != ' ') && (c != '\n') && (c != '\r') && (c != '\t')) {
					outbuffer[cursize++] = c;
					break;
				}
			}
		}

		if (cursize > 0) {
			while (!stream_eos(stream) && (cursize < size)) {
				read = stream->vtable->read(stream, &c, 1);
				if (!read)
					break;
				if (!c)
					break;
				if (!binary && ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')))
					break;
				outbuffer[cursize++] = c;
			}
		}
	}
	else {
		if (!binary) {
			//Consume whitespace
			while (!stream_eos(stream)) {
				read = stream->vtable->read(stream, buffer, 16);
				if (!read)
					break;
				for (i = 0; i < read; ++i) {
					char c = buffer[i];
					if ((c != ' ') && (c != '\n') && (c != '\r') && (c != '\t'))
						break;
				}
				if (i < read) {
					stream_seek(stream, (ssize_t)i - (ssize_t)read, STREAM_SEEK_CURRENT);
					break;
				}
			}
		}

		while (!stream_eos(stream) && (cursize < size)) {
			read = stream->vtable->read(stream, buffer, 128);
			if (!read)
				break;
			for (i = 0; i < read; ++i) {
				char c = buffer[i];
				if (!c)
					break;
				if (!binary && ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t')))
					break;
			}
			if (!i)
				break;
			if (cursize + i > size)
				i = size - cursize;
			memcpy(outbuffer + cursize, buffer, i);
			cursize += i;
			if (i < 128) {
				if ((i + 1) < read)
					stream_seek(stream, (ssize_t)(1 + i) - (ssize_t)read, STREAM_SEEK_CURRENT);
				break;
			}
		}
	}

	if (cursize < size)
		outbuffer[cursize] = 0;

	return (string_t) {outbuffer, cursize};
}
コード例 #24
0
ファイル: main.c プロジェクト: rampantpixels/foundation_lib
int
hashify_process_file(stream_t* input_file, stream_t* output_file, string_t output_filename,
                     bool check_only, hashify_string_t** history) {
	int result = HASHIFY_RESULT_OK;
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];
	hashify_string_t* local_hashes = 0;
	hashify_string_t* local_generated = 0;

	if (check_only)
		result = hashify_read_hashes(output_file, &local_hashes);
	else
		result = hashify_generate_preamble(output_file, output_filename);

	memset(line_buffer, 0, sizeof(line_buffer));
	while (!stream_eos(input_file) && (result == HASHIFY_RESULT_OK)) {
		string_t line_string;
		string_const_t def_string;
		string_const_t value_string;

		line_string = stream_read_line_buffer(input_file, line_buffer, sizeof(line_buffer), '\n');
		string_split(STRING_ARGS(line_string), STRING_CONST(" \t"), &def_string, &value_string, false);

		def_string = string_strip(STRING_ARGS(def_string), STRING_CONST(STRING_WHITESPACE));
		value_string = string_strip(STRING_ARGS(value_string), STRING_CONST(STRING_WHITESPACE));

		if (value_string.length && (value_string.str[0] == '"') &&
		        (value_string.str[ value_string.length - 1 ] == '"')) {
			++value_string.str;
			value_string.length -= 2;
		}

		if (def_string.length) {
			hash_t hash_value = hash(STRING_ARGS(value_string));

			log_infof(0, STRING_CONST("  %.*s: %.*s -> 0x%" PRIx64), STRING_FORMAT(def_string),
			          STRING_FORMAT(value_string), hash_value);

			if (check_only) {
				//Check local consistency
				result = hashify_check_local_consistency(value_string, hash_value, local_hashes);
			}
			else {
				stream_write_format(output_file,
				                    STRING_CONST("#define %.*s static_hash_string(\"%.*s\", %" PRIsize ", 0x%" PRIx64 "ULL)\n"),
				                    STRING_FORMAT(def_string), STRING_FORMAT(value_string), value_string.length, hash_value);
			}

			if (result == HASHIFY_RESULT_OK) {
				hashify_string_t hash_string;

				//Check history
				result = hashify_check_collisions(value_string, hash_value, *history);

				//Add to history
				hash_string.string = string_copy(hash_string.buffer, HASHIFY_STRING_LENGTH,
				                                 STRING_ARGS(value_string));
				hash_string.hash = hash_value;
				array_push_memcpy(*history, &hash_string);
				array_push_memcpy(local_generated, &hash_string);
			}
		}
	}

	if (check_only) {
		//Check local consistency
		result = hashify_check_match(local_hashes, local_generated);
	}

	array_deallocate(local_hashes);
	array_deallocate(local_generated);

	return result;
}
コード例 #25
0
ファイル: main.c プロジェクト: NocturnDragon/foundation_lib
int hashify_process_file( stream_t* input_file, stream_t* output_file, bool check_only, hashify_string_t** history )
{
	int result = HASHIFY_RESULT_OK;
	char line_buffer[HASHIFY_LINEBUFFER_LENGTH];
	hashify_string_t* local_hashes = 0;
	hashify_string_t* local_generated = 0;

	if( check_only )
		result = hashify_read_hashes( output_file, &local_hashes );
	else
		result = hashify_generate_preamble( output_file );
	
	while( !stream_eos( input_file ) && ( result == HASHIFY_RESULT_OK ) )
	{
		char* def_string = 0;
		char* value_string = 0;

		stream_read_line_buffer( input_file, line_buffer, HASHIFY_LINEBUFFER_LENGTH, '\n' );
		string_split( line_buffer, " \t", &def_string, &value_string, false );

		string_strip( def_string, STRING_WHITESPACE );
		string_strip( value_string, STRING_WHITESPACE );

		if( string_length( value_string ) && ( value_string[0] == '"' ) && ( value_string[ string_length( value_string ) - 1 ] == '"' ) )
		{
			unsigned int len = string_length( value_string );
			memmove( value_string, value_string + 1, len - 2 );
			value_string[len-2] = 0;
		}

		if( string_length( def_string ) )
		{
			hash_t hash_value = hash( value_string, string_length( value_string ) );

			log_infof( "  %s: %s -> 0x%llx", def_string, value_string, hash_value );

			if( check_only )
			{
				//Check local consistency
				result = hashify_check_local_consistency( value_string, hash_value, local_hashes );
			}
			else
			{
				stream_write_format( output_file, "#define %s static_hash_string( \"%s\", 0x%llxULL )\n", def_string, value_string, hash_value );
			}

			if( result == HASHIFY_RESULT_OK )
			{
				hashify_string_t hash_string;

				//Check history
				result = hashify_check_collisions( value_string, hash_value, *history );

				//Add to history
				string_copy( hash_string.string, value_string, HASHIFY_STRING_LENGTH );
				hash_string.hash = hash_value;
				array_push_memcpy( *history, &hash_string );
				array_push_memcpy( local_generated, &hash_string );
			}
		}

		string_deallocate( def_string );
		string_deallocate( value_string );
	}

	if( check_only )
	{
		//Check local consistency
		result = hashify_check_match( local_hashes, local_generated );
	}

	array_deallocate( local_hashes );
	array_deallocate( local_generated );

	return result;
}