class pkgTagFilePrivate
{
public:
- pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Size(Size)
+ pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Buffer(NULL),
+ Start(NULL), End(NULL),
+ Done(false), iOffset(0),
+ Size(Size)
{
}
FileFd &Fd;
/* */
pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size)
{
+ /* The size is increased by 4 because if we start with the Size of the
+ filename we need to try to read 1 char more to see an EOF faster, 1
+ char the end-pointer can be on and maybe 2 newlines need to be added
+ to the end of the file -> 4 extra chars */
+ Size += 4;
d = new pkgTagFilePrivate(pFd, Size);
if (d->Fd.IsOpen() == false)
- {
d->Start = d->End = d->Buffer = 0;
+ else
+ d->Buffer = (char*)malloc(sizeof(char) * Size);
+
+ if (d->Buffer == NULL)
d->Done = true;
- d->iOffset = 0;
- return;
- }
-
- d->Buffer = new char[Size];
+ else
+ d->Done = false;
+
d->Start = d->End = d->Buffer;
- d->Done = false;
d->iOffset = 0;
- Fill();
+ if (d->Done == false)
+ Fill();
}
/*}}}*/
// TagFile::~pkgTagFile - Destructor /*{{{*/
/* */
pkgTagFile::~pkgTagFile()
{
- delete [] d->Buffer;
+ free(d->Buffer);
delete d;
}
/*}}}*/
-// TagFile::Offset - Return the current offset in the buffer /*{{{*/
+// TagFile::Offset - Return the current offset in the buffer /*{{{*/
unsigned long pkgTagFile::Offset()
{
return d->iOffset;
*/
bool pkgTagFile::Resize()
{
- char *tmp;
- unsigned long long EndSize = d->End - d->Start;
-
// fail is the buffer grows too big
if(d->Size > 1024*1024+1)
return false;
+ return Resize(d->Size * 2);
+}
+bool pkgTagFile::Resize(unsigned long long const newSize)
+{
+ unsigned long long const EndSize = d->End - d->Start;
+
// get new buffer and use it
- tmp = new char[2*d->Size];
- memcpy(tmp, d->Buffer, d->Size);
- d->Size = d->Size*2;
- delete [] d->Buffer;
- d->Buffer = tmp;
+ char* newBuffer = (char*)realloc(d->Buffer, sizeof(char) * newSize);
+ if (newBuffer == NULL)
+ return false;
+ d->Buffer = newBuffer;
+ d->Size = newSize;
// update the start/end pointers to the new buffer
d->Start = d->Buffer;
if (d->Done == false)
{
// See if only a bit of the file is left
- if (d->Fd.Read(d->End, d->Size - (d->End - d->Buffer),&Actual) == false)
+ unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1);
+ if (d->Fd.Read(d->End, dataSize, &Actual) == false)
return false;
- if (Actual != d->Size - (d->End - d->Buffer))
+ if (Actual != dataSize)
d->Done = true;
d->End += Actual;
}
for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--)
if (*E == '\n')
LineCount++;
- for (; LineCount < 2; LineCount++)
- *d->End++ = '\n';
+ if (LineCount < 2)
+ {
+ if ((unsigned)(d->End - d->Buffer) >= d->Size)
+ Resize(d->Size + 3);
+ for (; LineCount < 2; LineCount++)
+ *d->End++ = '\n';
+ }
return true;
}
return true;
}
/*}}}*/
+// pkgTagSection::pkgTagSection - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgTagSection::pkgTagSection()
+ : Section(0), TagCount(0), d(NULL), Stop(0)
+{
+ memset(&Indexes, 0, sizeof(Indexes));
+ memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+}
+ /*}}}*/
// TagSection::Scan - Scan for the end of the header information /*{{{*/
// ---------------------------------------------------------------------
/* This looks for the first double new line in the data stream.
TagCount = 0;
while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
{
- TrimRecord(true,End);
+ TrimRecord(true,End);
+
+ // this can happen when TrimRecord trims away the entire Record
+ // (e.g. because it just contains comments)
+ if(Stop == End)
+ return true;
// Start a new index and add it to the hash
if (isspace(Stop[0]) == 0)
if (Stop == 0)
return false;
- for (; Stop+1 < End && Stop[1] == '\r'; Stop++);
+ for (; Stop+1 < End && Stop[1] == '\r'; Stop++)
+ /* nothing */
+ ;
// Double newline marks the end of the record
if (Stop+1 < End && Stop[1] == '\n')
for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--);
}
/*}}}*/
+// TagSection::Exists - return True if a tag exists /*{{{*/
+bool pkgTagSection::Exists(const char* const Tag)
+{
+ unsigned int tmp;
+ return Find(Tag, tmp);
+}
+ /*}}}*/
// TagSection::Find - Locate a tag /*{{{*/
// ---------------------------------------------------------------------
/* This searches the section for a tag that matches the given string. */
-bool pkgTagSection::Find(const char *Tag,unsigned &Pos) const
+bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
{
unsigned int Length = strlen(Tag);
unsigned int I = AlphaIndexes[AlphaHash(Tag)];