Example #1
0
int WindowsFileIO::read(void *p)
{
	LOG->Trace( "WindowsFileIO::read()" );

	/* See if we have a response for our request (which we may
	 * have made on a previous call): */
    if(WaitForSingleObjectEx(h, 0, TRUE) == WAIT_TIMEOUT)
		return -1;

	return finish_read(p);
}
Example #2
0
 /// read XML stream into XML tree below _pos
void XMLReaderBase::read()
{
	if (!parse()) {
		XMLError error;

		error._message = "XML parsing error";
		//error._line = ;
		//error._column = ;

		_errors.push_back(error);
	}

	finish_read();
}
int serial_read (
	struct serial_channel*	_chan,
	void*					_buf,
	int						len)
{
	struct serial_win32*	chan = (struct serial_win32*)_chan;
	char*					buf = (char*)_buf;
	int						bytesCopied = 0;
	int						bytesAvail;

	for (;;)
	{
		/* Get the number of bytes remaining in the read buffer.  This is
		 * the total number of bytes immediately available without making
		 * the caller wait.
		 */
		bytesAvail = chan->rxBufLen - chan->rxRecvLen;

		if (bytesAvail > 0)
		{
			/* If no space remains in the buffer provided by the caller, return
			 * the number of bytes which have been copied into the user's buffer.
			 */
			if (0 == len)
			{
				/* If there is still more data available in the application buffer,
				 * but no pending IO operation is active, there won't be a pending
				 * operation when this return is made.  Therefore manually signal
				 * the eRxReady event.  This ensures that the caller will get
				 * the signal immediately and call again to get more data from
				 * the buffer.  The later call may start an IO operation.
				 */
				if (RXSTATE_NONE == chan->rxState)
				{
					SetEvent(chan->eRxReady);
				}

				goto ok_return;
			}

			if (len < bytesAvail)
			{
				/* The rx buffer actually has more data in it than what the
				 * caller asked for.  Copy only what the caller asked for.
				 */
				memcpy(buf, chan->rxBuf + chan->rxRecvLen, len);
				chan->rxRecvLen += len;
				bytesCopied += len;
				len = 0;

			} else
			{
				/* Copy what's available in the serial port buffer.  There may
				 * still be more data imemdiately available from the OS, but we
				 * don't know that yet.  This might actually empty the buffer,
				 * but we cannot update rxBufLen or reset rxRecvLen until we know
				 * if a pending operation is outstanding or not.
				 */
				memcpy(buf, chan->rxBuf + chan->rxRecvLen, bytesAvail);
				chan->rxRecvLen += bytesAvail;
				bytesCopied += bytesAvail;
				buf += bytesAvail;
				len -= bytesAvail;
			}
		}

		switch (chan->rxState)
		{
		case RXSTATE_NONE:
			/* No operation is currently pending.  If the buffer has been
			 * completely drained by the caller, start up a wait operation.
			 */
			if (chan->rxRecvLen == chan->rxBufLen)
			{
				/* The buffer is completely empty, so zero out the lengths
				 * so the entire buffer is available for more data.  This
				 * is the only way the buffer truncates back to its start.
				 */
				chan->rxBufLen = 0;
				chan->rxRecvLen = 0;

				/* If start_wait_rx returns FALSE, an IO operation is now
				 * pending and the caller will get signaled with eRxReady
				 * when the pending operation completes.  Return the current
				 * number of bytes processed, or -1.
				 */
				if ( ! start_wait_rx(chan))
				{
					goto ok_return;
				}

				/* No operation is pending.  Most likely there is now new
				 * data in the read buffer, and thus the receive loop should
				 * keep running to copy all available data into the user
				 * buffer.
				 */
			}

			/* If the buffer is not empty, don't try to get an operation
			 * started.  This allows the caller to completely empty the
			 * application buffer on the next call (which should happen
			 * immediately as SetEvent is used to manually signal eRxReady).
			 * Only after the caller has emptied the buffer will the IO
			 * get started up again.
			 */
			break;

		case RXSTATE_WAIT:
			/* The serial port needs to finish the wait call.  If the wait
			 * call is not finished yet, return the current number of
			 * bytes processed (most likely will be 0, so the actual
			 * return code will be -1).
			 */
			if ( ! finish_wait_rx(chan))
			{
				goto ok_return;
			}
			
			/* If we fall through, finish_wait_rx returned TRUE, indicating
			 * that the start_read call put new data into the buffer.  Go
			 * through the loop above and try to consume it.
			 */
			break;

		case RXSTATE_READ:
			/* The serial port read just finished, or maybe not.  If the
			 * read is not yet finished, return the number of bytes put into
			 * the user's buffer, or -1 if no data was copied.
			 */
			if ( ! finish_read(chan))
			{
				goto ok_return;
			}

			/* If we fall through, the read may have put more data into the
			 * buffer, so loop and try to copy it into the user's buffer.
			 */
			break;
		}
	}

ok_return:
	/* If no bytes were copied, return -1.  This is how UNIX read(2) works
	 * when in nonblocking IO mode.  We don't however set an error code
	 * to EAGAIN like UNIX systems do.
	 */
	return bytesCopied > 0 ? bytesCopied : -1;
}