scmstream.cpp revision b20cc298c1a3191a4e6ce780c19313117902675d
/* $Id$ */
/** @file
* IPRT Testcase / Tool - Source Code Massager Stream Code.
*/
/*
* Copyright (C) 2010-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "scmstream.h"
/**
* Initializes the stream structure.
*
* @param pStream The stream structure.
* @param fWriteOrRead The value of the fWriteOrRead stream member.
*/
{
pStream->cbAllocated = 0;
pStream->cLinesAllocated = 0;
pStream->fFileMemory = false;
pStream->fFullyLineated = false;
}
/**
* Initialize an input stream.
*
* @returns IPRT status code.
* @param pStream The stream to initialize.
* @param pszFilename The file to take the stream content from.
*/
{
void *pvFile;
if (RT_SUCCESS(rc))
{
pStream->fFileMemory = true;
}
return rc;
}
/**
* Initialize an output stream.
*
* @returns IPRT status code
* @param pStream The stream to initialize.
* @param pRelatedStream Pointer to a related stream. NULL is fine.
*/
{
/* allocate stuff */
: _64K;
{
: cbEstimate / 24;
{
return VINF_SUCCESS;
}
}
}
/**
* Frees the resources associated with the stream.
*
* Nothing is happens to whatever the stream was initialized from or dumped to.
*
* @param pStream The stream to delete.
*/
{
{
if (pStream->fFileMemory)
else
}
pStream->cbAllocated = 0;
{
}
pStream->cLinesAllocated = 0;
}
/**
* Get the stream status code.
*
* @returns IPRT status code.
* @param pStream The stream.
*/
{
}
/**
* Grows the buffer of a write stream.
*
* @returns IPRT status code.
* @param pStream The stream. Must be in write mode.
* @param cbAppending The minimum number of bytes to grow the buffer
* with.
*/
{
void *pvNew;
if (!pStream->fFileMemory)
{
if (!pvNew)
}
else
{
if (!pvNew)
pStream->fFileMemory = false;
}
return VINF_SUCCESS;
}
/**
* Grows the line array of a stream.
*
* @returns IPRT status code.
* @param pStream The stream.
* @param iMinLine Minimum line number.
*/
{
if (!pvNew)
return VINF_SUCCESS;
}
/**
* Rewinds the stream and sets the mode to read.
*
* @param pStream The stream.
*/
{
pStream->fWriteOrRead = false;
}
/**
* Rewinds the stream and sets the mode to write.
*
* @param pStream The stream.
*/
{
pStream->fWriteOrRead = true;
pStream->fFullyLineated = true;
}
/**
* Checks if it's a text stream.
*
* Not 100% proof.
*
* @returns true if it probably is a text file, false if not.
* @param pStream The stream. Write or read, doesn't matter.
*/
{
return false;
return false;
return true;
}
/**
* Performs an integrity check of the stream.
*
* @returns IPRT status code.
* @param pStream The stream.
*/
{
/*
* Perform sanity checks.
*/
{
{
case SCMEOL_LF:
break;
case SCMEOL_CRLF:
break;
case SCMEOL_NONE:
break;
default:
}
}
return VINF_SUCCESS;
}
/**
* Writes the stream to a file.
*
* @returns IPRT status code
* @param pStream The stream.
* @param pszFilenameFmt The filename format string.
* @param ... Format arguments.
*/
{
int rc;
#ifdef RT_STRICT
/*
* Check that what we're going to write makes sense first.
*/
if (RT_FAILURE(rc))
return rc;
#endif
/*
* Do the actual writing.
*/
rc = RTFileOpenV(&hFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE, pszFilenameFmt, va);
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Writes the stream to standard output.
*
* @returns IPRT status code
* @param pStream The stream.
*/
{
int rc;
#ifdef RT_STRICT
/*
* Check that what we're going to write makes sense first.
*/
if (RT_FAILURE(rc))
return rc;
#endif
/*
* Do the actual writing.
*/
RTHANDLE h;
if (RT_SUCCESS(rc))
{
switch (h.enmType)
{
case RTHANDLETYPE_FILE:
break;
case RTHANDLETYPE_PIPE:
break;
default:
break;
}
}
return rc;
}
/**
* Worker for ScmStreamGetLine that builds the line number index while parsing
* the stream.
*
* @returns Same as SCMStreamGetLine.
* @param pStream The stream. Must be in read mode.
* @param pcchLine Where to return the line length.
* @param penmEol Where to return the kind of end of line marker.
*/
{
return NULL;
{
pStream->fFullyLineated = true;
return NULL;
}
{
if (RT_FAILURE(rc))
return NULL;
}
{
if ( cb < 1
else
{
cb--;
}
}
else
{
}
return pchRet;
}
/**
* Internal worker that delineates a stream.
*
* @returns IPRT status code.
* @param pStream The stream. Caller must check that it is in
* read mode.
*/
{
/* Save the stream position. */
/* Get each line. */
/* nothing */;
/* Restore the position */
}
/**
* Get the current stream position as an byte offset.
*
* @returns The current byte offset
* @param pStream The stream.
*/
{
}
/**
* Get the current stream position as a line number.
*
* @returns The current line (0-based).
* @param pStream The stream.
*/
{
}
/**
* Gets the stream offset of a given line.
*
* @returns The offset of the line, or the stream size if the line number is too
* high.
* @param pStream The stream. Must be in read mode.
* @param iLine The line we're asking about.
*/
{
if (!pStream->fFullyLineated)
{
}
}
/**
* Get the current stream size in bytes.
*
* @returns Count of bytes.
* @param pStream The stream.
*/
{
}
/**
* Gets the number of lines in the stream.
*
* @returns The number of lines.
* @param pStream The stream.
*/
{
if (!pStream->fFullyLineated)
}
/**
* Seeks to a given byte offset in the stream.
*
* @returns IPRT status code.
* @retval VERR_SEEK if the new stream position is the middle of an EOL marker.
* This is a temporary restriction.
*
* @param pStream The stream. Must be in read mode.
* @param offAbsolute The offset to seek to. If this is beyond the
* end of the stream, the position is set to the
* end.
*/
{
/* Must be fully delineated. (lazy bird) */
{
if (RT_FAILURE(rc))
return rc;
}
/* Ok, do the job. */
{
/** @todo Should do a binary search here, but I'm too darn lazy tonight. */
{
{
break;
}
}
}
else
{
}
return VINF_SUCCESS;
}
/**
* Seeks a number of bytes relative to the current stream position.
*
* @returns IPRT status code.
* @retval VERR_SEEK if the new stream position is the middle of an EOL marker.
* This is a temporary restriction.
*
* @param pStream The stream. Must be in read mode.
* @param offRelative The offset to seek to. A negative offset
* rewinds and positive one fast forwards the
* stream. Will quietly stop at the beginning and
* end of the stream.
*/
{
if (offRelative >= 0)
else
offAbsolute = 0;
}
/**
* Seeks to a given line in the stream.
*
* @returns IPRT status code.
*
* @param pStream The stream. Must be in read mode.
* @param iLine The line to seek to. If this is beyond the end
* of the stream, the position is set to the end.
*/
{
/* Must be fully delineated. (lazy bird) */
{
if (RT_FAILURE(rc))
return rc;
}
/* Ok, do the job. */
{
}
else
{
}
return VINF_SUCCESS;
}
/**
* Get a numbered line from the stream (changes the position).
*
* A line is always delimited by a LF character or the end of the stream. The
* delimiter is not included in returned line length, but instead returned via
* the @a penmEol indicator.
*
* @returns Pointer to the first character in the line, not NULL terminated.
* NULL if the end of the stream has been reached or some problem
* occurred.
*
* @param pStream The stream. Must be in read mode.
* @param iLine The line to get (0-based).
* @param pcchLine The length.
* @param penmEol Where to return the end of line type indicator.
*/
const char *ScmStreamGetLineByNo(PSCMSTREAM pStream, size_t iLine, size_t *pcchLine, PSCMEOL penmEol)
{
return NULL;
/* Make sure it's fully delineated so we can use the index. */
{
if (RT_FAILURE(rc))
return NULL;
}
/* End of stream? */
{
return NULL;
}
/* Get the data. */
/* update the stream position. */
pStream->off = pStream->paLines[iLine].off + pStream->paLines[iLine].cch + pStream->paLines[iLine].enmEol;
return pchRet;
}
/**
* Get a line from the stream.
*
* A line is always delimited by a LF character or the end of the stream. The
* delimiter is not included in returned line length, but instead returned via
* the @a penmEol indicator.
*
* @returns Pointer to the first character in the line, not NULL terminated.
* NULL if the end of the stream has been reached or some problem
* occurred.
*
* @param pStream The stream. Must be in read mode.
* @param pcchLine The length.
* @param penmEol Where to return the end of line type indicator.
*/
{
if (!pStream->fFullyLineated)
if ( pszLine
{
else
*pcchLine = 0;
}
return pszLine;
}
/**
* Get the current buffer pointer.
*
* @returns Buffer pointer on success, NULL on failure (asserted).
* @param pStream The stream. Must be in read mode.
*/
{
}
/**
* Gets a character from the stream.
*
* @returns The next unsigned character in the stream.
* ~(unsigned)0 on failure.
* @param pStream The stream. Must be in read mode.
*/
{
/* Check stream state. */
return ~(unsigned)0;
{
if (RT_FAILURE(rc))
return ~(unsigned)0;
}
/* If there isn't enough stream left, fail already. */
return ~(unsigned)0;
/* Read a character. */
/* Advance the line indicator. */
if (pStream->off >= pStream->paLines[iLine].off + pStream->paLines[iLine].cch + pStream->paLines[iLine].enmEol)
return (unsigned)ch;
}
/**
* Peeks at the next character from the stream.
*
* @returns The next unsigned character in the stream.
* ~(unsigned)0 on failure.
* @param pStream The stream. Must be in read mode.
*/
{
/* Check stream state. */
return ~(unsigned)0;
{
if (RT_FAILURE(rc))
return ~(unsigned)0;
}
/* If there isn't enough stream left, fail already. */
return ~(unsigned)0;
/* Peek at the next character. */
return (unsigned)ch;
}
/**
* Reads @a cbToRead bytes into @a pvBuf.
*
* Will fail if end of stream is encountered before the entire read has been
* completed.
*
* @returns IPRT status code.
* @retval VERR_EOF if there isn't @a cbToRead bytes left to read. Stream
* position will be unchanged.
*
* @param pStream The stream. Must be in read mode.
* @param pvBuf The buffer to read into.
* @param cbToRead The number of bytes to read.
*/
{
/* If there isn't enough stream left, fail already. */
return VERR_EOF;
/* Copy the data and simply seek to the new stream position. */
}
/**
* Checks if the given line is empty or full of white space.
*
* @returns true if white space only, false if not (or if non-existant).
* @param pStream The stream. Must be in read mode.
* @param iLine The line in question.
*/
{
if (!pchLine)
return false;
return cchLine == 0;
}
/**
* Try figure out the end of line style of the give stream.
*
* @returns Most likely end of line style.
* @param pStream The stream.
*/
{
else
{
else
}
if (enmEol == SCMEOL_NONE)
#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
#else
#endif
return enmEol;
}
/**
* Get the end of line indicator type for a line.
*
* @returns The EOL indicator. If the line isn't found, the default EOL
* indicator is return.
* @param pStream The stream.
* @param iLine The line (0-base).
*/
{
else
#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
#else
#endif
return enmEol;
}
/**
* Appends a line to the stream.
*
* @returns IPRT status code.
* @param pStream The stream. Must be in write mode.
* @param pchLine Pointer to the line.
* @param cchLine Line length.
* @param enmEol Which end of line indicator to use.
*/
{
/*
* Make sure the previous line has a new-line indicator.
*/
if (RT_UNLIKELY( iLine != 0
{
{
if (RT_FAILURE(rc))
return rc;
}
else
{
}
}
/*
* Ensure we've got sufficient buffer space.
*/
{
if (RT_FAILURE(rc))
return rc;
}
/*
* Add a line record.
*/
{
if (RT_FAILURE(rc))
return rc;
}
iLine++;
/*
* Copy the line
*/
else if (enmEol == SCMEOL_CRLF)
{
}
/*
* Start a new line.
*/
return VINF_SUCCESS;
}
/**
* Writes to the stream.
*
* @returns IPRT status code
* @param pStream The stream. Must be in write mode.
* @param pchBuf What to write.
* @param cchBuf How much to write.
*/
{
/*
* Ensure we've got sufficient buffer space.
*/
{
if (RT_FAILURE(rc))
return rc;
}
/*
* Deal with the odd case where we've already pushed a line with SCMEOL_NONE.
*/
if (RT_UNLIKELY( iLine > 0
{
iLine--;
}
/*
* Deal with lines.
*/
if (!pchLF)
else
{
for (;;)
{
{
if (RT_FAILURE(rc))
{
return rc;
}
}
if ( cchLine
else
{
cchLine--;
}
iLine++;
if (!pchLF)
{
break;
}
}
}
/*
* Copy the data and update position and size.
*/
return VINF_SUCCESS;
}
/**
* Write a character to the stream.
*
* @returns IPRT status code
* @param pStream The stream. Must be in write mode.
* @param pchBuf What to write.
* @param cchBuf How much to write.
*/
{
/*
* Only deal with the simple cases here, use ScmStreamWrite for the
* annoying stuff.
*/
if ( ch == '\n'
/*
* Just append it.
*/
return VINF_SUCCESS;
}
/**
* Formats a string and writes it to the SCM stream.
*
* @returns The number of bytes written (>= 0). Negative value are IPRT error
* status codes.
* @param pStream The stream to write to.
* @param pszFormat The format string.
* @param va The arguments to format.
*/
{
char *psz;
if (cch)
{
if (RT_FAILURE(rc))
}
return cch;
}
/**
* Formats a string and writes it to the SCM stream.
*
* @returns The number of bytes written (>= 0). Negative value are IPRT error
* status codes.
* @param pStream The stream to write to.
* @param pszFormat The format string.
* @param ... The arguments to format.
*/
{
return cch;
}
/**
* Copies @a cLines from the @a pSrc stream onto the @a pDst stream.
*
* The stream positions will be used and changed in both streams.
*
* @returns IPRT status code.
* @param pDst The destination stream. Must be in write mode.
* @param cLines The number of lines. (0 is accepted.)
* @param pSrc The source stream. Must be in read mode.
*/
{
while (cLines-- > 0)
{
if (!pchLine)
if (RT_FAILURE(rc))
return rc;
}
return VINF_SUCCESS;
}
/**
* If the given C word is at off - 1, return @c true and skip beyond it,
* otherwise return @c false.
*
* @retval true if the given C-word is at the current position minus one char.
* The stream position changes.
* @retval false if not. The stream position is unchanged.
*
* @param pStream The stream.
* @param cchWord The length of the word.
* @param pszWord The word.
*/
{
/* Check stream state. */
/* Sufficient chars left on the line? */
size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1);
return false;
/* Do they match? */
return false;
/* Is it the end of a C word? */
{
return false;
}
/* Skip ahead. */
return true;
}
/**
* Get's the C word starting at the current position.
*
* @returns Pointer to the word on success and the stream position advanced to
* the end of it.
* NULL on failure, stream position normally unchanged.
* @param pStream The stream to get the C word from.
* @param pcchWord Where to return the word length.
*/
{
/* Check stream state. */
/* Get the number of chars left on the line and locate the current char. */
/* Is it a leading C character. */
return NULL;
/* Find the end of the word. */
char ch;
|| RT_C_IS_ALNUM(ch)))
off++;
return psz;
}
/**
* Get's the C word starting at the current position minus one.
*
* @returns Pointer to the word on success and the stream position advanced to
* the end of it.
* NULL on failure, stream position normally unchanged.
* @param pStream The stream to get the C word from.
* @param pcchWord Where to return the word length.
*/
{
/* Check stream state. */
/* Get the number of chars left on the line and locate the current char. */
size_t const cchLeft = pStream->paLines[iLine].cch + pStream->paLines[iLine].off - (pStream->off - 1);
/* Is it a leading C character. */
return NULL;
/* Find the end of the word. */
char ch;
|| RT_C_IS_ALNUM(ch)))
off++;
return psz;
}