📄 pchannel.cxx
字号:
/*
* pchannel.cxx
*
* Operating System utilities.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: pchannel.cxx,v $
* Revision 1.6 1999/07/06 08:55:05 robertj
* Fixed bug in PFile::Copy, does not write last chunk of data to new file.
*
* Revision 1.5 1999/06/17 14:44:42 robertj
* Fixed incorrect comparison of open write channel
*
* Revision 1.4 1999/06/17 13:38:11 robertj
* Fixed race condition on indirect channel close, mutex needed in PIndirectChannel.
*
* Revision 1.3 1999/02/22 10:10:12 robertj
* Changed channel output flush to remove double Write() call.
*
* Revision 1.2 1999/01/31 00:57:18 robertj
* Fixed bug when opening an already open file, should close it!
*
* Revision 1.1 1998/11/30 12:46:19 robertj
* Initial revision
*
*/
#include <ptlib.h>
#include <ctype.h>
///////////////////////////////////////////////////////////////////////////////
// PChannel
PChannelStreamBuffer::PChannelStreamBuffer(PChannel * chan)
: channel(PAssertNULL(chan))
{
}
int PChannelStreamBuffer::overflow(int c)
{
if (pbase() == NULL) {
if (eback() == 0)
setp(buffer, &buffer[sizeof(buffer)]);
else {
char * halfway = &buffer[sizeof(buffer)/2];
setp(buffer, halfway);
setg(halfway, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
}
}
int bufSize = pptr() - pbase();
if (bufSize > 0) {
setp(pbase(), epptr());
if (!channel->Write(pbase(), bufSize))
return EOF;
}
if (c != EOF) {
*pptr() = (char)c;
pbump(1);
}
return 0;
}
int PChannelStreamBuffer::underflow()
{
if (eback() == NULL) {
if (pbase() == 0)
setg(buffer, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
else {
char * halfway = &buffer[sizeof(buffer)/2];
setp(buffer, halfway);
setg(halfway, &buffer[sizeof(buffer)], &buffer[sizeof(buffer)]);
}
}
if (gptr() != egptr())
return (BYTE)*gptr();
if (!channel->Read(eback(), egptr() - eback()) ||
channel->GetErrorCode() != PChannel::NoError)
return EOF;
PINDEX count = channel->GetLastReadCount();
char * p = egptr() - count;
memmove(p, eback(), count);
setg(eback(), p, egptr());
return (BYTE)*p;
}
int PChannelStreamBuffer::sync()
{
int inAvail = egptr() - gptr();
if (inAvail > 0) {
setg(eback(), egptr(), egptr());
if (channel->IsDescendant(PFile::Class()))
((PFile *)channel)->SetPosition(-inAvail, PFile::Current);
}
if (pptr() > pbase())
return overflow();
return 0;
}
streampos PChannelStreamBuffer::seekoff(streamoff off,
#ifdef __MWERKS__
ios::seekdir dir, ios::openmode)
#else
ios::seek_dir dir, int)
#endif
{
sync();
if (!channel->IsDescendant(PFile::Class()))
return -1;
((PFile *)channel)->SetPosition(off, (PFile::FilePositionOrigin)dir);
return ((PFile *)channel)->GetPosition();
}
PChannel::PChannel()
: readTimeout(PMaxTimeInterval), writeTimeout(PMaxTimeInterval)
{
os_handle = -1;
osError = 0;
lastError = NoError;
lastReadCount = lastWriteCount = 0;
init(new PChannelStreamBuffer(this));
Construct();
}
PChannel::~PChannel()
{
flush();
Close();
delete (PChannelStreamBuffer *)rdbuf();
init(NULL);
}
BOOL PChannel::IsOpen() const
{
return os_handle >= 0;
}
int PChannel::ReadChar()
{
BYTE c;
BOOL retVal = Read(&c, 1);
return (retVal && lastReadCount == 1) ? c : -1;
}
int PChannel::ReadCharWithTimeout(PTimeInterval & timeout)
{
SetReadTimeout(timeout);
PTimeInterval startTick = PTimer::Tick();
int c;
if ((c = ReadChar()) < 0) // Timeout or aborted
return -1;
timeout -= PTimer::Tick() - startTick;
return c;
}
BOOL PChannel::ReadBlock(void * buf, PINDEX len)
{
char * ptr = (char *)buf;
PINDEX numRead = 0;
while (numRead < len && Read(ptr+numRead, len - numRead))
numRead += lastReadCount;
lastReadCount = numRead;
return lastReadCount == len;
}
PString PChannel::ReadString(PINDEX len)
{
PString str;
ReadBlock(str.GetPointer(len+1), len);
str.SetSize(lastReadCount+1);
return str;
}
BOOL PChannel::WriteString(const PString & str)
{
const char * ptr = str;
PINDEX len = 0, slen = str.GetLength();
while (len < slen && Write(ptr+len, slen - len))
len += lastWriteCount;
return len == slen;
}
BOOL PChannel::ReadAsync(void * buf, PINDEX len)
{
BOOL retVal = Read(buf, len);
OnReadComplete(buf, lastReadCount);
return retVal;
}
void PChannel::OnReadComplete(void *, PINDEX)
{
}
BOOL PChannel::WriteChar(int c)
{
PAssert(c >= 0 && c < 256, PInvalidParameter);
char buf = (char)c;
return Write(&buf, 1);
}
BOOL PChannel::WriteAsync(const void * buf, PINDEX len)
{
BOOL retVal = Write(buf, len);
OnWriteComplete(buf, lastWriteCount);
return retVal;
}
void PChannel::OnWriteComplete(const void *, PINDEX)
{
}
enum {
NextCharEndOfString = -1,
NextCharDelay = -2,
NextCharSend = -3,
NextCharWait = -4
};
static int HexDigit(char c)
{
if (!isxdigit(c))
return 0;
int hex = c - '0';
if (hex < 10)
return hex;
hex -= 'A' - '9' - 1;
if (hex < 16)
return hex;
return hex - ('a' - 'A');
}
static int GetNextChar(const PString & command,
PINDEX & pos, PTimeInterval * time = NULL)
{
int temp;
if (command[pos] == '\0')
return NextCharEndOfString;
if (command[pos] != '\\')
return command[pos++];
switch (command[++pos]) {
case '\0' :
return NextCharEndOfString;
case 'a' : // alert (ascii value 7)
pos++;
return 7;
case 'b' : // backspace (ascii value 8)
pos++;
return 8;
case 'f' : // formfeed (ascii value 12)
pos++;
return 12;
case 'n' : // newline (ascii value 10)
pos++;
return 10;
case 'r' : // return (ascii value 13)
pos++;
return 13;
case 't' : // horizontal tab (ascii value 9)
pos++;
return 9;
case 'v' : // vertical tab (ascii value 11)
pos++;
return 11;
case 'x' : // followed by hh where nn is hex number (ascii value 0xhh)
if (isxdigit(command[++pos])) {
temp = HexDigit(command[pos++]);
if (isxdigit(command[pos]))
temp += HexDigit(command[pos++]);
return temp;
}
return command[pos];
case 's' :
pos++;
return NextCharSend;
case 'd' : // ns delay for n seconds/milliseconds
case 'w' :
temp = command[pos] == 'd' ? NextCharDelay : NextCharWait;
long milliseconds = 0;
while (isdigit(command[++pos]))
milliseconds = milliseconds*10 + command[pos] - '0';
if (milliseconds <= 0)
milliseconds = 1;
if (command[pos] == 'm')
pos++;
else {
milliseconds *= 1000;
if (command[pos] == 's')
pos++;
}
if (time != NULL)
*time = milliseconds;
return temp;
}
if (command[pos] < '0' || command[pos] > '7')
return command[pos++];
// octal number
temp = command[pos++] - '0';
if (command[pos] < '0' || command[pos] > '7')
return temp;
temp += command[pos++] - '0';
if (command[pos] < '0' || command[pos] > '7')
return temp;
temp += command[pos++] - '0';
return temp;
}
BOOL PChannel::ReceiveCommandString(int nextChar,
const PString & reply, PINDEX & pos, PINDEX start)
{
if (nextChar != GetNextChar(reply, pos)) {
pos = start;
return FALSE;
}
PINDEX dummyPos = pos;
return GetNextChar(reply, dummyPos) < 0;
}
BOOL PChannel::SendCommandString(const PString & command)
{
abortCommandString = FALSE;
int nextChar;
PINDEX sendPosition = 0;
PTimeInterval timeout;
SetWriteTimeout(10000);
while (!abortCommandString) { // not aborted
nextChar = GetNextChar(command, sendPosition, &timeout);
switch (nextChar) {
default :
if (!WriteChar(nextChar))
return FALSE;
break;
case NextCharEndOfString :
return TRUE; // Success!!
case NextCharSend :
break;
case NextCharDelay : // Delay in send
PThread::Current()->Sleep(timeout);
break;
case NextCharWait : // Wait for reply
PINDEX receivePosition = sendPosition;
if (GetNextChar(command, receivePosition) < 0) {
SetReadTimeout(timeout);
while (ReadChar() >= 0)
if (abortCommandString) // aborted
return FALSE;
}
else {
receivePosition = sendPosition;
do {
if (abortCommandString) // aborted
return FALSE;
if ((nextChar = ReadCharWithTimeout(timeout)) < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -