]> git.saurik.com Git - apt.git/blame - apt-pkg/contrib/strutl.cc
Sync
[apt.git] / apt-pkg / contrib / strutl.cc
CommitLineData
6c139d6e
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
08e8f724 3// $Id: strutl.cc,v 1.4 1998/09/22 05:30:28 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
08e8f724 80 and striped out as well. This is for URI/URL parsing. */
6c139d6e
AL
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 /*}}}*/
08e8f724
AL
131// ParseCWord - Parses a string like a C "" expression /*{{{*/
132// ---------------------------------------------------------------------
133/* This expects a series of space seperated strings enclosed in ""'s.
134 It concatenates the ""'s into a single string. */
135bool ParseCWord(const char *String,string &Res)
136{
137 // Skip leading whitespace
138 const char *C = String;
139 for (;*C != 0 && *C == ' '; C++);
140 if (*C == 0)
141 return false;
142
143 char Buffer[1024];
144 char *Buf = Buffer;
145 if (strlen(String) >= sizeof(Buffer))
146 return false;
147
148 for (; *C != 0; C++)
149 {
150 if (*C == '"')
151 {
152 for (C++; *C != 0 && *C != '"'; C++)
153 *Buf++ = *C;
154
155 if (*C == 0)
156 return false;
157
158 continue;
159 }
160
161 if (C != String && isspace(*C) != 0 && isspace(C[-1]) != 0)
162 continue;
163 if (isspace(*C) == 0)
164 return false;
165 *Buf++ = ' ';
166 }
167 *Buf = 0;
168 Res = Buffer;
169 return true;
170}
171 /*}}}*/
6c139d6e
AL
172// QuoteString - Convert a string into quoted from /*{{{*/
173// ---------------------------------------------------------------------
174/* */
175string QuoteString(string Str,const char *Bad)
176{
177 string Res;
178 for (string::iterator I = Str.begin(); I != Str.end(); I++)
179 {
180 if (strchr(Bad,*I) != 0 || isprint(*I) == 0 ||
181 *I <= 0x20 || *I >= 0x7F)
182 {
183 char Buf[10];
184 sprintf(Buf,"%%%02x",(int)*I);
185 Res += Buf;
186 }
187 else
188 Res += *I;
189 }
190 return Res;
191}
192 /*}}}*/
193// SizeToStr - Convert a long into a human readable size /*{{{*/
194// ---------------------------------------------------------------------
195/* A max of 4 digits are shown before conversion to the next highest unit. The
196 max length of the string will be 5 chars unless the size is > 10
197 YottaBytes (E24) */
198string SizeToStr(double Size)
199{
200 char S[300];
201 double ASize;
202 if (Size >= 0)
203 ASize = Size;
204 else
205 ASize = -1*Size;
206
207 /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes,
208 ExaBytes, ZettaBytes, YottaBytes */
209 char Ext[] = {'b','k','M','G','T','P','E','Z','Y'};
210 int I = 0;
211 while (I <= 8)
212 {
213 if (ASize < 100 && I != 0)
214 {
215 sprintf(S,"%.1f%c",ASize,Ext[I]);
216 break;
217 }
218
219 if (ASize < 10000)
220 {
221 sprintf(S,"%.0f%c",ASize,Ext[I]);
222 break;
223 }
224 ASize /= 1000.0;
225 I++;
226 }
227
228 return S;
229}
230 /*}}}*/
231// TimeToStr - Convert the time into a string /*{{{*/
232// ---------------------------------------------------------------------
233/* Converts a number of seconds to a hms format */
234string TimeToStr(unsigned long Sec)
235{
236 char S[300];
237
238 while (1)
239 {
240 if (Sec > 60*60*24)
241 {
242 sprintf(S,"%lid %lih%lim%lis",Sec/60/60/24,(Sec/60/60) % 24,(Sec/60) % 60,Sec % 60);
243 break;
244 }
245
246 if (Sec > 60*60)
247 {
248 sprintf(S,"%lih%lim%lis",Sec/60/60,(Sec/60) % 60,Sec % 60);
249 break;
250 }
251
252 if (Sec > 60)
253 {
254 sprintf(S,"%lim%lis",Sec/60,Sec % 60);
255 break;
256 }
257
258 sprintf(S,"%lis",Sec);
259 break;
260 }
261
262 return S;
263}
264 /*}}}*/
265// SubstVar - Substitute a string for another string /*{{{*/
266// ---------------------------------------------------------------------
267/* This replaces all occurances of Subst with Contents in Str. */
268string SubstVar(string Str,string Subst,string Contents)
269{
8efa2a3b 270 string::size_type Pos = 0;
6c139d6e
AL
271 string::size_type OldPos = 0;
272 string Temp;
273
274 while (OldPos < Str.length() &&
275 (Pos = Str.find(Subst,OldPos)) != string::npos)
276 {
277 Temp += string(Str,OldPos,Pos) + Contents;
278 OldPos = Pos + Subst.length();
279 }
280
281 if (OldPos == 0)
282 return Str;
283
284 return Temp + string(Str,OldPos);
285}
286 /*}}}*/
ad00ae81
AL
287// URItoFileName - Convert the uri into a unique file name /*{{{*/
288// ---------------------------------------------------------------------
289/* This converts a URI into a safe filename. It quotes all unsafe characters
290 and converts / to _ and removes the scheme identifier. The resulting
291 file name should be unique and never occur again for a different file */
292string URItoFileName(string URI)
293{
294 string::const_iterator I = URI.begin() + URI.find(':') + 1;
295 for (; I < URI.end() && *I == '/'; I++);
296
297 // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
298 URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
299 string::iterator J = URI.begin();
300 for (; J != URI.end(); J++)
301 if (*J == '/')
302 *J = '_';
303 return URI;
304}
305 /*}}}*/
6c139d6e
AL
306// Base64Encode - Base64 Encoding routine for short strings /*{{{*/
307// ---------------------------------------------------------------------
308/* This routine performs a base64 transformation on a string. It was ripped
309 from wget and then patched and bug fixed.
310
311 This spec can be found in rfc2045 */
312string Base64Encode(string S)
313{
314 // Conversion table.
315 static char tbl[64] = {'A','B','C','D','E','F','G','H',
316 'I','J','K','L','M','N','O','P',
317 'Q','R','S','T','U','V','W','X',
318 'Y','Z','a','b','c','d','e','f',
319 'g','h','i','j','k','l','m','n',
320 'o','p','q','r','s','t','u','v',
321 'w','x','y','z','0','1','2','3',
322 '4','5','6','7','8','9','+','/'};
323
324 // Pre-allocate some space
325 string Final;
326 Final.reserve((4*S.length() + 2)/3 + 2);
327
328 /* Transform the 3x8 bits to 4x6 bits, as required by
329 base64. */
330 for (string::const_iterator I = S.begin(); I < S.end(); I += 3)
331 {
332 char Bits[3] = {0,0,0};
333 Bits[0] = I[0];
334 if (I + 1 < S.end())
335 Bits[1] = I[1];
336 if (I + 2 < S.end())
337 Bits[2] = I[2];
338
339 Final += tbl[Bits[0] >> 2];
340 Final += tbl[((Bits[0] & 3) << 4) + (Bits[1] >> 4)];
341
342 if (I + 1 >= S.end())
343 break;
344
345 Final += tbl[((Bits[1] & 0xf) << 2) + (Bits[2] >> 6)];
346
347 if (I + 2 >= S.end())
348 break;
349
350 Final += tbl[Bits[2] & 0x3f];
351 }
352
353 /* Apply the padding elements, this tells how many bytes the remote
354 end should discard */
355 if (S.length() % 3 == 2)
356 Final += '=';
357 if (S.length() % 3 == 1)
358 Final += "==";
359
360 return Final;
361}
362 /*}}}*/
363// stringcmp - Arbitary string compare /*{{{*/
364// ---------------------------------------------------------------------
365/* This safely compares two non-null terminated strings of arbitary
366 length */
367int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
368{
369 for (; A != AEnd && B != BEnd; A++, B++)
370 if (*A != *B)
371 break;
372
373 if (A == AEnd && B == BEnd)
374 return 0;
375 if (A == AEnd)
376 return 1;
377 if (B == BEnd)
378 return -1;
379 if (*A < *B)
380 return -1;
381 return 1;
382}
383 /*}}}*/
384// stringcasecmp - Arbitary case insensitive string compare /*{{{*/
385// ---------------------------------------------------------------------
386/* */
387int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
388{
389 for (; A != AEnd && B != BEnd; A++, B++)
390 if (toupper(*A) != toupper(*B))
391 break;
392
393 if (A == AEnd && B == BEnd)
394 return 0;
395 if (A == AEnd)
396 return 1;
397 if (B == BEnd)
398 return -1;
399 if (toupper(*A) < toupper(*B))
400 return -1;
401 return 1;
402}
403 /*}}}*/