]> git.saurik.com Git - apt.git/blob - apt-pkg/tagfile.cc
23fc344f3ff79f6ab585814a488798d1849f8613
[apt.git] / apt-pkg / tagfile.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: tagfile.cc,v 1.12 1998/10/24 04:58:06 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 /* */
28 pkgTagFile::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. */
40 bool 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 {
49 cout << string(Start,End-Start) << endl;
50 return _error->Error("Unable to parse package file");
51 }
52 }
53 Start += Tag.size();
54 iOffset += Tag.size();
55
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 */
63 bool pkgTagFile::Fill()
64 {
65 unsigned long EndSize = End - Start;
66
67 if (Left == 0)
68 {
69 if (EndSize <= 1)
70 return false;
71 return true;
72 }
73
74 memmove(Buffer,Start,EndSize);
75 Start = Buffer;
76 End = Buffer + EndSize;
77
78 // See if only a bit of the file is left
79 if (Left < Size - (End - Buffer))
80 {
81 if (Fd.Read(End,Left) == false)
82 return false;
83
84 End += Left;
85 Left = 0;
86 }
87 else
88 {
89 if (Fd.Read(End,Size - (End - Buffer)) == false)
90 {
91 cout << "boink" << endl;
92 return false;
93 }
94
95 Left -= Size - (End - Buffer);
96 End = Buffer + Size;
97 }
98 return true;
99 }
100 /*}}}*/
101 // TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/
102 // ---------------------------------------------------------------------
103 /* This jumps to a pre-recorded file location and */
104 bool 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 /*}}}*/
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. */
124 bool 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;
136
137 // Skip line feeds
138 for (; Stop[0] == '\r' && Stop < End; Stop++);
139
140 if (Stop[0] == '\n')
141 {
142 // Extra one at the end to simplify find
143 Indexes[TagCount] = Stop - Section;
144 for (; (Stop[0] == '\n' || Stop[0] == '\r') && Stop < End; Stop++);
145 return true;
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. */
161 bool 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--);
181
182 return true;
183 }
184 Start = End = 0;
185 return false;
186 }
187 /*}}}*/