Sync
[ntk/apt.git] / apt-pkg / tagfile.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
c88edf1d 3// $Id: tagfile.cc,v 1.12 1998/10/24 04:58: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/* */
8e06abb2 28pkgTagFile::pkgTagFile(FileFd &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)
0a8e3465
AL
48 {
49 cout << string(Start,End-Start) << endl;
578bfd0a 50 return _error->Error("Unable to parse package file");
0a8e3465 51 }
578bfd0a 52 }
dcb79bae
AL
53 Start += Tag.size();
54 iOffset += Tag.size();
55
578bfd0a
AL
56 return true;
57}
58 /*}}}*/
59// TagFile::Fill - Top up the buffer /*{{{*/
60// ---------------------------------------------------------------------
61/* This takes the bit at the end of the buffer and puts it at the start
62 then fills the rest from the file */
63bool pkgTagFile::Fill()
64{
ad00ae81 65 unsigned long EndSize = End - Start;
578bfd0a
AL
66
67 if (Left == 0)
68 {
ad00ae81 69 if (EndSize <= 1)
578bfd0a
AL
70 return false;
71 return true;
72 }
73
ad00ae81 74 memmove(Buffer,Start,EndSize);
578bfd0a 75 Start = Buffer;
ad00ae81 76 End = Buffer + EndSize;
578bfd0a 77
c88edf1d
AL
78 // See if only a bit of the file is left
79 if (Left < Size - (End - Buffer))
578bfd0a 80 {
ad00ae81 81 if (Fd.Read(End,Left) == false)
578bfd0a 82 return false;
c88edf1d 83
ad00ae81 84 End += Left;
578bfd0a
AL
85 Left = 0;
86 }
87 else
88 {
ad00ae81 89 if (Fd.Read(End,Size - (End - Buffer)) == false)
c88edf1d
AL
90 {
91 cout << "boink" << endl;
578bfd0a 92 return false;
c88edf1d
AL
93 }
94
ad00ae81
AL
95 Left -= Size - (End - Buffer);
96 End = Buffer + Size;
578bfd0a
AL
97 }
98 return true;
99}
100 /*}}}*/
ad00ae81
AL
101// TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/
102// ---------------------------------------------------------------------
103/* This jumps to a pre-recorded file location and */
104bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
105{
106 iOffset = Offset;
107 Left = Fd.Size() - Offset;
108 if (Fd.Seek(Offset) == false)
109 return false;
110 End = Start = Buffer;
111
112 if (Fill() == false)
113 return false;
114
115 if (Tag.Scan(Start,End - Start) == false)
116 return _error->Error("Unable to parse package file");
117 return true;
118}
119 /*}}}*/
578bfd0a
AL
120// TagSection::Scan - Scan for the end of the header information /*{{{*/
121// ---------------------------------------------------------------------
122/* This looks for the first double new line in the data stream. It also
123 indexes the tags in the section. */
124bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
125{
126 const char *End = Start + MaxLength;
127 Stop = Section = Start;
128
129 TagCount = 0;
130 Indexes[TagCount++] = Stop - Section;
131 Stop++;
132 for (; Stop < End; Stop++)
133 {
134 if (Stop[-1] != '\n')
135 continue;
0a8e3465
AL
136
137 // Skip line feeds
138 for (; Stop[0] == '\r' && Stop < End; Stop++);
139
578bfd0a
AL
140 if (Stop[0] == '\n')
141 {
142 // Extra one at the end to simplify find
143 Indexes[TagCount] = Stop - Section;
0a8e3465 144 for (; (Stop[0] == '\n' || Stop[0] == '\r') && Stop < End; Stop++);
578bfd0a 145 return true;
578bfd0a
AL
146 }
147
148 if (isspace(Stop[0]) == 0)
149 Indexes[TagCount++] = Stop - Section;
150
151 // Just in case.
152 if (TagCount > sizeof(Indexes)/sizeof(Indexes[0]))
153 TagCount = sizeof(Indexes)/sizeof(Indexes[0]);
154 }
155 return false;
156}
157 /*}}}*/
158// TagSection::Find - Locate a tag /*{{{*/
159// ---------------------------------------------------------------------
160/* This searches the section for a tag that matches the given string. */
161bool pkgTagSection::Find(const char *Tag,const char *&Start,
162 const char *&End)
163{
164 unsigned int Length = strlen(Tag);
165 for (unsigned int I = 0; I != TagCount; I++)
166 {
167 if (strncasecmp(Tag,Section + Indexes[I],Length) != 0)
168 continue;
169
170 // Make sure the colon is in the right place
171 const char *C = Section + Length + Indexes[I];
172 for (; isspace(*C) != 0; C++);
173 if (*C != ':')
174 continue;
175
176 // Strip off the gunk from the start end
177 Start = C;
178 End = Section + Indexes[I+1];
179 for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
180 for (; isspace(End[-1]) != 0 && End > Start; End--);
0a8e3465 181
578bfd0a
AL
182 return true;
183 }
184 Start = End = 0;
185 return false;
186}
187 /*}}}*/