From: <ja...@us...> - 2013-06-17 16:45:27
|
Revision: 10 http://sourceforge.net/p/sdlcp/code/10 Author: jam555 Date: 2013-06-17 16:45:25 +0000 (Mon, 17 Jun 2013) Log Message: ----------- Apparently made more changes to my rbtree implementation here, and to my queue. Don't know when, and I think I actually reimplemented an rbtree in another project. Added a spawn function, though there isn't a header, and the code isn't compile-ready yet. Modified Paths: -------------- SDLCP/trunk/queue.hpp SDLCP/trunk/rbtree.h Added Paths: ----------- SDLCP/trunk/sdlpipe_windows.c Modified: SDLCP/trunk/queue.hpp =================================================================== --- SDLCP/trunk/queue.hpp 2011-08-25 06:25:56 UTC (rev 9) +++ SDLCP/trunk/queue.hpp 2013-06-17 16:45:25 UTC (rev 10) @@ -26,10 +26,10 @@ #ifndef SDLCP2_TEMPLATOMICQUEUE -#include "SDL_atomic.h" -#include "queue.h +# include "SDL_atomic.h" +# include "queue.h" -#define SDLCP2_TEMPLATOMICQUEUE +# define SDLCP2_TEMPLATOMICQUEUE namespace SDLCP_2 { @@ -43,109 +43,12 @@ SDLCP2_AtomicQueueInit( static_cast< SDLCP2_AtomicQueue* >( q ) ); }; - ~TemplAtomicQueue() - { - bool rethrow = 0; - - try - { - while( 1 ) - { - pop(); - } - } - catch( ... ) - { - rethrow = 1; - } - - delete static_cast< SDLCP2_AtomicQueue* >( q ); - q = 0; - - if( rethrow ) - { - throw; - } - }; + ~TemplAtomicQueue(); - TemplAtomicQueue cede_all() volatile - { - void *n = static_cast< void* >( new SDLCP2_AtomicQueue() ); - - while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) - {} - - while( SDL_AtomicCAS( &l2, 0, -1 ) != SDL_TRUE ) - {} - - SDL_AtomicSet( &l1, 0 ); - - void *o = fetch_queue(); - release_queue( n ); - - SDL_AtomicSet( &l2, 0 ); - - return( TemplAtomicQueue( static_cast< SDLCP2_AtomicQueue* >( o ) ) ); - }; + TemplAtomicQueue cede_all() volatile; - T pop() volatile - { - void *data; - - while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) - {} - - int v = SDL_AtomicGet( &l2 ); - while( v >= 0 || SDL_AtomicCAS( &l, v, v + 1 ) != SDL_TRUE ) - { - v = SDL_AtomicGet( &l2 ); - } - - SDL_AtomicSet( &l1, 0 ); - - switch( SDLCP2_AtomicQueuePop( static_cast< SDLCP2_AtomicQueue* >( q ), &data ) ) - { - case 1: - SDL_AtomicDecRef( &l2 ); - break; - case 2: - SDL_AtomicDecRef( &l2 ); - throw( "Out of data." ); - default: - SDL_AtomicDecRef( &l2 ); - throw( "Error." ); - } - - T ret( *static_cast< T* >( data ) ); - delete static_cast< T* >( data ); - - return( ret ); - }; - void push( T &that ) volatile - { - T *tmp = new T( that ); - - while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) - {} - - int v = SDL_AtomicGet( &l2 ); - while( v >= 0 || SDL_AtomicCAS( &l, v, v + 1 ) != SDL_TRUE ) - { - v = SDL_AtomicGet( &l2 ); - } - - SDL_AtomicSet( &l1, 0 ); - - switch( SDLCP2_AtomicQueuePush( static_cast< SDLCP2_AtomicQueue* >( _q ), static_cast< void* >( tmp ) ) ) - { - case 1: - SDL_AtomicDecRef( &l2 ); - break; - default: - SDL_AtomicDecRef( &l2 ); - throw( "Error." ); - } - }; + T pop() volatile; + void push( T &that ) volatile; private: void *q; SDL_atomic_t l1, l2; @@ -153,30 +56,144 @@ TemplAtomicQueue( SDLCP2_AtomicQueue *_q ) : q( static_cast< void* >( q ) ) {}; - TemplAtomicQueue( TemplAtomicQueue &that ) + TemplAtomicQueue( TemplAtomicQueue &that ); + + void* fetch_queue() volatile; + void release_queue( void *_q ) volatile { - void *tmp = static_cast< void* >( new SDLCP2_AtomicQueue() ); - q = that.fetch_queue(); - that.release_queue( tmp ); + SDL_AtomicSetPtr( &q, _q ); }; + }; + + template< class T > + TemplAtomicQueue< T >::~TemplAtomicQueue() + { + bool rethrow = 0; - void* fetch_queue() volatile + try { - void *ret; - - ret = SDL_AtomicGetPtr( &q ); - while( ret == 0 || SDL_AtomicCASPtr( &q, ret, 0 ) != SDL_TRUE ) + while( 1 ) { - ret = SDL_AtomicGetPtr( &q ); + pop(); } - - return( ret ); - }; - void release_queue( void *_q ) volatile + } + catch( ... ) { - SDL_AtomicSetPtr( &q, _q ); - }; - }; + rethrow = 1; + } + + delete static_cast< SDLCP2_AtomicQueue* >( q ); + q = 0; + + if( rethrow ) + { + throw; + } + } + + template< class T > + TemplAtomicQueue< T > TemplAtomicQueue< T >::cede_all() volatile + { + void *n = static_cast< void* >( new SDLCP2_AtomicQueue() ); + + while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) + {} + + while( SDL_AtomicCAS( &l2, 0, -1 ) != SDL_TRUE ) + {} + + SDL_AtomicSet( &l1, 0 ); + + void *o = fetch_queue(); + release_queue( n ); + + SDL_AtomicSet( &l2, 0 ); + + return( TemplAtomicQueue( static_cast< SDLCP2_AtomicQueue* >( o ) ) ); + } + + template< class T > + T TemplAtomicQueue< T >::pop() volatile + { + void *data; + + while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) + {} + + int v = SDL_AtomicGet( &l2 ); + while( v >= 0 || SDL_AtomicCAS( &l, v, v + 1 ) != SDL_TRUE ) + { + v = SDL_AtomicGet( &l2 ); + } + + SDL_AtomicSet( &l1, 0 ); + + switch( SDLCP2_AtomicQueuePop( static_cast< SDLCP2_AtomicQueue* >( q ), &data ) ) + { + case 1: + SDL_AtomicDecRef( &l2 ); + break; + case 2: + SDL_AtomicDecRef( &l2 ); + throw( "Out of data." ); + default: + SDL_AtomicDecRef( &l2 ); + throw( "Error." ); + } + + T ret( *static_cast< T* >( data ) ); + delete static_cast< T* >( data ); + + return( ret ); + } + template< class T > + void TemplAtomicQueue< T >::push( T &that ) volatile + { + T *tmp = new T( that ); + + while( SDL_AtomicCAS( &l1, 0, 1 ) != SDL_TRUE ) + {} + + int v = SDL_AtomicGet( &l2 ); + while( v >= 0 || SDL_AtomicCAS( &l, v, v + 1 ) != SDL_TRUE ) + { + v = SDL_AtomicGet( &l2 ); + } + + SDL_AtomicSet( &l1, 0 ); + + switch( SDLCP2_AtomicQueuePush( static_cast< SDLCP2_AtomicQueue* >( _q ), static_cast< void* >( tmp ) ) ) + { + case 1: + SDL_AtomicDecRef( &l2 ); + break; + default: + SDL_AtomicDecRef( &l2 ); + throw( "Error." ); + } + } + + template< class T > + TemplAtomicQueue< T >::TemplAtomicQueue( TemplAtomicQueue &that ) + { + void *tmp = static_cast< void* >( new SDLCP2_AtomicQueue() ); + q = that.fetch_queue(); + that.release_queue( tmp ); + } + + template< class T > + void* TemplAtomicQueue< T >::fetch_queue() volatile + { + void *ret; + + ret = SDL_AtomicGetPtr( &q ); + while( ret == 0 || SDL_AtomicCASPtr( &q, ret, 0 ) != SDL_TRUE ) + { + ret = SDL_AtomicGetPtr( &q ); + } + + return( ret ); + } }; #endif /* SDLCP2_TEMPLATOMICQUEUE */ Modified: SDLCP/trunk/rbtree.h =================================================================== --- SDLCP/trunk/rbtree.h 2011-08-25 06:25:56 UTC (rev 9) +++ SDLCP/trunk/rbtree.h 2013-06-17 16:45:25 UTC (rev 10) @@ -23,6 +23,11 @@ /* rbtree.h */ +/* Based on: http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx */ +/* Red-black trees are a simulation of a tree that uses nodes with 4 */ +/* branches. The black nodes represent those nodes, the red nodes */ +/* represent HALF of one of those nodes (so that 1 black with 2 red == 1 */ +/* full 4-branch node). */ /* This file is very much not finished. */ @@ -31,30 +36,174 @@ rbtree_lesser_element = 0, rbtree_greater_element = 1, - rbtree_parent_element = 2, - - rbtree_key_element = 3 + rbtree_parent_element = 2 }; struct rbtree_element { - void *elements[ 4 ]; + void *elements[ 3 ]; + char red; }; +int is_red( rb_tree **node ) +{ + if( node ) + { + if( *node == (void*)0 ) + { + return( 0 ); + } + + return( ( *node )->red ); + } + + return( -1 ); +} + + /* Bug checking function. Will probably be slow. Recursive. */ +int assert +( + rbtree_element **root, + void (*lesser_func)( void*, rbtree_element**, rbtree_element** ), void *lesser_data, + void (*puts_func)( void*, char* ), void *puts_data +) +{ + if( !lesser_func ) + { + return( -1 ); + } + + if( root && *root ) + { + int lh, rh; + rbtree_element *ln = ( *root )->elements[ 0 ], *rn = ( *root )->elements[ 1 ]; + + if + ( + is_red( root ) && + ( + is_red( &ln ) || + is_red( &rn ) + ) + ) + { + if( puts_func ) + { + ( *puts_func )( puts_data, "Red violation." ); + } + + return( 0 ); + } + + lh = assert( ln, lesser_func, lesser_data, puts_func, puts_data ); + rh = assert( rn, lesser_func, lesser_data, puts_func, puts_data ); + + if + ( + ( ln && !( *lesser_func )( lesser_data, &ln, root ) ) || + ( rn && !( *lesser_func )( lesser_data, root, &rn ) ) + ) + { + if( puts_func ) + { + ( *puts_func )( puts_data, "Sort violation." ); + } + + return( 0 ); + } + + if( lh && rh && lh != rh ) + { + if( puts_func ) + { + ( *puts_func )( puts_data, "Black height violation." ); + } + + return( 0 ); + } + + if( lh && rh ) + { + return( is_red( root ) ? lh : lh + 1 ); + } else { + return( 0 ); + } + } + + return( 1 ); +} + +int set_black( rb_tree **node ) +{ + if( node ) + { + if( *node != 0 ) + { + ( *node )->elements[ rbtree_key_element ] = ( ( *node )->elements[ rbtree_key_element ] & RBTREE_KEYVAL_SORTMASK ); + + return( 1 ); + } + + return( -2 ); + } + + return( -1 ); +} +int set_red( rb_tree **node ) +{ + if( node ) + { + if( *node != 0 ) + { + ( *node )->elements[ rbtree_key_element ] = ( ( *node )->elements[ rbtree_key_element ] & RBTREE_KEYVAL_SORTMASK ) | rbtree_keyval_red; + + return( 1 ); + } + + return( -2 ); + } + + return( -1 ); +} /* Returns a pointer suitable for INSERTIONS and DELETIONS, not just searches. */ -rbtree_element** find( rbtree_element **root, void *key ) + /* Also, proot should actually be a void**, but that typo occures throughout this file... */ + /* proot is the parent root, mostly useful for insertions. */ +rbtree_element** find +( + rbtree_element **root, + rbtree_element *key, + + rbtree_element **proot, + + void (*lesser_func)( void*, rbtree_element**, rbtree_element** ), void *lesser_data +) { - if( root ) + if( root && lesser_func ) { + if( proot ) + { + proot = 0; + } + while( *root ) { - if( ( *root )->elements[ rbtree_key_element ] == key ) + if( ( *lesser_func )( lesser_data, root, &key ) ) { - return( (rbtree_element*)root ); - } else if( ( *root )->elements[ rbtree_key_element ] > key ) + if( proot ) + { + proot = root; + } + + root = (rbtree_element*)&( ( *root )->elements[ rbtree_greater_element ] ); + } else if( ( *lesser_func )( lesser_data, &key, root ) ) { + if( proot ) + { + proot = root; + } + root = (rbtree_element*)&( ( *root )->elements[ rbtree_lesser_element ] ); } else { - root = (rbtree_element*)&( ( *root )->elements[ rbtree_greater_element ] ); + return( (rbtree_element*)root ); } } @@ -73,7 +222,7 @@ dir = ( dir ? 1 : 0 ); or = *root; - nr = (rbtree_element*)or->elements[ !dir ]; + nr = (rbtree_element*)( or->elements[ !dir ] ); if( !nr ) { @@ -83,7 +232,7 @@ or->elements[ !dir ] = nr->elements[ dir ]; if( nr->elements[ dir ] ) { - (rbtree_element*)( nr->elements[ dir ] )->elements[ rbtree_parent_element ] = (void*)or; + ( (rbtree_element*)( nr->elements[ dir ] ) )->elements[ rbtree_parent_element ] = (void*)or; } nr->elements[ dir ] = (void*)or; nr->elements[ rbtree_parent_element ] = or->elements[ rbtree_parent_element ]; @@ -96,3 +245,28 @@ return( 0 ); } +int rotate2( rbtree_element **root, int dir ) +{ + if( root && *root ) + { + int res; + + dir = dir ? 1 : 0; + + res = rotate1( &( ( *root )->elements[ !dir ] ), !dir ); + if( !res ) + { + return( res - 1 ); + } + + res = rotate1( root, dir ); + if( !res ) + { + return( res - 1 ); + } + + return( res - ( ( !res ) ? 3 : 0 ) ); + } + + return( 0 ); +} Added: SDLCP/trunk/sdlpipe_windows.c =================================================================== --- SDLCP/trunk/sdlpipe_windows.c (rev 0) +++ SDLCP/trunk/sdlpipe_windows.c 2013-06-17 16:45:25 UTC (rev 10) @@ -0,0 +1,549 @@ +/* + SDLCP version 2 + Copyright (C) Aug 25, 2011 Jared Maddox <abs...@gm...> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jared Maddox +*/ +/* + sdlpipe_windows.c +*/ + + +/* TODO: */ +/* Missing SDLPIPE_TYPEID define. */ +/* SDLPipe_ProgramResult() needs to have it's actual "body" filled out. */ +/* Need to add includes. */ +/* There are some C++isms. Need to convert them to C-friendly. */ + + +/* From reading online, it LOOKS like the only reason why Win32 gui programs */ +/* don't have the standard io handles is only because they don't */ +/* automagically allocate them beforehand. This redirection trick should */ +/* seemingly solve that without client GUI programs having to do anything. */ + +/* Microsoft apparently uses the redirection trick with another trick (the */ +/* same-name .com trick) to allow a gui program called msdev to receive */ +/* input from the console. I think msdev is part of Visual Studio. */ + + +#define INPUT 0 +#define OUTPUT 1 +#define ERROR 2 + +typedef struct sdlpipe_data +{ + HANDLE pipein, pipeout, pipeerr; + PROCESS_INFORMATION child; +} sdlpipe_data; + + +static int sdlpipe_seek( SDL_RWops *context, int offset, int whence ) +{ + SDL_SetError( "SDL Pipe RWops don't support seeking." ); + + return( -1 ); +} + +static int sdlpipe_read( SDL_RWops *context, void *ptr, int size, int maxnum ); +static int sdlpipe_write( SDL_RWops *context, const void *ptr, int size, int num ); + +static int sdlpipe_read_bb( SDL_RWops *context, void *ptr, int size, int maxnum ); +static int sdlpipe_write_bb( SDL_RWops *context, const void *ptr, int size, int num ); + +static int sdlpipe_close( SDL_RWops *context ); + + +int build_pipe( HANDLE *e1, HANDLE *e2, SECURITY_ATTRIBUTES *sa ) +{ + if( !CreatePipe( &( e1[ INPUT ] ), &( e2[ OUTPUT ] ), sa, 0 ) ) + { + return( -1 ); + } + if( !CreatePipe( &( e2[ INPUT ] ), &( e1[ OUTPUT ] ), sa, 0 ) ) + { + CloseHandle( e1[ INPUT ] ); + CloseHandle( e2[ OUTPUT ] ); + + return( -2 ); + } + if( !CreatePipe( &( e2[ ERROR ] ), &( e1[ ERROR ] ), sa, 0 ) ) + { + CloseHandle( e1[ INPUT ] ); + CloseHandle( e2[ OUTPUT ] ); + + CloseHandle( e2[ INPUT ] ); + CloseHandle( e1[ OUTPUT ] ); + + return( -3 ); + } + + return( 1 ); +} + +int set_pipe_side_inheritance( HANDLE *e, bool i ) +{ + if + ( + !SetHandleInformation + ( + e[ INPUT ], + HANDLE_FLAG_INHERIT, + ( i ? HANDLE_FLAG_INHERIT : 0 ) + ) + ) + { + return( -1 ); + } + if + ( + !SetHandleInformation + ( + e[ OUTPUT ], + HANDLE_FLAG_INHERIT, + ( i ? HANDLE_FLAG_INHERIT : 0 ) + ) + ) + { + return( -2 ); + } + if + ( + !SetHandleInformation + ( + e[ ERROR ], + HANDLE_FLAG_INHERIT, + ( i ? HANDLE_FLAG_INHERIT : 0 ) + ) + ) + { + return( -3 ); + } + + return( 1 ); +} +void close_pipe_side( HANDLE *e ) +{ + CloseHandle( e[ INPUT ] ); + CloseHandle( e[ OUTPUT ] ); + CloseHandle( e[ ERROR ] ); +} + + + +sdlpipe_data* SDLPipe_SpawnProgram( const char *command, char *const args[], int blocking ) +{ + SDL_RWops *ret = SDL_AllocRW(); + + if( !ret ) + { + return( ret ); + } + + sdlpipe_data *sdlpd = (sdlpipe_data*)SDL_malloc( sizeof( sdlpipe_data ) ); + + if( sdlpd ) + { + HANDLE here[ 3 ], child[ 3 ]; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + size_t arglen = 1; + DWORD flags; + char *arg = 0; + char *const *argiter = args; + + /* Assemble the command and arguments into a single construct. */ + arglen += strlen( command ); + while( *argiter ) + { + arglen += 1 + strlen( *argiter ); + ++argiter; + } + arg = (char*)SDL_malloc( sizeof( char ) * arglen ); + if( !arg ) + { + SDL_free( sdlpd ); + SDL_FreeRW( ret ); + + SDL_SetError( "SDLPipe_SpawnProgram() failed to allocate memory for it's arguments." ); + + return( 0 ); + } + argiter = args; + strcpy( arg, command ); + arglen = strlen( command ); + while( *argiter ) + { + /* NOTE: */ + /* This might copy nulls as well as string contents. If that causes */ + /* problems, then remove the "1 +" from the arglen increment, and */ + /* add "- 1" to the angle brackets on the "= ' ';" line. */ + + arg[ arglen ] = ' '; + + strcpy( &( arg[ arglen + 1 ] ), *argiter ); + + arglen += 1 + strlen( *argiter ); + ++argiter; + } + + /* We want the pipes inherited. */ + memset( &sa, sizeof( SECURITY_ATTRIBUTES ), 0 ); + sa.nLength = sizeof( SECURITY_ATTRIBUTES ); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + /* Allocate the pipes. */ + if( !build_pipe( here, child, &sa ) ) + { + SDL_free( arg ); + SDL_free( sdlpd ); + SDL_FreeRW( ret ); + + SDL_SetError( "SDLPipe_SpawnProgram() failed to allocate pipes." ); + + return( 0 ); + } + + /* Keep this end from being inherited by this child, or any other. */ + if( !set_pipe_side_inheritance( here, 0 ) ) + { + close_pipe_side( ret->connection ); + close_pipe_side( child ); + + SDL_free( arg ); + SDL_free( sdlpd ); + SDL_FreeRW( ret ); + + SDL_SetError( "SDLPipe_SpawnProgram() failed to set the pipe's inheritance values." ); + + return( 0 ); + } + + /* Setup for child creation. */ + memset( &( ret->child ), sizeof( PROCESS_INFORMATION ), 0 ); + memset( &si, sizeof( STARTUPINFO ), 0 ); + /* Override the standard I/O handles. */ + si.cb = sizeof( STARTUPINFO ); + si.hStdError = child[ ERROR ]; /* Vista apparently needs this. */ + si.hStdOutput = child[ OUTPUT ]; + si.hStdInput = child[ INPUT ]; + si.dwFlags = STARTF_USESTDHANDLES; + + /* Create the process. */ + if + ( !CreateProcessA + ( + command, arg, + NULL, NULL, /* No inheriting the child's handles. */ + TRUE, /* Let the child inherit the pipe ends. */ + 0, /* No flags. */ + NULL, NULL, + &si, &( ret->child ) + ) + ) + { + close_pipe_side( ret->connection ); + close_pipe_side( child ); + + SDL_free( arg ); + SDL_free( sdlpd ); + SDL_FreeRW( ret ); + + SDL_SetError( "SDLPipe_SpawnProgram() failed to spawn the program." ); + + return( 0 ); + } + + /* We don't need arg's contents anymore. */ + SDL_free( arg ); + arg = 0; + + /* We don't need these pipe handles, either. Also, keeping them can */ + /* apparently cause a deadlock if we try to read from */ + /* ret->connection, so it's better to side-step the issue. */ + close_pipe_side( child ); + + /* Set the blocking state. */ + if( !blocking ) + { + flags = PIPE_NOWAIT; + + /* Special handling on failure. */ + + if( !SetNamedPipeHandleState( here[ INPUT ], &flags, 0, 0 ) ) + { + ret->read = sdlpipe_read_bb; + } else { + ret->read = sdlpipe_read; + } + if( !SetNamedPipeHandleState( here[ OUTPUT ], &flags, 0, 0 ) ) + { + ret->write = sdlpipe_write_bb; + } else { + ret->write = sdlpipe_write; + } + /* Error always gets treated the same anyways, so no test. */ + SetNamedPipeHandleState( here[ ERROR ], &flags, 0, 0 ); + } else { + ret->read = sdlpipe_read; + ret->write = sdlpipe_write; + } + + /* Now we just need to assemble all of the relevant data into one spot... */ + + ret->seek = sdlpipe_seek; + ret->close = sdlpipe_close; + ret->type = SDLPIPE_TYPEID; + ret->hidden.unknown.data1 = (void*)sdlpd; + + sdlpd->pipein = here[ INPUT ]; + sdlpd->pipeout = here[ OUTPUT ]; + sdlpd->pipeerr = here[ ERROR ]; + } else { + SDL_free( ret ); + ret = 0; + + SDL_SetError( "SDLPipe_SpawnProgram() failed to allocate a sdlpipe_data instance." ); + } + + return( ret ); +} + + + +static int sdlpipe_read( SDL_RWops *context, void *ptr, int size, int maxnum ) +{ + if( !context ) + { + SDL_SetError( "sdlpipe_read_bb() called with null SDL_RWops*." ); + + return( -1 ); + } + if( context->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "sdlpipe_read_bb() called on unknown SDL_RWops type." ); + + return( -1 ); + } + if( size != 1 ) + { + SDL_SetError( "sdlpipe_read_bb() with a data size other than 1." ); + + return( -1 ); + } + + + sdlpipe_data *sdlpd = (sdlpipe_data*)( context->hidden.unknown.data1 ); + DWORD isize = 0; + + if( !GetNamedPipeInfo( sdlpd->pipeerr, 0, 0, &isize, 0 ) ) + { + return( -2 ); + } + if( isize && ReadFile( sdlpd->pipeerr, buffer, ( maxnum < isize ? maxnum : isize ), &isize, 0 ) ) + { + return( isize ); + } + + if( !ReadFile( sdlpd->pipein, buffer, maxnum, &isize, 0 ) ) + { + return( -3 ); + } + + + memset( ptr, 0, size * maxnum ); + return( isize ); +} +static int sdlpipe_write( SDL_RWops *context, const void *ptr, int size, int num ) +{ + if( !context ) + { + SDL_SetError( "sdlpipe_write_bb() called with null SDL_RWops*." ); + + return( -1 ); + } + if( context->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "sdlpipe_write_bb() called on unknown SDL_RWops type." ); + + return( -1 ); + } + if( size != 1 ) + { + SDL_SetError( "sdlpipe_write_bb() with a data size other than 1." ); + + return( -1 ); + } + + + sdlpipe_data *sdlpd = (sdlpipe_data*)( context->hidden.unknown.data1 ); + DWORD osize = 0; + + if( !WriteFile( sdlpd->pipeout, buffer, num, &osize, 0 ) ) + { + return( -3 ); + } + + + return( osize ); +} + +static int sdlpipe_read_bb( SDL_RWops *context, void *ptr, int size, int maxnum ) +{ + if( !context ) + { + SDL_SetError( "sdlpipe_read_bb() called with null SDL_RWops*." ); + + return( -1 ); + } + if( context->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "sdlpipe_read_bb() called on unknown SDL_RWops type." ); + + return( -1 ); + } + if( size != 1 ) + { + SDL_SetError( "sdlpipe_read_bb() with a data size other than 1." ); + + return( -1 ); + } + + + sdlpipe_data *sdlpd = (sdlpipe_data*)( context->hidden.unknown.data1 ); + DWORD isize = 0; + + if( !GetNamedPipeInfo( sdlpd->pipeerr, 0, 0, &isize, 0 ) ) + { + return( -2 ); + } + if( isize && ReadFile( sdlpd->pipeerr, buffer, ( maxnum < isize ? maxnum : isize ), &isize, 0 ) ) + { + return( isize ); + } + + if( !GetNamedPipeInfo( sdlpd->pipein, 0, 0, &isize, 0 ) ) + { + return( -2 ); + } + if( !ReadFile( sdlpd->pipein, buffer, ( maxnum < isize ? maxnum : isize ), &isize, 0 ) ) + { + return( -3 ); + } + + + memset( ptr, 0, size * maxnum ); + return( isize ); +} +static int sdlpipe_write_bb( SDL_RWops *context, const void *ptr, int size, int num ) +{ + if( !context ) + { + SDL_SetError( "sdlpipe_write_bb() called with null SDL_RWops*." ); + + return( -1 ); + } + if( context->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "sdlpipe_write_bb() called on unknown SDL_RWops type." ); + + return( -1 ); + } + if( size != 1 ) + { + SDL_SetError( "sdlpipe_write_bb() with a data size other than 1." ); + + return( -1 ); + } + + + sdlpipe_data *sdlpd = (sdlpipe_data*)( context->hidden.unknown.data1 ); + DWORD osize = 0; + + if( !GetNamedPipeInfo( sdlpd->pipeout, 0, &osize, 0, 0 ) ) + { + return( -2 ); + } + if( !WriteFile( sdlpd->pipeout, buffer, ( num < osize ? num : osize ), &osize, 0 ) ) + { + return( -3 ); + } + + + return( osize ); +} + +static int sdlpipe_close( SDL_RWops *context ) +{ + if( !context ) + { + SDL_SetError( "sdlpipe_close() called with null SDL_RWops*." ); + + return( -1 ); + } + if( context->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "sdlpipe_close() called on unknown SDL_RWops type." ); + + return( -1 ); + } + + sdlpipe_data *sdlpd = (sdlpipe_data*)( context->hidden.unknown.data1 ); + + CloseHandle( sdlpd->pipein ); + CloseHandle( sdlpd->pipeout ); + CloseHandle( sdlpd->pipeerr ); + + CloseHandle( sdlpd->child.hProcess ); + CloseHandle( sdlpd->child.hThread ); + + /* Release our memory blocks. */ + SDL_free( sdlpd ); + SDL_FreeRW( context ); + + return( 0 ); +} + +int SDLPipe_ProgramResult( SDL_RWops *pipe, int *ret ) +{ + if( !pipe ) + { + SDL_SetError( "SDLPipe_ProgramResult() called with null SDL_RWops*." ); + + return( SDLPipe_error ); + } + if( !ret ) + { + SDL_SetError( "SDLPipe_ProgramResult() called with null int *ret." ); + + return( SDLPipe_error ); + } + if( pipe->type != SDLPIPE_TYPEID ) + { + SDL_SetError( "SDLPipe_ProgramResult() called on unknown SDL_RWops type." ); + + return( SDLPipe_error ); + } + + sdlpipe_data *sdlpd = (sdlpipe_data*)( pipe->hidden.unknown.data1 ); + + /* Real contents here. */ + + return( SDLPipe_unknown ); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |