当前位置: 首页>>代码示例>>C++>>正文


C++ WaitCommEvent函数代码示例

本文整理汇总了C++中WaitCommEvent函数的典型用法代码示例。如果您正苦于以下问题:C++ WaitCommEvent函数的具体用法?C++ WaitCommEvent怎么用?C++ WaitCommEvent使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了WaitCommEvent函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: serialMonitorWaitLines

int
serialMonitorWaitLines (SerialDevice *serial) {
  DWORD event;

  if (WaitCommEvent(serial->package.fileHandle, &event, NULL)) return 1;
  logWindowsSystemError("WaitCommEvent");
  return 0;
}
开发者ID:plundblad,项目名称:brltty,代码行数:8,代码来源:serial_windows.c

示例2: rxqueue_count

int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size)
{
    COMSTAT  stat;
    DWORD error;
    DWORD msk,length;
    if (returned_size==NULL) returned_size=(size_t *)&length;

    
    if ( isOpened()) {
        size_t rxqueue_remaining =  rxqueue_count();
        if (rxqueue_remaining >= data_count) {
            *returned_size = rxqueue_remaining;
            return 0;
        }
    }

    while ( isOpened() )
    {
        msk = 0;
        SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR );
        if(!WaitCommEvent(_serial_handle, &msk, &_wait_o))
        {
            if(GetLastError() == ERROR_IO_PENDING)
            {
                if (WaitForSingleObject(_wait_o.hEvent, timeout) == WAIT_TIMEOUT)
                {
                    *returned_size =0;
                    return ANS_TIMEOUT;
                }

                GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE);

                ::ResetEvent(_wait_o.hEvent);
            }else
            {
                ClearCommError(_serial_handle, &error, &stat);
                 *returned_size = stat.cbInQue;
                return ANS_DEV_ERR;
            }
        }

        if(msk & EV_ERR){
            // FIXME: may cause problem here
            ClearCommError(_serial_handle, &error, &stat);
        }

        if(msk & EV_RXCHAR){
            ClearCommError(_serial_handle, &error, &stat);
            if(stat.cbInQue >= data_count)
            {
                *returned_size = stat.cbInQue;
                return 0;
            }
        }
    }
    *returned_size=0;
    return ANS_DEV_ERR;
}
开发者ID:intel-cornellcup,项目名称:rplidar,代码行数:58,代码来源:net_serial.cpp

示例3: ProcessRead

/*------------------------------------------------------------------------------
-- FUNCTION:    PortIOThreadProc
--
-- DATE:        Oct 13, 2010
--
-- REVISIONS:   Nov 05, 2010
--              Modified the function to also listen for a "disconnect" event,
--              and to break in that case. ProcessRead() is now called once a 
--				complete packet is confirmed (as opposed to sending the 
--				contents of the buffer to ProcessRead() as soon as they arrive).
--
--				Nov 29, 2010
--				Renamed function from ReadThreadProc(). The event handling is
--				from the original function, but the response to each event has
--				changed.
--
-- DESIGNER:    Dean Morin
--
-- PROGRAMMER:  Dean Morin, Daniel Wright
--
-- INTERFACE:   DWORD WINAPI PortIOThreadProc(HWND hWnd)
--                      hWnd - the handle to the window
--
-- RETURNS:     0 because threads are required to return a DWORD.
--
-- NOTES:
--              While connected, this thread will loop and wait for characters
--              to arrive at the port, or for a timeout to occur, then call the
--				appropriate function. This function uses overlapped I/O.
------------------------------------------------------------------------------*/
DWORD WINAPI PortIOThreadProc(HWND hWnd) {
    OVERLAPPED  ol		= {0};
    DWORD       dwEvent = 0;
    DWORD       dwError = 0;
    COMSTAT     cs      = {0};
    HANDLE*     hEvents = NULL;
    PSTATEINFO  psi     = NULL;
    PWNDDATA	pwd		= (PWNDDATA) GetWindowLongPtr(hWnd, 0);
    

    if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
        DISPLAY_ERROR("Error creating event in read thread");
    }
    hEvents     = (HANDLE*) malloc(sizeof(HANDLE) * PORT_IO_EVENTS);
    hEvents[0]  = CreateEvent(NULL, FALSE, FALSE, TEXT("disconnected"));
    hEvents[1]  = ol.hEvent;
    
    psi = (PSTATEINFO) malloc(sizeof(STATEINFO));
    InitStateInfo(psi);
    DL_STATE = psi->iState;


    while (pwd->bConnected) {
        
        SetCommMask(pwd->hPort, EV_RXCHAR);      
        if (!WaitCommEvent(pwd->hPort, &dwEvent, &ol)) {
            ProcessCommError(pwd->hPort);
        }
        dwEvent = WaitForMultipleObjects(PORT_IO_EVENTS, hEvents, FALSE, 
                                         psi->dwTimeout);
        ClearCommError(pwd->hPort, &dwError, &cs);
 
        if (dwEvent == WAIT_OBJECT_0) {
            // the connection was severed
            break;
        }
        else if (dwEvent == WAIT_OBJECT_0 + 1  &&  cs.cbInQue) {
            // data arrived at the port
            ReadFromPort(hWnd, psi, ol, cs.cbInQue);
        }
        else if (dwEvent == WAIT_TIMEOUT) {
            // a timeout occured
            ProcessTimeout(hWnd, psi);
        }
        else if (dwEvent == WAIT_FAILED) {
            DISPLAY_ERROR("Invalid event occured in the Port I/O thread");
        }
        ResetEvent(ol.hEvent);
    }

    if (!PurgeComm(pwd->hPort, PURGE_RXCLEAR)) {
        DISPLAY_ERROR("Error purging read buffer");
    }
    CloseHandle(ol.hEvent);
    CloseHandle(hEvents[0]);
    free(hEvents);
    return 0;
}
开发者ID:deanmorin,项目名称:wireless,代码行数:88,代码来源:Physical.c

示例4: readyRead

void VirtualSerialDevice::commEventOccurred()
{
    DWORD event = d->commEventMask;
    if (event & EV_RXCHAR) {
        emit readyRead();
    }
    ResetEvent(d->commEventOverlapped.hEvent);
    WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped);
}
开发者ID:KDE,项目名称:android-qt-creator,代码行数:9,代码来源:virtualserialdevice_win.cpp

示例5: source_wait

static int source_wait(serial_source src, struct timeval *deadline)
/* Effects: waits until deadline for some data on source. deadline
     can be NULL for indefinite waiting.
   Returns: 0 if data is available, -1 if the deadline expires
*/
{
#ifndef LOSE32
  struct timeval tv;
  fd_set fds;
  int cnt;

  if (src->recv.bufpos < src->recv.bufused)
    return 0;

  for (;;)
    {
      if (deadline)
	{
	  gettimeofday(&tv, NULL);
	  tv.tv_sec = deadline->tv_sec - tv.tv_sec;
	  tv.tv_usec = deadline->tv_usec - tv.tv_usec;
	  if (tv.tv_usec < 0)
	    {
	      tv.tv_usec += 1000000;
	      tv.tv_sec--;
	    }
	  if (tv.tv_sec < 0)
	    return -1;
	}

      FD_ZERO(&fds);
      FD_SET(src->fd, &fds);
      cnt = select(src->fd + 1, &fds, NULL, NULL, deadline ? &tv : NULL);
      if (cnt < 0)
	{
	  if (errno == EINTR)
	    continue;
	  message(src, msg_unix_error);
	  return -1;
	}
      if (cnt == 0)
	return -1;
      return 0;
    }
#else // LOSE32
    // FIXME: the deadline is ignored here

    DWORD eventMask;
    SetCommMask(src->hComm, EV_RXCHAR);
    if (!WaitCommEvent(src->hComm, &eventMask, NULL)) {
        return -1;
    }

    return 0;

#endif
}
开发者ID:mszczodrak,项目名称:otf,代码行数:57,代码来源:serialsource.c

示例6: initCOMPort

//initializes the dongle COM port
void initCOMPort() {
	DCB dcb = {};
	COMMTIMEOUTS timeouts;
	timeouts.ReadIntervalTimeout = 15;
	timeouts.ReadTotalTimeoutConstant = 15;
	timeouts.ReadTotalTimeoutMultiplier = 15;
	timeouts.WriteTotalTimeoutConstant = 20;
	timeouts.WriteTotalTimeoutMultiplier = 10;


	osReaderDongle.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
	osWriteDongle.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
	osStatusDongle.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);

	hCOMDongle = CreateFile(COMPORTDONGLE, GENERIC_READ | GENERIC_WRITE, 0, NULL, //COM3 on the NUC
		OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (hCOMDongle == INVALID_HANDLE_VALUE) {
		prints(L"ERROR OPENING DONGLE COM PORT\n");
	}
	else {
		prints(L"USB dongle COM port 3 opened\n");
	}

	ZeroMemory(&dcb, sizeof(DCB));
	dcb.DCBlength = sizeof(DCB);
	if (!GetCommState(hCOMDongle, &dcb))
	{
		prints(L"Dongle GetCommState failed with error %X.\n", GetLastError());
	}

	dcb.BaudRate = 19200;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.EvtChar = '\n';

	if (!SetCommState(hCOMDongle, &dcb))
	{
		prints(L"Dongle SetCommState failed with error %X.\n", GetLastError());
	}
	if (!SetCommTimeouts(hCOMDongle, &timeouts)) {
		prints(L"Dongle SetCommTimeouts failed with error %d.\n", GetLastError());
	}
	if (!SetCommMask(hCOMDongle, EV_RXCHAR)) {
		prints(L"SetCommMask failed with error %d.\n", GetLastError());
	}

	if (WaitCommEvent(hCOMDongle, &dwCommEventDongle, &osStatusDongle)) {
		prints(L"Main board wait Com event %X\n", dwCommEvent);
	}
	else {
		if (GetLastError() != ERROR_IO_PENDING) {
			prints(L"WaitCommEvent failed with error %d\n", GetLastError());
		}
	}
	prints(L"Dongle COM init end\r\n\r\n");
}
开发者ID:LKarel,项目名称:Empire-Robot,代码行数:58,代码来源:ROBOTEX.cpp

示例7: defined

// Wait up to msec for data to become available for reading.
// return 0 if timeout, or non-zero if one or more bytes are
// received and can be read.  -1 if an error occurs
int Serial::Input_wait(int msec)
{
	if (!port_is_open) return -1;
#if defined(LINUX) || defined(MACOSX)
	fd_set rfds;
	struct timeval tv;
	tv.tv_sec = msec / 1000;
	tv.tv_usec = (msec % 1000) * 1000;
	FD_ZERO(&rfds);
	FD_SET(port_fd, &rfds);
	return select(port_fd+1, &rfds, NULL, NULL, &tv);
#elif defined(WINDOWS)
	// http://msdn2.microsoft.com/en-us/library/aa363479(VS.85).aspx
	// http://msdn2.microsoft.com/en-us/library/aa363424(VS.85).aspx
	// http://source.winehq.org/WineAPI/WaitCommEvent.html
	COMSTAT st;
	DWORD errmask=0, eventmask=EV_RXCHAR, ret;
	OVERLAPPED ov;
	int r;
	// first, request comm event when characters arrive
	if (!SetCommMask(port_handle, EV_RXCHAR)) return -1;
	// look if there are characters in the buffer already
	if (!ClearCommError(port_handle, &errmask, &st)) return -1;
	//printf("Input_wait, %lu buffered, timeout = %d ms\n", st.cbInQue, msec);
	if (st.cbInQue > 0) return 1;

	ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (ov.hEvent == NULL) return -1;
	ov.Internal = ov.InternalHigh = 0;
	ov.Offset = ov.OffsetHigh = 0;
	if (WaitCommEvent(port_handle, &eventmask, &ov)) {
		//printf("Input_wait, WaitCommEvent, immediate success\n");
		r = 1;
	} else {
		if (GetLastError() == ERROR_IO_PENDING) {
			ret = WaitForSingleObject(ov.hEvent, msec);
			if (ret == WAIT_OBJECT_0) {
				//printf("Input_wait, WaitCommEvent, delayed success\n");
				r = 1;
			} else if (ret == WAIT_TIMEOUT) {
				//printf("Input_wait, WaitCommEvent, timeout\n");
				GetCommMask(port_handle, &eventmask);
				r = 0;
			} else {  // WAIT_FAILED or WAIT_ABANDONED
				//printf("Input_wait, WaitCommEvent, delayed error\n");
				r = -1;
			}
		} else {
			//printf("Input_wait, WaitCommEvent, immediate error\n");
			r = -1;
		}
	}
	SetCommMask(port_handle, 0);
	CloseHandle(ov.hEvent);
	return r;
#endif
}
开发者ID:RDju,项目名称:knobot_soft,代码行数:60,代码来源:serial.cpp

示例8: readSerial

static BOOL readSerial(ClientElem_t *pClient, char* buffer, int maxRead, int* pRead, int timeout) {
	BOOL res;
	if (!pClient->pendingCommRd) {
		res = WaitCommEvent(pClient->serialHdl, &pClient->commMaskRd, &pClient->ovCommRd);
		if (!res) {
			int err = GetLastError();
			if (err != ERROR_IO_PENDING) {
				// readfile call error
				return FALSE;
			} else {
				pClient->pendingCommRd = TRUE;
				*pRead = 0;
				return TRUE;
			}
		}
	}
	res = WaitForSingleObject(pClient->ovCommRd.hEvent, timeout);
	ResetEvent(pClient->ovCommRd.hEvent);
	if (res == WAIT_TIMEOUT) {
		*pRead = 0;
		return TRUE;
	} else if (res != WAIT_OBJECT_0) {
		return FALSE;
	} 
	pClient->pendingCommRd = FALSE;

	res = ReadFile(pClient->serialHdl, buffer, maxRead, pRead, &pClient->ovRd);
	if (!res) {
		int err = GetLastError();
		if (err != ERROR_IO_PENDING) {
			// readfile call error
			return FALSE;
		} else {
			// async op
			res = WaitForSingleObject(pClient->ovRd.hEvent, timeout);
			if (res == WAIT_TIMEOUT) {
				*pRead = 0;
				return TRUE;
			} else if (res != WAIT_OBJECT_0) {
				return FALSE;
			} 
			res = GetOverlappedResult(pClient->serialHdl, &pClient->ovRd, pRead, FALSE);
			if (!res) {
				int err = GetLastError();
				return FALSE;
			}
			ResetEvent(pClient->ovRd.hEvent);

		}
	} else {
		// sync op
	}
	
	DBG_PRINT("uart-->%i", *pRead);
	return TRUE;
}
开发者ID:pellepl,项目名称:cnc_ctrl,代码行数:56,代码来源:uartsocket.c

示例9: sizeof

/*!
Opens a serial port.  Note that this function does not specify which device to open.  If you need
to open a device by name, see QextSerialPort::open(const char*).  This function has no effect
if the port associated with the class is already open.  The port is also configured to the current
settings, as stored in the Settings structure.
*/
bool QextSerialPort::open(OpenMode mode) {
    unsigned long confSize = sizeof(COMMCONFIG);
    Win_CommConfig.dwSize = confSize;
    DWORD dwFlagsAndAttributes = 0;
    if (queryMode() == QextSerialPort::EventDriven)
        dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;

    QMutexLocker lock(mutex);
    if (mode == QIODevice::NotOpen)
        return isOpen();
    if (!isOpen()) {
        /*open the port*/
        Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
                              0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
        if (Win_Handle!=INVALID_HANDLE_VALUE) {
            QIODevice::open(mode);
            /*configure port settings*/
            GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
            GetCommState(Win_Handle, &(Win_CommConfig.dcb));

            /*set up parameters*/
            Win_CommConfig.dcb.fBinary=TRUE;
            Win_CommConfig.dcb.fInX=FALSE;
            Win_CommConfig.dcb.fOutX=FALSE;
            Win_CommConfig.dcb.fAbortOnError=FALSE;
            Win_CommConfig.dcb.fNull=FALSE;
            setBaudRate(Settings.BaudRate);
            setDataBits(Settings.DataBits);
            setStopBits(Settings.StopBits);
            setParity(Settings.Parity);
            setFlowControl(Settings.FlowControl);
            setTimeout(Settings.Timeout_Millisec);
            SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));

            //init event driven approach
            if (queryMode() == QextSerialPort::EventDriven) {
                Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
                Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
                Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
                Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
                Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
                SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
                if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
                    qWarning() << "failed to set Comm Mask. Error code:", GetLastError();
                    return false;
                }
                winEventNotifier = new QWinEventNotifier(overlap.hEvent, this);
                connect(winEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(onWinEvent(HANDLE)));
                WaitCommEvent(Win_Handle, &eventMask, &overlap);
            }
        }
    } else {
        return false;
    }
    return isOpen();
}
开发者ID:M-Elfeki,项目名称:Auto_Pilot,代码行数:62,代码来源:win_qextserialport.cpp

示例10: _flush_uart

int _flush_uart(int out, int in)
{
	DWORD dw;

	if(out=FDISCARD) PurgeComm(port, PURGE_TXCLEAR);
	else if(out) WaitCommEvent(port, &dw, NULL);
	if(in) PurgeComm(port, PURGE_RXCLEAR);

	return 0;
}
开发者ID:abidbodal,项目名称:firmware_upgrader_k20,代码行数:10,代码来源:serialw32.c

示例11: Wait

BOOL Serial::Wait(DWORD timeout)
{
//	SetCommMask(m_hComm,EV_RXCHAR);
	DWORD dwEvent;
	if(!WaitCommEvent(m_hComm,&dwEvent,NULL))
	{
	}

	return TRUE;
}
开发者ID:Biotron,项目名称:kpgweigher,代码行数:10,代码来源:serial1.cpp

示例12: ResetEvent

void Win_QextSerialPort::monitorCommEvent()
{
    DWORD eventMask = 0;

    ResetEvent(m_Overlap.hEvent);
    if (!WaitCommEvent(m_WinHandle, & eventMask, & m_Overlap))
    {
        if (GetLastError() != ERROR_IO_PENDING)
        {
            qCritical("WaitCommEvent error %ld\n", GetLastError());
        }
    }

    if (WaitForSingleObject(m_Overlap.hEvent, INFINITE) == WAIT_OBJECT_0) 
    {
        //overlap event occured
        DWORD undefined;
        if (!GetOverlappedResult(m_WinHandle, & m_Overlap, & undefined, false)) 
        {
            qWarning("Comm event overlapped error %ld", GetLastError());
            return;
        }
        if (eventMask & EV_RXCHAR) 
        {
            if (sender() != this)
                emit readyRead();
        }
        if (eventMask & EV_TXEMPTY) 
        {
            DWORD numBytes;
            GetOverlappedResult(m_WinHandle, & m_OverlapWrite, & numBytes, true);
            m_pBytesToWriteLock->lockForWrite();

            if (sender() != this)
            {
                emit bytesWritten(bytesToWrite());
            }

            m_BytesToWrite = 0;
            m_pBytesToWriteLock->WriteUnlock();
        }
        if (eventMask & EV_DSR)
        {
            if (lineStatus() & LS_DSR)
            {
                emit dsrChanged(true);
            }
            else
            {
                emit dsrChanged(false);
            }
        }
    }
}
开发者ID:dulton,项目名称:53_hero,代码行数:54,代码来源:win_qextserialport.cpp

示例13: ASSERT

void CSerialPort::WaitEvent(DWORD& dwMask)
{
  ASSERT(IsOpen());
  ASSERT(!m_bOverlapped);

  if (!WaitCommEvent(m_hComm, &dwMask, NULL))
  {
    TRACE(_T("Failed in call to WaitCommEvent\n"));
    AfxThrowSerialException();
  }
}
开发者ID:freegroup,项目名称:DigitalSimulator,代码行数:11,代码来源:SerialPort.cpp

示例14: WaitCommThread

DWORD
WaitCommThread(
    LPVOID Trash
    )
{

    DWORD ReasonSatisfied;
    DWORD Trash2;
    OVERLAPPED Ol;
    UNREFERENCED_PARAMETER(Trash);

    Ol.hEvent = WaitEvent;
    do {

        if (!WaitCommEvent(
                 hFile,
                 &ReasonSatisfied,
                 &Ol
                 )) {

            DWORD LastError = GetLastError();

            if (LastError == ERROR_IO_PENDING) {

                if (!GetOverlappedResult(
                         hFile,
                         &Ol,
                         &Trash2,
                         TRUE
                         )) {

                    WaitForSingleObject(IoSemaphore,-1);
                    printf("Could not do the getoverlapped on the wait: %d\n",GetLastError());
                    ReleaseSemaphore(IoSemaphore,1,NULL);

                }

            } else {

                WaitForSingleObject(IoSemaphore,-1);
                printf("Could not start the wait: %d\n",LastError);
                ReleaseSemaphore(IoSemaphore,1,NULL);

            }

        }

    } while (TRUE);

    return 1;

}
开发者ID:BillTheBest,项目名称:WinNT4,代码行数:52,代码来源:tmskstr.c

示例15: ser_windows_wait_handle

static void
ser_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
    struct ser_windows_state *state;
    COMSTAT status;
    DWORD errors;
    HANDLE h = (HANDLE) _get_osfhandle (scb->fd);

    state = scb->state;

    *except = state->except_event;
    *read = state->ov.hEvent;

    if (state->in_progress)
        return;

    /* Reset the mask - we are only interested in any characters which
       arrive after this point, not characters which might have arrived
       and already been read.  */

    /* This really, really shouldn't be necessary - just the second one.
       But otherwise an internal flag for EV_RXCHAR does not get
       cleared, and we get a duplicated event, if the last batch
       of characters included at least two arriving close together.  */
    if (!SetCommMask (h, 0))
        warning (_("ser_windows_wait_handle: reseting mask failed"));

    if (!SetCommMask (h, EV_RXCHAR))
        warning (_("ser_windows_wait_handle: reseting mask failed (2)"));

    /* There's a potential race condition here; we must check cbInQue
       and not wait if that's nonzero.  */

    ClearCommError (h, &errors, &status);
    if (status.cbInQue > 0)
    {
        SetEvent (state->ov.hEvent);
        return;
    }

    state->in_progress = 1;
    ResetEvent (state->ov.hEvent);
    state->lastCommMask = -2;
    if (WaitCommEvent (h, &state->lastCommMask, &state->ov))
    {
        gdb_assert (state->lastCommMask & EV_RXCHAR);
        SetEvent (state->ov.hEvent);
    }
    else
        gdb_assert (GetLastError () == ERROR_IO_PENDING);
}
开发者ID:sergiodj,项目名称:gdb-sergio,代码行数:51,代码来源:ser-mingw.c


注:本文中的WaitCommEvent函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。