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