DumpAvail works and apt-cache is complete
[ntk/apt.git] / apt-pkg / tagfile.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
ad00ae81 3// $Id: tagfile.cc,v 1.9 1998/07/19 04:22:06 jgg Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Fast scanner for RFC-822 type header information
7
ad00ae81 8 This uses a rotating buffer to load the package information into.
578bfd0a
AL
9 The scanner runs over it and isolates and indexes a single section.
10
11 ##################################################################### */
12 /*}}}*/
13// Include Files /*{{{*/
6c139d6e 14#ifdef __GNUG__
094a497d 15#pragma implementation "apt-pkg/tagfile.h"
6c139d6e
AL
16#endif
17
094a497d
AL
18#include <apt-pkg/tagfile.h>
19#include <apt-pkg/error.h>
578bfd0a
AL
20
21#include <string>
22#include <stdio.h>
23 /*}}}*/
24
25// TagFile::pkgTagFile - Constructor /*{{{*/
26// ---------------------------------------------------------------------
27/* */
ad00ae81 28pkgTagFile::pkgTagFile(File &Fd,unsigned long Size) : Fd(Fd), Size(Size)
578bfd0a 29{
ad00ae81
AL
30 Buffer = new char[Size];
31 Start = End = Buffer;
578bfd0a 32 Left = Fd.Size();
dcb79bae 33 iOffset = 0;
578bfd0a
AL
34 Fill();
35}
36 /*}}}*/
37// TagFile::Step - Advance to the next section /*{{{*/
38// ---------------------------------------------------------------------
39/* If the Section Scanner fails we refill the buffer and try again. */
40bool pkgTagFile::Step(pkgTagSection &Tag)
41{
42 if (Tag.Scan(Start,End - Start) == false)
43 {
44 if (Fill() == false)
45 return false;
46
47 if (Tag.Scan(Start,End - Start) == false)
48 return _error->Error("Unable to parse package file");
49 }
dcb79bae
AL
50 Start += Tag.size();
51 iOffset += Tag.size();
52
578bfd0a
AL
53 return true;
54}
55 /*}}}*/
56// TagFile::Fill - Top up the buffer /*{{{*/
57// ---------------------------------------------------------------------
58/* This takes the bit at the end of the buffer and puts it at the start
59 then fills the rest from the file */
60bool pkgTagFile::Fill()
61{
ad00ae81 62 unsigned long EndSize = End - Start;
578bfd0a
AL
63
64 if (Left == 0)
65 {
ad00ae81 66 if (EndSize <= 1)
578bfd0a
AL
67 return false;
68 return true;
69 }
70
ad00ae81 71 memmove(Buffer,Start,EndSize);
578bfd0a 72 Start = Buffer;
ad00ae81 73 End = Buffer + EndSize;
578bfd0a 74
ad00ae81
AL
75 // See if only a bit of the file is left
76 if (Left < Size)
578bfd0a 77 {
ad00ae81 78 if (Fd.Read(End,Left) == false)
578bfd0a 79 return false;
ad00ae81 80 End += Left;
578bfd0a
AL
81 Left = 0;
82 }
83 else
84 {
ad00ae81 85 if (Fd.Read(End,Size - (End - Buffer)) == false)
578bfd0a 86 return false;
ad00ae81
AL
87 Left -= Size - (End - Buffer);
88 End = Buffer + Size;
578bfd0a
AL
89 }
90 return true;
91}
92 /*}}}*/
ad00ae81
AL
93// TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/
94// ---------------------------------------------------------------------
95/* This jumps to a pre-recorded file location and */
96bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
97{
98 iOffset = Offset;
99 Left = Fd.Size() - Offset;
100 if (Fd.Seek(Offset) == false)
101 return false;
102 End = Start = Buffer;
103
104 if (Fill() == false)
105 return false;
106
107 if (Tag.Scan(Start,End - Start) == false)
108 return _error->Error("Unable to parse package file");
109 return true;
110}
111 /*}}}*/
578bfd0a
AL
112// TagSection::Scan - Scan for the end of the header information /*{{{*/
113// ---------------------------------------------------------------------
114/* This looks for the first double new line in the data stream. It also
115 indexes the tags in the section. */
116bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
117{
118 const char *End = Start + MaxLength;
119 Stop = Section = Start;
120
121 TagCount = 0;
122 Indexes[TagCount++] = Stop - Section;
123 Stop++;
124 for (; Stop < End; Stop++)
125 {
126 if (Stop[-1] != '\n')
127 continue;
128 if (Stop[0] == '\n')
129 {
130 // Extra one at the end to simplify find
131 Indexes[TagCount] = Stop - Section;
132 for (; Stop[0] == '\n' && Stop < End; Stop++);
133 return true;
134 break;
135 }
136
137 if (isspace(Stop[0]) == 0)
138 Indexes[TagCount++] = Stop - Section;
139
140 // Just in case.
141 if (TagCount > sizeof(Indexes)/sizeof(Indexes[0]))
142 TagCount = sizeof(Indexes)/sizeof(Indexes[0]);
143 }
144 return false;
145}
146 /*}}}*/
147// TagSection::Find - Locate a tag /*{{{*/
148// ---------------------------------------------------------------------
149/* This searches the section for a tag that matches the given string. */
150bool pkgTagSection::Find(const char *Tag,const char *&Start,
151 const char *&End)
152{
153 unsigned int Length = strlen(Tag);
154 for (unsigned int I = 0; I != TagCount; I++)
155 {
156 if (strncasecmp(Tag,Section + Indexes[I],Length) != 0)
157 continue;
158
159 // Make sure the colon is in the right place
160 const char *C = Section + Length + Indexes[I];
161 for (; isspace(*C) != 0; C++);
162 if (*C != ':')
163 continue;
164
165 // Strip off the gunk from the start end
166 Start = C;
167 End = Section + Indexes[I+1];
168 for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
169 for (; isspace(End[-1]) != 0 && End > Start; End--);
170 return true;
171 }
172 Start = End = 0;
173 return false;
174}
175 /*}}}*/