]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/strutl.cc
DumpAvail works and apt-cache is complete
[apt.git] / apt-pkg / contrib / strutl.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
ad00ae81 3// $Id: strutl.cc,v 1.3 1998/07/19 04:22:08 jgg Exp $
6c139d6e
AL
4/* ######################################################################
5
6 String Util - Some usefull string functions.
7
8 strstrip - Remove whitespace from the front and end of a line.
9
10 This source is placed in the Public Domain, do with it what you will
11 It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
12
13 ##################################################################### */
14 /*}}}*/
15// Includes /*{{{*/
16#include <strutl.h>
17#include <ctype.h>
18#include <string.h>
19#include <stdio.h>
20 /*}}}*/
21
22// strstrip - Remove white space from the front and back of a string /*{{{*/
23// ---------------------------------------------------------------------
24/* This is handy to use when parsing a file. It also removes \n's left
25 over from fgets and company */
26char *_strstrip(char *String)
27{
28 for (;*String != 0 && (*String == ' ' || *String == '\t'); String++);
29
30 if (*String == 0)
31 return String;
32
33 char *End = String + strlen(String) - 1;
34 for (;End != String - 1 && (*End == ' ' || *End == '\t' || *End == '\n' ||
35 *End == '\r'); End--);
36 End++;
37 *End = 0;
38 return String;
39};
40 /*}}}*/
41// strtabexpand - Converts tabs into 8 spaces /*{{{*/
42// ---------------------------------------------------------------------
43/* */
44char *_strtabexpand(char *String,size_t Len)
45{
46 for (char *I = String; I != I + Len && *I != 0; I++)
47 {
48 if (*I != '\t')
49 continue;
50 if (I + 8 > String + Len)
51 {
52 *I = 0;
53 return String;
54 }
55
56 /* Assume the start of the string is 0 and find the next 8 char
57 division */
58 int Len;
59 if (String == I)
60 Len = 1;
61 else
62 Len = 8 - ((String - I) % 8);
63 Len -= 2;
64 if (Len <= 0)
65 {
66 *I = ' ';
67 continue;
68 }
69
70 memmove(I + Len,I + 1,strlen(I) + 1);
71 for (char *J = I; J + Len != I; *I = ' ', I++);
72 }
73 return String;
74}
75 /*}}}*/
76// ParseQuoteWord - Parse a single word out of a string /*{{{*/
77// ---------------------------------------------------------------------
78/* This grabs a single word, converts any % escaped characters to their
79 proper values and advances the pointer. Double quotes are understood
80 and striped out as well. */
81bool ParseQuoteWord(const char *&String,string &Res)
82{
83 // Skip leading whitespace
84 const char *C = String;
85 for (;*C != 0 && *C == ' '; C++);
86 if (*C == 0)
87 return false;
88
89 // Jump to the next word
90 for (;*C != 0 && *C != ' '; C++)
91 {
92 if (*C == '"')
93 {
94 for (C++;*C != 0 && *C != '"'; C++);
95 if (*C == 0)
96 return false;
97 }
98 }
99
100 // Now de-quote characters
101 char Buffer[1024];
102 char Tmp[3];
103 const char *Start = String;
104 char *I;
105 for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
106 {
107 if (*Start == '%' && Start + 2 < C)
108 {
109 Tmp[0] = Start[1];
110 Tmp[1] = Start[2];
111 Tmp[3] = 0;
112 *I = (char)strtol(Tmp,0,16);
113 Start += 3;
114 continue;
115 }
116 if (*Start != '"')
117 *I = *Start;
118 else
119 I--;
120 Start++;
121 }
122 *I = 0;
123 Res = Buffer;
124
125 // Skip ending white space
126 for (;*C != 0 && *C == ' '; C++);
127 String = C;
128 return true;
129}
130 /*}}}*/
131// QuoteString - Convert a string into quoted from /*{{{*/
132// ---------------------------------------------------------------------
133/* */
134string QuoteString(string Str,const char *Bad)
135{
136 string Res;
137 for (string::iterator I = Str.begin(); I != Str.end(); I++)
138 {
139 if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
140 *I <= 0x20 || *I >= 0x7F)
141 {
142 char Buf[10];
143 sprintf(Buf,"%%%02x",(int)*I);
144 Res += Buf;
145 }
146 else
147 Res += *I;
148 }
149 return Res;
150}
151 /*}}}*/
152// SizeToStr - Convert a long into a human readable size /*{{{*/
153// ---------------------------------------------------------------------
154/* A max of 4 digits are shown before conversion to the next highest unit. The
155 max length of the string will be 5 chars unless the size is > 10
156 YottaBytes (E24) */
157string SizeToStr(double Size)
158{
159 char S[300];
160 double ASize;
161 if (Size >= 0)
162 ASize = Size;
163 else
164 ASize = -1*Size;
165
166 /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes,
167 ExaBytes, ZettaBytes, YottaBytes */
168 char Ext[] = {'b','k','M','G','T','P','E','Z','Y'};
169 int I = 0;
170 while (I <= 8)
171 {
172 if (ASize < 100 && I != 0)
173 {
174 sprintf(S,"%.1f%c",ASize,Ext[I]);
175 break;
176 }
177
178 if (ASize < 10000)
179 {
180 sprintf(S,"%.0f%c",ASize,Ext[I]);
181 break;
182 }
183 ASize /= 1000.0;
184 I++;
185 }
186
187 return S;
188}
189 /*}}}*/
190// TimeToStr - Convert the time into a string /*{{{*/
191// ---------------------------------------------------------------------
192/* Converts a number of seconds to a hms format */
193string TimeToStr(unsigned long Sec)
194{
195 char S[300];
196
197 while (1)
198 {
199 if (Sec > 60*60*24)
200 {
201 sprintf(S,"%lid %lih%lim%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
202 break;
203 }
204
205 if (Sec > 60*60)
206 {
207 sprintf(S,"%lih%lim%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
208 break;
209 }
210
211 if (Sec > 60)
212 {
213 sprintf(S,"%lim%lis",Sec/60,Sec % 60);
214 break;
215 }
216
217 sprintf(S,"%lis",Sec);
218 break;
219 }
220
221 return S;
222}
223 /*}}}*/
224// SubstVar - Substitute a string for another string /*{{{*/
225// ---------------------------------------------------------------------
226/* This replaces all occurances of Subst with Contents in Str. */
227string SubstVar(string Str,string Subst,string Contents)
228{
8efa2a3b 229 string::size_type Pos = 0;
6c139d6e
AL
230 string::size_type OldPos = 0;
231 string Temp;
232
233 while (OldPos < Str.length() &&
234 (Pos = Str.find(Subst,OldPos)) != string::npos)
235 {
236 Temp += string(Str,OldPos,Pos) + Contents;
237 OldPos = Pos + Subst.length();
238 }
239
240 if (OldPos == 0)
241 return Str;
242
243 return Temp + string(Str,OldPos);
244}
245 /*}}}*/
ad00ae81
AL
246// URItoFileName - Convert the uri into a unique file name /*{{{*/
247// ---------------------------------------------------------------------
248/* This converts a URI into a safe filename. It quotes all unsafe characters
249 and converts / to _ and removes the scheme identifier. The resulting
250 file name should be unique and never occur again for a different file */
251string URItoFileName(string URI)
252{
253 string::const_iterator I = URI.begin() + URI.find(':') + 1;
254 for (; I < URI.end() && *I == '/'; I++);
255
256 // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
257 URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
258 string::iterator J = URI.begin();
259 for (; J != URI.end(); J++)
260 if (*J == '/')
261 *J = '_';
262 return URI;
263}
264 /*}}}*/
6c139d6e
AL
265// Base64Encode - Base64 Encoding routine for short strings /*{{{*/
266// ---------------------------------------------------------------------
267/* This routine performs a base64 transformation on a string. It was ripped
268 from wget and then patched and bug fixed.
269
270 This spec can be found in rfc2045 */
271string Base64Encode(string S)
272{
273 // Conversion table.
274 static char tbl[64] = {'A','B','C','D','E','F','G','H',
275 'I','J','K','L','M','N','O','P',
276 'Q','R','S','T','U','V','W','X',
277 'Y','Z','a','b','c','d','e','f',
278 'g','h','i','j','k','l','m','n',
279 'o','p','q','r','s','t','u','v',
280 'w','x','y','z','0','1','2','3',
281 '4','5','6','7','8','9','+','/'};
282
283 // Pre-allocate some space
284 string Final;
285 Final.reserve((4*S.length() + 2)/3 + 2);
286
287 /* Transform the 3x8 bits to 4x6 bits, as required by
288 base64. */
289 for (string::const_iterator I = S.begin(); I < S.end(); I += 3)
290 {
291 char Bits[3] = {0,0,0};
292 Bits[0] = I[0];
293 if (I + 1 < S.end())
294 Bits[1] = I[1];
295 if (I + 2 < S.end())
296 Bits[2] = I[2];
297
298 Final += tbl[Bits[0] >> 2];
299 Final += tbl[((Bits[0] & 3) << 4) + (Bits[1] >> 4)];
300
301 if (I + 1 >= S.end())
302 break;
303
304 Final += tbl[((Bits[1] & 0xf) << 2) + (Bits[2] >> 6)];
305
306 if (I + 2 >= S.end())
307 break;
308
309 Final += tbl[Bits[2] & 0x3f];
310 }
311
312 /* Apply the padding elements, this tells how many bytes the remote
313 end should discard */
314 if (S.length() % 3 == 2)
315 Final += '=';
316 if (S.length() % 3 == 1)
317 Final += "==";
318
319 return Final;
320}
321 /*}}}*/
322// stringcmp - Arbitary string compare /*{{{*/
323// ---------------------------------------------------------------------
324/* This safely compares two non-null terminated strings of arbitary
325 length */
326int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
327{
328 for (; A != AEnd && B != BEnd; A++, B++)
329 if (*A != *B)
330 break;
331
332 if (A == AEnd && B == BEnd)
333 return 0;
334 if (A == AEnd)
335 return 1;
336 if (B == BEnd)
337 return -1;
338 if (*A < *B)
339 return -1;
340 return 1;
341}
342 /*}}}*/
343// stringcasecmp - Arbitary case insensitive string compare /*{{{*/
344// ---------------------------------------------------------------------
345/* */
346int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
347{
348 for (; A != AEnd && B != BEnd; A++, B++)
349 if (toupper(*A) != toupper(*B))
350 break;
351
352 if (A == AEnd && B == BEnd)
353 return 0;
354 if (A == AEnd)
355 return 1;
356 if (B == BEnd)
357 return -1;
358 if (toupper(*A) < toupper(*B))
359 return -1;
360 return 1;
361}
362 /*}}}*/