⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pchannel.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * 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.33  2005/08/05 20:41:42  csoutheren * Added unix support for scattered read/write * * Revision 1.32  2004/07/03 03:00:46  rjongbloed * Fixed MSVC warning * * Revision 1.31  2004/07/03 01:48:28  rjongbloed * Fixed memory leak caused by buggy iostream, can't do init twice. Thanks Norbert Bartalsky * * Revision 1.30  2004/06/08 01:31:08  csoutheren * Make the test sense correct for the init(NULL) * * Revision 1.29  2004/06/08 01:29:00  csoutheren * Removed memory leak on VS.net caused by unobvious iostream allocation * * Revision 1.28  2004/04/09 06:38:11  rjongbloed * Fixed compatibility with STL based streams, eg as used by VC++2003 * * Revision 1.27  2004/04/03 08:22:21  csoutheren * Remove pseudo-RTTI and replaced with real RTTI * * Revision 1.26  2004/03/22 10:15:28  rjongbloed * Added classes similar to PWaitAndSignal to automatically unlock a PReadWriteMutex *   when goes out of scope. * * Revision 1.25  2004/02/24 11:19:32  rjongbloed * Fixed seekpos() function on channel to read data when seeking beyond end of corrent stream. * * Revision 1.24  2003/12/19 04:31:27  csoutheren * Changed GetLastReadCount and GetLastWriteCount to be virtual * * Revision 1.23  2003/04/23 00:37:04  craigs * More casts to avoid problems on MacOSX thanks to Shawn Hsiao * * Revision 1.22  2003/03/19 00:10:24  robertj * Added ability to use seekoff() in a PChannel streambuf that is not a file. * * Revision 1.21  2003/02/11 07:22:43  robertj * Fixed strange behaviour in ReadString(P_MAX_INDEX) with DOS text files where *   it would get extra garbage at the end of the string, thanks Joerg Schoemer. * * Revision 1.20  2003/02/10 01:01:03  robertj * Fixed portability issue for lseek() calls, should just look for -1 return *   value to indicate error, thanks Joerg Schoemer * * Revision 1.19  2002/12/19 03:37:05  craigs * Simplified PChannel::WriteString * * Revision 1.18  2002/04/09 02:30:18  robertj * Removed GCC3 variable as __GNUC__ can be used instead, thanks jason Spence * * Revision 1.17  2002/01/26 23:57:45  craigs * Changed for GCC 3.0 compatibility, thanks to manty@manty.net * * Revision 1.16  2001/11/13 04:13:22  robertj * Added ability to adjust size of ios buffer on PChannels. * * Revision 1.15  2001/09/27 10:23:42  craigs * CHanged ReadString to allow read until end of input with P_MAX_INDEX arg * * Revision 1.14  2001/09/11 02:36:52  robertj * Fixed crash bug when ReadString() gets I/O error. * * Revision 1.13  2001/09/10 21:58:31  craigs * Fixed cut and paste problem that broke PIndirectChannel::Write * * Revision 1.12  2001/09/10 02:51:23  robertj * Major change to fix problem with error codes being corrupted in a *   PChannel when have simultaneous reads and writes in threads. * * Revision 1.11  2001/06/04 10:13:38  robertj * Added compare function to compare value of os_handle. * Added has function based on os_handle value. * * Revision 1.10  2001/01/02 06:07:07  robertj * Fixed race condition in reopening indirect channel, thanks Bertrand Croq. * * Revision 1.9  2000/11/14 08:25:58  robertj * Added function to propagate the error text through to indirect channel. * * Revision 1.8  2000/08/22 08:33:37  robertj * Removed PAssert() for write to unattached indirect channel, now sets *    return code so is similay to "unopened file" semantics. * * Revision 1.7  2000/06/26 11:17:20  robertj * Nucleus++ port (incomplete). * * 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>///////////////////////////////////////////////////////////////////////////////// PChannelPChannelStreamBuffer::PChannelStreamBuffer(PChannel * chan)  : channel(PAssertNULL(chan)){}BOOL PChannelStreamBuffer::SetBufferSize(PINDEX newSize){  return input.SetSize(newSize) && output.SetSize(newSize);}int PChannelStreamBuffer::overflow(int c){  if (pbase() == NULL) {    char * p = output.GetPointer(1024);    setp(p, p+output.GetSize());  }  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) {    char * p = input.GetPointer(1024);    char * e = p+input.GetSize();    setg(p, e, e);  }  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 (PIsDescendant(channel, PFile))      ((PFile *)channel)->SetPosition(-inAvail, PFile::Current);  }  if (pptr() > pbase())    return overflow();  return 0;}#if __USE_STL__streampos PChannelStreamBuffer::seekoff(off_type off, ios_base::seekdir dir, ios_base::openmode)#elsestreampos PChannelStreamBuffer::seekoff(streamoff off, ios::seek_dir dir, int)#endif{  sync();  if (PIsDescendant(channel, PFile)) {    PFile * file = (PFile *)channel;    file->SetPosition(off, (PFile::FilePositionOrigin)dir);    return file->GetPosition();  }  // If we have an input stream and the buffer is empty then force a read so  // we can seek ahead.  if (egptr() == gptr()) {    int c = underflow();    if (c == EOF)      return EOF;  }  while (off-- > 0) {    if (sbumpc() == EOF)      return EOF;  }      return egptr() - gptr();}#if __USE_STL__streampos PChannelStreamBuffer::seekpos(pos_type pos, ios_base::openmode mode){  return seekoff(pos, ios_base::beg, mode);}#endif#ifdef _MSC_VER#pragma warning(disable:4355)#endifPChannel::PChannel()  : iostream(new PChannelStreamBuffer(this)),    readTimeout(PMaxTimeInterval), writeTimeout(PMaxTimeInterval){  os_handle = -1;  memset(lastErrorCode, 0, sizeof(lastErrorCode));  memset(lastErrorNumber, 0, sizeof(lastErrorNumber));  lastReadCount = lastWriteCount = 0;  Construct();}#ifdef _MSC_VER#pragma warning(default:4355)#endifPChannel::~PChannel(){  flush();  Close();  delete (PChannelStreamBuffer *)rdbuf();#ifndef _WIN32  init(NULL);#endif}PObject::Comparison PChannel::Compare(const PObject & obj) const{  PAssert(PIsDescendant(&obj, PChannel), PInvalidCast);  int h1 = GetHandle();  int h2 = ((const PChannel&)obj).GetHandle();  if (h1 < h2)    return LessThan;  if (h1 > h2)    return GreaterThan;  return EqualTo;}PINDEX PChannel::HashFunction() const{  return GetHandle()%97;}BOOL PChannel::IsOpen() const{  return os_handle >= 0;}PINDEX PChannel::GetLastReadCount() const{   return lastReadCount; }PINDEX PChannel::GetLastWriteCount() const{   return lastWriteCount; }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;  if (len == P_MAX_INDEX) {    PINDEX l = 0;    for (;;) {      char * p = l + str.GetPointer(l+1000+1);      if (!Read(p, 1000))        break;      l += lastReadCount;    }    str.SetSize(l+1);    /*Need to put in a null at the end to allow for MSDOS/Win32 text files      which returns fewer bytes than actually read as it shrinks the data into      the removed carriage returns, so it actually changes the buffer beyond      what it indicated. */    str[l] = '\0';  }  else {    if (!ReadBlock(str.GetPointer(len+1), len))      return PString::Empty();  }  return str;}BOOL PChannel::WriteString(const PString & str){  return Write((const char *)str, str.GetLength()); }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){}BOOL PChannel::SetBufferSize(PINDEX newSize){  return ((PChannelStreamBuffer *)rdbuf())->SetBufferSize(newSize);}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){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -