]>
git.saurik.com Git - apt.git/blob - apt-pkg/contrib/strutl.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: strutl.cc,v 1.5 1998/10/20 02:39:30 jgg Exp $
4 /* ######################################################################
6 String Util - Some usefull string functions.
8 strstrip - Remove whitespace from the front and end of a line.
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>
13 ##################################################################### */
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 */
26 char *_strstrip(char *String
)
28 for (;*String
!= 0 && (*String
== ' ' || *String
== '\t'); String
++);
33 char *End
= String
+ strlen(String
) - 1;
34 for (;End
!= String
- 1 && (*End
== ' ' || *End
== '\t' || *End
== '\n' ||
35 *End
== '\r'); End
--);
41 // strtabexpand - Converts tabs into 8 spaces /*{{{*/
42 // ---------------------------------------------------------------------
44 char *_strtabexpand(char *String
,size_t Len
)
46 for (char *I
= String
; I
!= I
+ Len
&& *I
!= 0; I
++)
50 if (I
+ 8 > String
+ Len
)
56 /* Assume the start of the string is 0 and find the next 8 char
62 Len
= 8 - ((String
- I
) % 8);
70 memmove(I
+ Len
,I
+ 1,strlen(I
) + 1);
71 for (char *J
= I
; J
+ Len
!= I
; *I
= ' ', I
++);
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. This is for URI/URL parsing. */
81 bool ParseQuoteWord(const char *&String
,string
&Res
)
83 // Skip leading whitespace
84 const char *C
= String
;
85 for (;*C
!= 0 && *C
== ' '; C
++);
89 // Jump to the next word
90 for (;*C
!= 0 && *C
!= ' '; C
++)
94 for (C
++;*C
!= 0 && *C
!= '"'; C
++);
100 // Now de-quote characters
103 const char *Start
= String
;
105 for (I
= Buffer
; I
< Buffer
+ sizeof(Buffer
) && Start
!= C
; I
++)
107 if (*Start
== '%' && Start
+ 2 < C
)
112 *I
= (char)strtol(Tmp
,0,16);
125 // Skip ending white space
126 for (;*C
!= 0 && *C
== ' '; C
++);
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. */
135 bool ParseCWord(const char *String
,string
&Res
)
137 // Skip leading whitespace
138 const char *C
= String
;
139 for (;*C
!= 0 && *C
== ' '; C
++);
145 if (strlen(String
) >= sizeof(Buffer
))
152 for (C
++; *C
!= 0 && *C
!= '"'; C
++)
161 if (C
!= String
&& isspace(*C
) != 0 && isspace(C
[-1]) != 0)
163 if (isspace(*C
) == 0)
172 // QuoteString - Convert a string into quoted from /*{{{*/
173 // ---------------------------------------------------------------------
175 string
QuoteString(string Str
,const char *Bad
)
178 for (string::iterator I
= Str
.begin(); I
!= Str
.end(); I
++)
180 if (strchr(Bad
,*I
) != 0 || isprint(*I
) == 0 ||
181 *I
<= 0x20 || *I
>= 0x7F)
184 sprintf(Buf
,"%%%02x",(int)*I
);
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
198 string
SizeToStr(double Size
)
207 /* bytes, KiloBytes, MegaBytes, GigaBytes, TeraBytes, PetaBytes,
208 ExaBytes, ZettaBytes, YottaBytes */
209 char Ext
[] = {'b','k','M','G','T','P','E','Z','Y'};
213 if (ASize
< 100 && I
!= 0)
215 sprintf(S
,"%.1f%c",ASize
,Ext
[I
]);
221 sprintf(S
,"%.0f%c",ASize
,Ext
[I
]);
231 // TimeToStr - Convert the time into a string /*{{{*/
232 // ---------------------------------------------------------------------
233 /* Converts a number of seconds to a hms format */
234 string
TimeToStr(unsigned long Sec
)
242 sprintf(S
,"%lid %lih%lim%lis",Sec
/60/60/24,(Sec
/60/60) % 24,(Sec
/60) % 60,Sec
% 60);
248 sprintf(S
,"%lih%lim%lis",Sec
/60/60,(Sec
/60) % 60,Sec
% 60);
254 sprintf(S
,"%lim%lis",Sec
/60,Sec
% 60);
258 sprintf(S
,"%lis",Sec
);
265 // SubstVar - Substitute a string for another string /*{{{*/
266 // ---------------------------------------------------------------------
267 /* This replaces all occurances of Subst with Contents in Str. */
268 string
SubstVar(string Str
,string Subst
,string Contents
)
270 string::size_type Pos
= 0;
271 string::size_type OldPos
= 0;
274 while (OldPos
< Str
.length() &&
275 (Pos
= Str
.find(Subst
,OldPos
)) != string::npos
)
277 Temp
+= string(Str
,OldPos
,Pos
) + Contents
;
278 OldPos
= Pos
+ Subst
.length();
284 return Temp
+ string(Str
,OldPos
);
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 */
292 string
URItoFileName(string URI
)
294 string::const_iterator I
= URI
.begin() + URI
.find(':') + 1;
295 for (; I
< URI
.end() && *I
== '/'; I
++);
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
++)
306 // URIAccess - Return the access method for the URI /*{{{*/
307 // ---------------------------------------------------------------------
309 string
URIAccess(string URI
)
311 string::size_type Pos
= URI
.find(':');
312 if (Pos
== string::npos
)
314 return string(URI
,0,Pos
);
317 // Base64Encode - Base64 Encoding routine for short strings /*{{{*/
318 // ---------------------------------------------------------------------
319 /* This routine performs a base64 transformation on a string. It was ripped
320 from wget and then patched and bug fixed.
322 This spec can be found in rfc2045 */
323 string
Base64Encode(string S
)
326 static char tbl
[64] = {'A','B','C','D','E','F','G','H',
327 'I','J','K','L','M','N','O','P',
328 'Q','R','S','T','U','V','W','X',
329 'Y','Z','a','b','c','d','e','f',
330 'g','h','i','j','k','l','m','n',
331 'o','p','q','r','s','t','u','v',
332 'w','x','y','z','0','1','2','3',
333 '4','5','6','7','8','9','+','/'};
335 // Pre-allocate some space
337 Final
.reserve((4*S
.length() + 2)/3 + 2);
339 /* Transform the 3x8 bits to 4x6 bits, as required by
341 for (string::const_iterator I
= S
.begin(); I
< S
.end(); I
+= 3)
343 char Bits
[3] = {0,0,0};
350 Final
+= tbl
[Bits
[0] >> 2];
351 Final
+= tbl
[((Bits
[0] & 3) << 4) + (Bits
[1] >> 4)];
353 if (I
+ 1 >= S
.end())
356 Final
+= tbl
[((Bits
[1] & 0xf) << 2) + (Bits
[2] >> 6)];
358 if (I
+ 2 >= S
.end())
361 Final
+= tbl
[Bits
[2] & 0x3f];
364 /* Apply the padding elements, this tells how many bytes the remote
365 end should discard */
366 if (S
.length() % 3 == 2)
368 if (S
.length() % 3 == 1)
374 // stringcmp - Arbitary string compare /*{{{*/
375 // ---------------------------------------------------------------------
376 /* This safely compares two non-null terminated strings of arbitary
378 int stringcmp(const char *A
,const char *AEnd
,const char *B
,const char *BEnd
)
380 for (; A
!= AEnd
&& B
!= BEnd
; A
++, B
++)
384 if (A
== AEnd
&& B
== BEnd
)
395 // stringcasecmp - Arbitary case insensitive string compare /*{{{*/
396 // ---------------------------------------------------------------------
398 int stringcasecmp(const char *A
,const char *AEnd
,const char *B
,const char *BEnd
)
400 for (; A
!= AEnd
&& B
!= BEnd
; A
++, B
++)
401 if (toupper(*A
) != toupper(*B
))
404 if (A
== AEnd
&& B
== BEnd
)
410 if (toupper(*A
) < toupper(*B
))
415 // LookupTag - Lookup the value of a tag in a taged string /*{{{*/
416 // ---------------------------------------------------------------------
417 /* The format is like those used in package files and the method
418 communication system */
419 string
LookupTag(string Message
,const char *Tag
,const char *Default
)
421 // Look for a matching tag.
422 int Length
= strlen(Tag
);
423 for (string::iterator I
= Message
.begin(); I
+ Length
< Message
.end(); I
++)
426 if (I
[Length
] == ':' && stringcasecmp(I
,I
+Length
,Tag
) == 0)
428 // Find the end of line and strip the leading/trailing spaces
431 for (; isspace(*I
) != 0 && I
< Message
.end(); I
++);
432 for (J
= I
; *J
!= '\n' && J
< Message
.end(); J
++);
433 for (; J
> I
&& isspace(J
[-1]) != 0; J
--);
435 return string(I
,J
-I
);
438 for (; *I
!= '\n' && I
< Message
.end(); I
++);
441 // Failed to find a match
447 // StringToBool - Converts a string into a boolean /*{{{*/
448 // ---------------------------------------------------------------------
449 /* This inspects the string to see if it is true or if it is false and
450 then returns the result. Several varients on true/false are checked. */
451 int StringToBool(string Text
,int Default
= -1)
454 int Res
= strtol(Text
.c_str(),&End
,0);
455 if (End
!= Text
.c_str() && Res
>= 0 && Res
<= 1)
458 // Check for positives
459 if (strcasecmp(Text
.c_str(),"no") == 0 ||
460 strcasecmp(Text
.c_str(),"false") == 0 ||
461 strcasecmp(Text
.c_str(),"without") == 0 ||
462 strcasecmp(Text
.c_str(),"disable") == 0)
465 // Check for negatives
466 if (strcasecmp(Text
.c_str(),"yes") == 0 ||
467 strcasecmp(Text
.c_str(),"true") == 0 ||
468 strcasecmp(Text
.c_str(),"with") == 0 ||
469 strcasecmp(Text
.c_str(),"enable") == 0)