|
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.
|