StdBuf StdCompilerINIRead::ReadString(size_t iLength, RawCompileType eRawType, bool fAppendNull) { // Excpect valid position if (!pPos) { notFound("String"); return StdBuf(); } // Skip whitespace SkipWhitespace(); // Escaped? Go over '"' if (eRawType == RCT_Escaped && *pPos++ != '"') { notFound("Escaped string"); return StdBuf(); } // Create buffer StdBuf OutBuf; OutBuf.New(iLength + (fAppendNull ? sizeof('\0') : 0)); // Read char *pOut = getMBufPtr<char>(OutBuf); while (iLength && !TestStringEnd(eRawType)) { // Read a character if (eRawType == RCT_Escaped) *pOut++ = ReadEscapedChar(); else *pOut++ = *pPos++; // Count it iLength--; } // Escaped: Go over '"' if (eRawType == RCT_Escaped) { while (*pPos != '"') { if (!*pPos || *pPos == '\n' || *pPos == '\r') { Warn("string not terminated!"); pPos--; break; } pPos++; } pPos++; } // Nothing read? Identifiers need to be non-empty if (pOut == OutBuf.getData() && (eRawType == RCT_Idtf || eRawType == RCT_ID)) { notFound("String"); return StdBuf(); } // Append null if (fAppendNull) *pOut = '\0'; // Shrink, if less characters were read OutBuf.Shrink(iLength); // Done return OutBuf; }
StdBuf C4Playback::ReWriteBinary() { const int OUTPUT_GROW = 16 * 1024; StdBuf Output; int iPos = 0; bool fFinished = false; uint32_t iFrame = 0; for (chunks_t::const_iterator i = chunks.begin(); !fFinished && i != chunks.end(); i++) { // Check frame difference if (i->Frame - iFrame < 0 || i->Frame - iFrame > 0xff) LogF( "ERROR: Invalid frame difference between chunks (0-255 allowed)! " "Data will be invalid!"); // Pack data StdBuf Chunk; try { switch (i->Type) { case RCT_Ctrl: Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pCtrl); break; case RCT_CtrlPkt: Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pPkt); break; case RCT_End: fFinished = true; break; default: // debugrec if (i->pDbg) Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pDbg); break; } } catch (StdCompiler::Exception *pEx) { LogF("Record: Binary unpack error: %s", pEx->Msg.getData()); delete pEx; return StdBuf(); } // Grow output while (Output.getSize() - iPos < sizeof(C4RecordChunkHead) + Chunk.getSize()) Output.Grow(OUTPUT_GROW); // Write header C4RecordChunkHead *pHead = getMBufPtr<C4RecordChunkHead>(Output, iPos); pHead->Type = i->Type; pHead->iFrm = i->Frame - iFrame; iPos += sizeof(C4RecordChunkHead); iFrame = i->Frame; // Write chunk Output.Write(Chunk, iPos); iPos += Chunk.getSize(); } Output.SetSize(iPos); return Output; }
bool C4Record::Rec(int iFrame, const StdBuf &sBuf, C4RecordChunkType eType) { // filler chunks (this should never be necessary, though) while (iFrame > iLastFrame + 0xff) Rec(iLastFrame + 0xff, StdBuf(), RCT_Frame); // get frame difference uint32_t iFrameDiff = Max<uint32_t>(0, iFrame - iLastFrame); iLastFrame += iFrameDiff; // create head C4RecordChunkHead Head = {static_cast<uint8_t>(iFrameDiff), static_cast<uint8_t>(eType)}; // pack CtrlRec.Write(&Head, sizeof(Head)); CtrlRec.Write(sBuf.getData(), sBuf.getSize()); #ifdef IMMEDIATEREC // immediate rec: always flush CtrlRec.Flush(); #endif // Stream if (fStreaming) Stream(Head, sBuf); return true; }