/** * Writes the stream to a file. * * @returns IPRT status code * @param pStream The stream. * @param pszFilenameFmt The filename format string. * @param ... Format arguments. */ int ScmStreamWriteToFile(PSCMSTREAM pStream, const char *pszFilenameFmt, ...) { int rc; #ifdef RT_STRICT /* * Check that what we're going to write makes sense first. */ rc = ScmStreamCheckItegrity(pStream); if (RT_FAILURE(rc)) return rc; #endif /* * Do the actual writing. */ RTFILE hFile; va_list va; va_start(va, pszFilenameFmt); rc = RTFileOpenV(&hFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE, pszFilenameFmt, va); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, pStream->pch, pStream->cb, NULL); RTFileClose(hFile); } va_end(va); return rc; }
/** * Writes the stream to standard output. * * @returns IPRT status code * @param pStream The stream. */ int ScmStreamWriteToStdOut(PSCMSTREAM pStream) { int rc; #ifdef RT_STRICT /* * Check that what we're going to write makes sense first. */ rc = ScmStreamCheckItegrity(pStream); if (RT_FAILURE(rc)) return rc; #endif /* * Do the actual writing. */ RTHANDLE h; rc = RTHandleGetStandard(RTHANDLESTD_OUTPUT, &h); if (RT_SUCCESS(rc)) { switch (h.enmType) { case RTHANDLETYPE_FILE: rc = RTFileWrite(h.u.hFile, pStream->pch, pStream->cb, NULL); break; case RTHANDLETYPE_PIPE: rc = RTPipeWriteBlocking(h.u.hPipe, pStream->pch, pStream->cb, NULL); break; default: rc = VERR_INVALID_HANDLE; break; } } return rc; }
/** * Creates a diff of the changes between the streams @a pLeft and @a pRight. * * This currently only implements the simplest diff format, so no contexts. * * Also, note that we won't detect differences in the final newline of the * streams. * * @returns The number of differences. * @param pszFilename The filename. * @param pLeft The left side stream. * @param pRight The right side stream. * @param fIgnoreEol Whether to ignore end of line markers. * @param fIgnoreLeadingWhite Set if leading white space should be ignored. * @param fIgnoreTrailingWhite Set if trailing white space should be ignored. * @param fSpecialChars Whether to print special chars in a human * readable form or not. * @param cchTab The tab size. * @param pDiff Where to write the diff. */ size_t ScmDiffStreams(const char *pszFilename, PSCMSTREAM pLeft, PSCMSTREAM pRight, bool fIgnoreEol, bool fIgnoreLeadingWhite, bool fIgnoreTrailingWhite, bool fSpecialChars, size_t cchTab, PRTSTREAM pDiff) { #ifdef RT_STRICT ScmStreamCheckItegrity(pLeft); ScmStreamCheckItegrity(pRight); #endif /* * Set up the diff state. */ SCMDIFFSTATE State; State.cDiffs = 0; State.pszFilename = pszFilename; State.pLeft = pLeft; State.pRight = pRight; State.fIgnoreEol = fIgnoreEol; State.fIgnoreLeadingWhite = fIgnoreLeadingWhite; State.fIgnoreTrailingWhite = fIgnoreTrailingWhite; State.fSpecialChars = fSpecialChars; State.cchTab = cchTab; State.pDiff = pDiff; /* * Compare them line by line. */ ScmStreamRewindForReading(pLeft); ScmStreamRewindForReading(pRight); const char *pchLeft; const char *pchRight; for (;;) { SCMEOL enmEolLeft; size_t cchLeft; pchLeft = ScmStreamGetLine(pLeft, &cchLeft, &enmEolLeft); SCMEOL enmEolRight; size_t cchRight; pchRight = ScmStreamGetLine(pRight, &cchRight, &enmEolRight); if (!pchLeft || !pchRight) break; if (!scmDiffCompare(&State, pchLeft, cchLeft, enmEolLeft, pchRight, cchRight, enmEolRight)) scmDiffSynchronize(&State, 3); } /* * Deal with any remaining differences. */ if (pchLeft) scmDiffReport(&State, 0, ScmStreamTellLine(pLeft) - 1, ~(size_t)0, ScmStreamTellLine(pRight), 0); else if (pchRight) scmDiffReport(&State, 0, ScmStreamTellLine(pLeft), 0, ScmStreamTellLine(pRight) - 1, ~(size_t)0); /* * Report any errors. */ if (RT_FAILURE(ScmStreamGetStatus(pLeft))) RTMsgError("Left diff stream error: %Rrc\n", ScmStreamGetStatus(pLeft)); if (RT_FAILURE(ScmStreamGetStatus(pRight))) RTMsgError("Right diff stream error: %Rrc\n", ScmStreamGetStatus(pRight)); return State.cDiffs; }