bool ReadString(char *str, int size) { char ch; if (bufpoint >= bufsize) { FillBuf(); } do // remove non symbolic data { if (PopFromBuf(&ch) == false) { return false; } } while (!IsLiteral(ch)); do { if (IsLiteral(ch)) { *str = ch; str++; } else // packet end { *str = 0; // add end of string return true; } } while (PopFromBuf(&ch) == true); return false; }
int RageFileObj::Read( void *pBuffer, size_t iBytes ) { int ret = 0; while( !m_bEOF && iBytes > 0 ) { if( m_pBuffer != NULL && m_iBufAvail ) { /* Copy data out of the buffer first. */ int iFromBuffer = min( (int) iBytes, m_iBufAvail ); memcpy( pBuffer, m_pBuf, iFromBuffer ); if( m_bCRC32Enabled ) CRC32( m_iCRC32, pBuffer, iFromBuffer ); ret += iFromBuffer; m_iFilePos += iFromBuffer; iBytes -= iFromBuffer; m_iBufAvail -= iFromBuffer; m_pBuf += iFromBuffer; pBuffer = (char *) pBuffer + iFromBuffer; } if( !iBytes ) break; ASSERT( m_iBufAvail == 0 ); /* If buffering is disabled, or the block is bigger than the buffer, * read the remainder of the data directly into the desteination buffer. */ if( m_pBuffer == NULL || iBytes >= BSIZE ) { /* We have a lot more to read, so don't waste time copying it into the * buffer. */ int iFromFile = this->ReadInternal( pBuffer, iBytes ); if( iFromFile == -1 ) return -1; if( iFromFile == 0 ) m_bEOF = true; if( m_bCRC32Enabled ) CRC32( m_iCRC32, pBuffer, iFromFile ); ret += iFromFile; m_iFilePos += iFromFile; return ret; } /* If buffering is enabled, and we need more data, fill the buffer. */ m_pBuf = m_pBuffer; int got = FillBuf(); if( got == -1 ) return got; if( got == 0 ) m_bEOF = true; } return ret; }
int RageFile::Read( void *buffer, size_t bytes ) { if( !IsOpen() ) RageException::Throw("\"%s\" is not open.", GetPath().c_str()); if( !(m_Mode&READ) ) RageException::Throw("\"%s\" is not open for reading", GetPath().c_str()); int ret = 0; while( !m_EOF && bytes > 0 ) { /* Copy data out of the buffer first. */ int FromBuffer = min( (int) bytes, m_BufAvail ); memcpy( buffer, m_pBuf, FromBuffer ); ret += FromBuffer; m_FilePos += FromBuffer; bytes -= FromBuffer; m_BufAvail -= FromBuffer; m_pBuf += FromBuffer; buffer = (char *) buffer + FromBuffer; if( !bytes ) break; ASSERT( !m_BufAvail ); /* We need more; either fill the buffer and keep going, or just read directly * into the destination buffer. */ if( bytes >= sizeof(m_Buffer) ) { /* We have a lot more to read, so don't waste time copying it into the * buffer. */ int FromFile = m_File->Read( buffer, bytes ); if( FromFile < 0 ) return FromFile; if( FromFile == 0 ) m_EOF = true; ret += FromFile; m_FilePos += FromFile; return ret; } m_pBuf = m_Buffer; int got = FillBuf(); if( got < 0 ) return got; if( got == 0 ) m_EOF = true; } return ret; }
/****************************************************************************** * \name _tasctime * \brief Converts a UTC time into a string and returns a pointer to it. * \param ptm Pointer to the UTC time. * \remarks The string is stored in thread local buffer, shared between * ctime, gmtime and localtime (32 and 64 bit versions). */ _TCHAR * _tasctime(const struct tm *ptm) { PTHREADDATA pThreadData; _TCHAR *pstr; /* Get pointer to TLS buffer */ pThreadData = GetThreadData(); #ifndef _UNICODE pstr = pThreadData->asctimebuf; #else pstr = pThreadData->wasctimebuf; #endif /* Fill the buffer */ FillBuf((timebuf_t*)pstr, ptm); return pstr; }
/****************************************************************************** * \name _tasctime * \brief Converts a UTC time into a string and returns a pointer to it. * \param ptm Pointer to the UTC time. * \remarks The string is stored in thread local buffer, shared between * ctime, gmtime and localtime (32 and 64 bit versions). */ _TCHAR * _tasctime(const struct tm *ptm) { thread_data_t *data = msvcrt_get_thread_data(); _TCHAR *pstr; #ifndef _UNICODE pstr = data->asctime_buffer; #else pstr = data->wasctime_buffer; #endif if(!pstr) pstr = malloc(sizeof(struct tm)); /* Fill the buffer */ FillBuf((timebuf_t*)pstr, ptm); return pstr; }
/****************************************************************************** * \name _tasctime_s * \brief Converts a local time into a string and returns a pointer to it. * \param buffer Buffer that receives the string (26 characters). * \param numberOfElements Size of the buffer in characters. * \param time Pointer to the UTC time. */ errno_t _tasctime_s( _TCHAR* buffer, size_t numberOfElements, const struct tm *ptm) { /* Validate parameters */ if (!buffer || numberOfElements < 26 || !ptm || (unsigned int)ptm->tm_sec > 59 || (unsigned int)ptm->tm_min > 59 || (unsigned int)ptm->tm_hour > 23 || (unsigned int)ptm->tm_mday > 31 || (unsigned int)ptm->tm_mon > 11 || (unsigned int)ptm->tm_year > 2038 || (unsigned int)ptm->tm_wday > 6 || (unsigned int)ptm->tm_yday > 365) { #if 0 _invalid_parameter(NULL, #ifdef UNICODE L"_wasctime", #else L"asctime", #endif _CRT_WIDE(__FILE__), __LINE__, 0); #endif return EINVAL; } /* Fill the buffer */ FillBuf((timebuf_t*)buffer, ptm); return 0; }
/* Retrieve audio data, for mixing. At the time of this call, the frameno at which the * sound will be played doesn't have to be known. Once committed, and the frameno * is known, call CommitPCMData. size is in bytes. * * If the data returned is at the end of the stream, return false. * * size is in frames * iSoundFrame is in frames (abstract) */ bool RageSound::GetDataToPlay( int16_t *pBuffer, int iSize, int &iSoundFrame, int &iFramesStored ) { int iNumRewindsThisCall = 0; /* We only update m_iDecodePosition; only take a shared lock, so we don't block the main thread. */ // LockMut(m_Mutex); ASSERT_M( m_bPlaying, ssprintf("%p", this) ); iFramesStored = 0; iSoundFrame = m_iDecodePosition; while( 1 ) { /* If we don't have any data left buffered, fill the buffer by * up to as much as we need. */ if( !Bytes_Available() ) FillBuf( iSize ); /* Get a block of data. */ int iGotFrames = GetData( (char *) pBuffer, iSize ); /* If we didn't get any data, see if we need to pad the end of the file with * silence for m_LengthSeconds. */ if( !iGotFrames && m_Param.m_LengthSeconds != -1 ) { const float LastSecond = m_Param.m_StartSecond + m_Param.m_LengthSeconds; int LastFrame = int(LastSecond*samplerate()); int FramesOfSilence = LastFrame - m_iDecodePosition; FramesOfSilence = clamp( FramesOfSilence, 0, iSize ); if( FramesOfSilence > 0 ) { memset( pBuffer, 0, FramesOfSilence * framesize ); iGotFrames = FramesOfSilence; } } if( !iGotFrames ) { /* EOF. */ switch( GetStopMode() ) { case RageSoundParams::M_STOP: /* Not looping. Normally, we'll just stop here. */ return false; case RageSoundParams::M_LOOP: /* Rewind and restart. */ iNumRewindsThisCall++; if( iNumRewindsThisCall > 3 ) { /* We're rewinding a bunch of times in one call. This probably means * that the length is too short. It might also mean that the start * position is very close to the end of the file, so we're looping * over the remainder. If we keep doing this, we'll chew CPU rewinding, * so stop. */ LOG->Warn( "Sound %s is busy looping. Sound stopped (start = %f, length = %f)", GetLoadedFilePath().c_str(), m_Param.m_StartSecond, m_Param.m_LengthSeconds ); return false; } /* Rewind and start over. XXX: this will take an exclusive lock */ SetPositionSeconds( m_Param.m_StartSecond ); /* Make sure we can get some data. If we can't, then we'll have * nothing to send and we'll just end up coming back here. */ if( !Bytes_Available() ) FillBuf( iSize ); if( GetData(NULL, iSize) == 0 ) { LOG->Warn( "Can't loop data in %s; no data available at start point %f", GetLoadedFilePath().c_str(), m_Param.m_StartSecond ); /* Stop here. */ return false; } continue; case RageSoundParams::M_CONTINUE: /* Keep playing silence. */ memset( pBuffer, 0, iSize*framesize ); iGotFrames = iSize; break; default: ASSERT(0); } } /* This block goes from m_iDecodePosition to m_iDecodePosition+iGotFrames. */ /* We want to fade when there's m_FadeLength seconds left, but if * m_LengthFrames is -1, we don't know the length we're playing. * (m_LengthFrames is the length to play, not the length of the * source.) If we don't know the length, don't fade. */ if( m_Param.m_FadeLength != 0 && m_Param.m_LengthSeconds != -1 ) { const float fFinishFadingOutAt = m_Param.m_StartSecond + m_Param.m_LengthSeconds; const float fStartFadingOutAt = fFinishFadingOutAt - m_Param.m_FadeLength; const float fStartSecond = float(m_iDecodePosition) / samplerate(); const float fEndSecond = float(m_iDecodePosition+iGotFrames) / samplerate(); const float fStartVolume = SCALE( fStartSecond, fStartFadingOutAt, fFinishFadingOutAt, 1.0f, 0.0f ); const float fEndVolume = SCALE( fEndSecond, fStartFadingOutAt, fFinishFadingOutAt, 1.0f, 0.0f ); RageSoundUtil::Fade( pBuffer, iGotFrames, fStartVolume, fEndVolume ); } RageSoundUtil::Pan( pBuffer, iGotFrames, m_Param.m_Balance ); iSoundFrame = m_iDecodePosition; iFramesStored = iGotFrames; m_iDecodePosition += iGotFrames; return true; } }
/* Read up to the next \n, and return it in out. Strip the \n. If the \n is * preceded by a \r (DOS newline), strip that, too. */ int RageFile::GetLine( CString &out ) { out = ""; if ( !IsOpen() ) RageException::Throw("\"%s\" is not open.", m_Path.c_str()); if( !(m_Mode&READ) ) RageException::Throw("\"%s\" is not open for reading", GetPath().c_str()); if( m_EOF ) return 0; bool GotData = false; while( 1 ) { bool done = false; /* Find the end of the block we'll move to out. */ char *p = (char *) memchr( m_pBuf, '\n', m_BufAvail ); bool ReAddCR = false; if( p == NULL ) { /* Hack: If the last character of the buffer is \r, then it's likely that an * \r\n has been split across buffers. Move everything else, then move the * \r to the beginning of the buffer and handle it the next time around the loop. */ if( m_BufAvail && m_pBuf[m_BufAvail-1] == '\r' ) { ReAddCR = true; --m_BufAvail; } p = m_pBuf+m_BufAvail; /* everything */ } else done = true; if( p >= m_pBuf ) { char *RealEnd = p; if( done && p > m_pBuf && p[-1] == '\r' ) --RealEnd; /* not including \r */ out.append( m_pBuf, RealEnd ); if( done ) ++p; /* skip \n */ const int used = p-m_pBuf; if( used ) { m_BufAvail -= used; m_FilePos += used; GotData = true; m_pBuf = p; } } if( ReAddCR ) { ASSERT( m_BufAvail == 0 ); m_pBuf = m_Buffer; m_Buffer[m_BufAvail] = '\r'; ++m_BufAvail; } if( done ) break; /* We need more data. */ m_pBuf = m_Buffer; const int size = FillBuf(); /* If we've read data already, then don't mark EOF yet. Wait until the * next time we're called. */ if( size == 0 && !GotData ) { m_EOF = true; return 0; } if( size == -1 ) return -1; // error if( size == 0 ) break; // EOF or error } return GotData? 1:0; }