Checkpoint
[ntk/apt.git] / apt-pkg / tagfile.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: tagfile.cc,v 1.2 1998/07/04 05:57:39 jgg Exp $
4 /* ######################################################################
5
6 Fast scanner for RFC-822 type header information
7
8 This uses a rotating 64K 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 #include <pkglib/tagfile.h>
15 #include <pkglib/error.h>
16
17 #include <string>
18 #include <stdio.h>
19 /*}}}*/
20
21 // TagFile::pkgTagFile - Constructor /*{{{*/
22 // ---------------------------------------------------------------------
23 /* */
24 pkgTagFile::pkgTagFile(File &Fd) : Fd(Fd)
25 {
26 Buffer = new char[64*1024];
27 Start = End = Buffer + 64*1024;
28 Left = Fd.Size();
29 Fill();
30 }
31 /*}}}*/
32 // TagFile::Step - Advance to the next section /*{{{*/
33 // ---------------------------------------------------------------------
34 /* If the Section Scanner fails we refill the buffer and try again. */
35 bool pkgTagFile::Step(pkgTagSection &Tag)
36 {
37 if (Tag.Scan(Start,End - Start) == false)
38 {
39 if (Fill() == false)
40 return false;
41
42 if (Tag.Scan(Start,End - Start) == false)
43 return _error->Error("Unable to parse package file");
44 }
45 Start += Tag.Length();
46 return true;
47 }
48 /*}}}*/
49 // TagFile::Fill - Top up the buffer /*{{{*/
50 // ---------------------------------------------------------------------
51 /* This takes the bit at the end of the buffer and puts it at the start
52 then fills the rest from the file */
53 bool pkgTagFile::Fill()
54 {
55 unsigned long Size = End - Start;
56
57 if (Left == 0)
58 {
59 if (Size <= 1)
60 return false;
61 return true;
62 }
63
64 memmove(Buffer,Start,Size);
65 Start = Buffer;
66
67 // See if only a bit of the file is left or if
68 if (Left < End - Buffer - Size)
69 {
70 if (Fd.Read(Buffer + Size,Left) == false)
71 return false;
72 End = Buffer + Size + Left;
73 Left = 0;
74 }
75 else
76 {
77 if (Fd.Read(Buffer + Size, End - Buffer - Size) == false)
78 return false;
79 Left -= End - Buffer - Size;
80 }
81 return true;
82 }
83 /*}}}*/
84 // TagSection::Scan - Scan for the end of the header information /*{{{*/
85 // ---------------------------------------------------------------------
86 /* This looks for the first double new line in the data stream. It also
87 indexes the tags in the section. */
88 bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
89 {
90 const char *End = Start + MaxLength;
91 Stop = Section = Start;
92
93 TagCount = 0;
94 Indexes[TagCount++] = Stop - Section;
95 Stop++;
96 for (; Stop < End; Stop++)
97 {
98 if (Stop[-1] != '\n')
99 continue;
100 if (Stop[0] == '\n')
101 {
102 // Extra one at the end to simplify find
103 Indexes[TagCount] = Stop - Section;
104 for (; Stop[0] == '\n' && Stop < End; Stop++);
105 return true;
106 break;
107 }
108
109 if (isspace(Stop[0]) == 0)
110 Indexes[TagCount++] = Stop - Section;
111
112 // Just in case.
113 if (TagCount > sizeof(Indexes)/sizeof(Indexes[0]))
114 TagCount = sizeof(Indexes)/sizeof(Indexes[0]);
115 }
116 return false;
117 }
118 /*}}}*/
119 // TagSection::Find - Locate a tag /*{{{*/
120 // ---------------------------------------------------------------------
121 /* This searches the section for a tag that matches the given string. */
122 bool pkgTagSection::Find(const char *Tag,const char *&Start,
123 const char *&End)
124 {
125 unsigned int Length = strlen(Tag);
126 for (unsigned int I = 0; I != TagCount; I++)
127 {
128 if (strncasecmp(Tag,Section + Indexes[I],Length) != 0)
129 continue;
130
131 // Make sure the colon is in the right place
132 const char *C = Section + Length + Indexes[I];
133 for (; isspace(*C) != 0; C++);
134 if (*C != ':')
135 continue;
136
137 // Strip off the gunk from the start end
138 Start = C;
139 End = Section + Indexes[I+1];
140 for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
141 for (; isspace(End[-1]) != 0 && End > Start; End--);
142 return true;
143 }
144 Start = End = 0;
145 return false;
146 }
147 /*}}}*/
148
149 #include <pkglib/pkgcachegen.h>
150 #include <pkglib/deblistparser.h>
151
152 int main(int argc,char *argv[])
153 {
154 {
155 File F(argv[1],File::ReadOnly);
156 File CacheF("./cache",File::WriteEmpty);
157 DynamicMMap Map(CacheF,MMap::Public);
158 pkgCacheGenerator Gen(Map);
159 Gen.SelectFile(argv[1]);
160
161 debListParser Parser(F);
162 Gen.MergeList(Parser);
163 }
164
165 {
166 File CacheF("./cache",File::WriteExists);
167 MMap Map(CacheF,MMap::Public);
168 pkgCache Cache(Map);
169 for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
170 {
171 cout << "Package: " << I.Name() << endl;
172 }
173 }
174
175 #if 0
176 pkgTagSection I;
177 while (Test.Step(I) == true)
178 {
179 const char *Start;
180 const char *End;
181 if (I.Find("Package",Start,End) == false)
182 {
183 cout << "Failed" << endl;
184 continue;
185 }
186
187 cout << "Package: " << string(Start,End - Start) << endl;
188
189 /* for (const char *I = Start; I < End; I++)
190 {
191 const char *Begin = I;
192 bool Number = true;
193 while (isspace(*I) == 0 && ispunct(*I) == 0 && I < End)
194 {
195 if (isalpha(*I) != 0)
196 Number = false;
197 I++;
198 }
199 if (Number == false)
200 cout << string(Begin,I-Begin) << endl;
201 while ((isspace(*I) != 0 || ispunct(*I) != 0) && I < End)
202 I++;
203 I--;
204 } */
205 }
206 #endif
207 _error->DumpErrors();
208 }