1 /**
2 *  Copyright Mikael H�gdahl - triyana@users.sourceforge.net
3 *
4 *  This source is distributed under the terms of the Q Public License version 1.0,
5 *  created by Trolltech (www.trolltech.com).
6 */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <ctype.h>
12 #include "MHString.h"
13 #include "MHVector.h"
14 #include "MHUtil.h"
15 
16 
17 
18 /**
19 *  Do an sprintf constrcutor
20 *  @param int         - Size
21 *  @param const char* - First string
22 *  @param ...         - Rest of params
23 */
MHString(int size,const char * str,...)24 MHString::MHString(int size, const char* str, ...) {
25     va_list args;
26     char*   buffer = new char[size + 1];
27 
28     va_start (args, str);
29     vsnprintf (buffer, size, str, args);
30     va_end (args);
31 
32     aData = buffer;
33     aLen  = STRLEN (buffer);
34 }
35 
36 
37 
38 /**
39 *  Align the string
40 *  @param bool - true to align right
41 *  @param int  - Width of string
42 *  @param char - Pad string, only one char
43 */
align(bool right,int nWidth,char pad)44 void MHString::align (bool right, int nWidth, char pad) {
45     char*   p = new char[nWidth + 1];
46     int     count = 0;
47 
48     if (aLen >= nWidth) {
49         delete []p;
50         return;
51     }
52     p[0] = pad;
53     p[1] = '\0';
54 
55     while ((nWidth - aLen - strlen(p)) > 0) {
56         count++;
57         p[count]     = pad;
58         p[count + 1] = '\0';
59     }
60     if (right)
61         allocate (p, aData);
62     else
63         allocate (aData, p);
64     delete []p;
65 }
66 
67 
68 
69 /**
70 *  Allocate a string
71 */
allocate(const char * s)72 void MHString::allocate (const char* s) {
73     Clear();
74     aLen = STRLEN(s);
75     aData = new char[aLen + 1];
76     strncpy (aData, s, aLen);
77     aData[aLen] = '\0';
78 }
79 
80 
81 
82 /**
83 *  Allocate a string
84 *  @param int - Number to convert
85 */
allocate(int i)86 void MHString::allocate (int i) {
87     char s [100];
88 
89     Clear ();
90     sprintf (s, "%d", i);
91     aLen = STRLEN(s);
92     aData = new char[aLen + 1];
93     strncpy (aData, s, aLen);
94     aData[aLen] = '\0';
95 }
96 
97 
98 
99 /**
100 *  Allocate a string
101 *  @param double - Number to convert
102 */
allocate(double d)103 void MHString::allocate (double d) {
104     char s[100];
105 
106     Clear ();
107     sprintf (s, "%.*f", 2, d);
108     aLen = STRLEN(s);
109     aData = new char[aLen + 1];
110     strncpy (aData, s, aLen);
111     aData[aLen] = '\0';
112 }
113 
114 
115 
116 /**
117 *  Allocate a string
118 */
allocate(const char * s,const char * s2)119 void MHString::allocate (const char* s, const char* s2) {
120     int   l1 = STRLEN (s);
121     int   l2 = STRLEN (s2);
122     char* c  = new char[l1 + l2 + 1];
123 
124     strncpy (c, s, l1);
125     c[l1] = '\0';
126     strncat (c, s2, l2);
127     c[l1 + l2] = '\0';
128     Clear();
129     aLen  = l1 + l2;
130     aData = c;
131     aData[aLen] = '\0';
132 }
133 
134 
135 
136 /**
137 *  Allocate a string
138 */
allocate(const char * s,int n)139 void MHString::allocate (const char* s, int n) {
140     char  s2[100];
141     sprintf (s2, "%d", n);
142     allocate (s, s2);
143 }
144 
145 
146 
147 /**
148 *  Allocate a string
149 */
allocate(const char * s,double n)150 void MHString::allocate (const char* s, double n) {
151     char  s2[100];
152     sprintf (s2, "%.*f", 2, n);
153     allocate (s, s2);
154 }
155 
156 
157 
158 /**
159 * Convert first letter in each word to uppercase, all other lowercase
160 */
CapitalizeAll()161 void MHString::CapitalizeAll () {
162     ToLower ();
163 
164     char* source = aData;
165     bool space   = true;
166     while (*source) {
167         if (space && *source > ' ' && *source != '\'') {
168             *source = toupper (*source);
169             space = false;
170         }
171         else if (*source <= ' ')
172             space = true;
173 
174         source++;
175     }
176 }
177 
178 
179 
180 /**
181 * Convert first letter in first word to uppercase, all other lowercase
182 */
CapitalizeFirst()183 void MHString::CapitalizeFirst () {
184     ToLower ();
185 }
186 
187 
188 
189 /**
190 *  Empty string
191 */
Clear()192 void MHString::Clear () {
193     delete []aData;
194     aData = 0;
195     aLen  = 0;
196 }
197 
198 
199 
200 /**
201 *  Compare string with another string
202 *  @param char* - String to compare with
203 *  @return int - 0, -1, 1
204 */
Compare(const char * pBuffer)205 int MHString::Compare (const char* pBuffer) {
206     if (aData && pBuffer)
207         return strcmp (aData, pBuffer);
208     return -1;
209 }
210 
211 
212 
213 /**
214 *  Compare string with another string
215 *  @return int - 0, -1, 1
216 */
Compare(const MH * o,int type)217 int MHString::Compare (const MH* o, int type) {
218     if (type == SORT_STRING)
219         return Compare(((MHString*)o)->Get());
220     else if (type == SORT_NUM) {
221         double d1 = ToDouble ();
222         double d2 = ((MHString*)o)->ToDouble ();
223 
224         if (fabs (d1 - d2) < 0.0000001)
225             return 0;
226         else if (d1 < d2)
227             return -1;
228         return 1;
229     }
230     return -1;
231 }
232 
233 
234 
235 /**
236 *  Compare string with another string
237 *  @param char* - String to compare with
238 *  @param MHString::STATUS - EXACT or DONT_CARE
239 *  @return int - 0, -1, 1
240 */
CompareIgnoreCase(const char * pBuffer)241 int MHString::CompareIgnoreCase (const char* pBuffer) {
242     if (aData && pBuffer)
243         return strncasecmp (aData, pBuffer, aLen);
244     else
245         return -1;
246 }
247 
248 
249 
250 /**
251 *  Find string
252 *  @param char* - String to find inside current string
253 *  @param int   - Start in current string
254 *  @return int  - Pos or -1
255 */
find(const char * word,int start,bool compareCase)256 int MHString::find (const char* word, int start, bool compareCase) {
257     if (start < (aLen - 1)) {
258         if (compareCase == false) {
259             MHString s(aData);
260             MHString s2(word);
261             s.ToLower();
262             s2.ToLower();
263             return s.Find(s2, false);
264         }
265         else {
266             const char* s = strstr (aData + start, word);
267             return s - aData;
268         }
269     }
270     return -1;
271 }
272 
273 
274 
275 /**
276 *  Get left part of string
277 *  @param int       - Number of char
278 *  @return MHString - New string with left part of original string
279 */
Left(int count)280 MHString MHString::Left (int count) {
281     MHString s;
282     if (count > 0) {
283         if (count > aLen) count = aLen;
284         char* buffer = new char[count + 1];
285         strncpy (buffer, aData, count);
286         buffer[count] = '\0';
287         s.Clear();
288         s.aData = buffer;
289         s.aLen  = count;
290     }
291     return s;
292 }
293 
294 
295 
296 /**
297 *  Get middle part of string
298 *  @param int       - Pos of first char
299 *  @param int       - Number of char
300 *  @return MHString - New string with left part of original string
301 */
Mid(int start,int count)302 MHString MHString::Mid (int start, int count) {
303     MHString s;
304     if (start > 0 && count > 0) {
305         if ((start + count) > aLen) return s;
306         char* buffer = new char[count + 1];
307         strncpy (buffer, aData + start, count);
308         buffer[count] = '\0';
309         s.Clear();
310         s.aData = buffer;
311         s.aLen  = count;
312     }
313     return s;
314 }
315 
316 
317 
318 /**
319 *  Remove char from head
320 *  @param char - Character to remove
321 */
Remove(char ch)322 void MHString::Remove (char ch) {
323     if (aLen > 0) {
324         char* tmp    = new char[aLen + 1];
325         char* source = aData;
326         char* dest   = tmp;
327 
328         *tmp = *aData;
329         while (*source) {
330             if (*source != ch) {
331                 *dest = *source;
332                 dest++;
333             }
334             source++;
335         }
336         *dest = '\0';
337         aLen = STRLEN(tmp);
338         delete aData;
339         aData = tmp;
340     }
341 }
342 
343 
344 
345 /**
346 *  Remove char from head
347 *  @param char - Character to remove
348 */
RemoveHead(char ch)349 void MHString::RemoveHead (char ch) {
350     char* source = aData;
351 
352     if (source && *source) {
353         if (*source == ch) {
354             while (*source == ch)
355                 source++;
356             memmove (aData, source, strlen(source) + 1);
357         }
358 
359         aLen = STRLEN(aData);
360     }
361 }
362 
363 
364 
365 /**
366 *  Remove char from tail
367 *  @param char - Character to remove
368 */
RemoveTail(char ch)369 void MHString::RemoveTail (char ch) {
370     char* source = aData + aLen - 1;
371 
372     if (source && *source) {
373         if (*source == ch) {
374             while (*source == ch) {
375                 *source = '\0';
376                 source--;
377             }
378         }
379         aLen = STRLEN(aData);
380     }
381 }
382 
383 
384 
385 /**
386 *  Get right part of string
387 *  @param int - Number of char
388 *  @return MHString - New string with left part of original string
389 */
Right(int count)390 MHString MHString::Right (int count) {
391     MHString s;
392     if (count > 0) {
393         if ((aLen - count) < 0) count = aLen;
394         char* buffer = new char[count + 1];
395         strncpy (buffer, aData + aLen - count, count);
396         buffer[count] = '\0';
397         s.Clear();
398         s.aData = buffer;
399         s.aLen  = count;
400     }
401     return s;
402 }
403 
404 
405 
406 /**
407 *  Save an array of strings
408 *  @param const char* - Filename
409 *  @param MHVector*   - Vector with MHString objects
410 *  @param bool        - true to add a new line, default false
411 *  @param bool        - true to add row counter, default false
412 */
Save(const char * fileName,MHVector * v,bool nl,bool row)413 void MHString::Save (const char* fileName, MHVector* v, bool nl, bool row) {
414     FILE* file = fopen (fileName, "w");
415 
416     if (file) {
417         for (int f = 0; f < v->Size(); f++) {
418             MHString* s = (MHString*) (*v)[f];
419             char      b[20];
420             snprintf (b, 10, "%05d    ", f + 1);
421             if (row)
422                 fwrite (b, sizeof(char), 9, file);
423             fwrite (s->Get(), sizeof(char), s->Size(), file);
424             if (nl) fwrite ("\n", sizeof(char), 1, file);
425         }
426     }
427     fclose (file);
428 }
429 
430 
431 
432 /**
433 *  Make string smaller
434 *  @param int - Number of char
435 */
Shrink(int count)436 void MHString::Shrink (int count) {
437     if (count > 0 && count < aLen) {
438         char* buffer = new char[count + 1];
439         strncpy (buffer, aData, count);
440         buffer[count] = '\0';
441         Clear();
442         aData = buffer;
443         aLen  = count;
444     }
445 }
446 
447 
448 
449 /**
450 *  Split string into many strings
451 *  @param char c    - Character to split on
452 *  @param MHVector* - The result vector
453 *  @return int      - Number of strings
454 */
Split(char c,MHVector * ve)455 int MHString::Split (char c, MHVector* ve) {
456     int         nIndex = 0;
457     int         nTempPos = 0;
458     char        Temp [10000];
459 
460     Temp[0] = '\0';
461 
462     while (aData[nIndex] != 0 && nIndex < aLen) {
463         if (aData[nIndex] == c || nTempPos == 9999) {
464             Temp [nTempPos] = '\0';
465             ve->Push (new MHString(Temp));
466             nTempPos = 0;
467             Temp [0] = '\0';
468         }
469         else
470             Temp[nTempPos++] = aData[nIndex];
471         nIndex++;
472     }
473 
474     //  Check if something is left in buffer
475     if (nTempPos > 0) {
476         Temp [nTempPos] = '\0';
477         ve->Push (new MHString(Temp));
478     }
479 
480     return ve->Size();
481 }
482 
483 
484 
485 /**
486 *  Split string into many strings
487 *  @param MHVector* - The result vector
488 *  @param int       - Positions in vector even pairs of start and stop, end with -1
489 *  @return int      - Number of strings
490 */
Split(MHVector * ve,int nFirstPos,...)491 int MHString::Split (MHVector* ve, int nFirstPos, ...) {
492     int     nIndex = 0;
493     int     count;
494     int     pos[1000];
495     va_list ap;
496 
497     va_start (ap, nFirstPos);
498     pos [nIndex++] = nFirstPos;
499     while (nFirstPos != -1) {
500         nFirstPos = va_arg (ap, int);
501         pos[nIndex++] = nFirstPos;
502         if (nIndex == 1000) return 0;
503     }
504     va_end (ap);
505 
506     for (int i = 0; i < (nIndex - 1) && pos[i] != -1 && pos[i + 1] != -1; i += 2) {
507         int  start = pos[i];
508         int  stop  = pos[i+1];
509         char buffer[1000];
510 
511         if (start < 0 && stop >= aLen) return ve->Size();
512         count = 0;
513         for (int f = start; f <= stop && count < 999; f++)
514             buffer[count++] = aData[f];
515         buffer[count] = '\0';
516         ve->Push (new MHString(buffer));
517         nIndex++;
518     }
519     return ve->Size();
520 }
521 
522 
523 
524 /**
525 *  Do an sprintf operation of this string
526 *  @param int         - Length of string
527 *  @param const char* - First string
528 *  @param ...         - Rest of params
529 */
Sprintf(int len,const char * str,...)530 void MHString::Sprintf(int len, const char* str, ...) {
531     char*   buffer = new char[len + 1];
532 
533     va_list argp;
534     va_start (argp, str);
535     vsnprintf (buffer, len, str, argp);
536     va_end (argp);
537 
538     Clear();
539     aData = buffer;
540     aLen  = STRLEN(buffer);
541 }
542 
543 
544 
545 /**
546 *  Remove all whitespaces first and last in the string
547 */
Strip()548 void MHString::Strip () {
549     if (aLen < 1) return;
550     char* source1 = aData;
551     char* source2 = aData + aLen - 1;
552 
553     while (source1 && *source1 != '\0' && *source1 < 33)
554         *source1++ = '\0';
555 
556     while (source2 && *source2 != '\0' && *source2 < 33 && source2 > aData)
557         *source2-- = '\0';
558 
559     int len = source2 - source1 + 1;
560     if (len != aLen) {
561         strncpy (aData, source1, len);
562         aData[len] = '\0';
563         aLen = len;
564     }
565 }
566 
567 
568 
569 /**
570 *  Convert string to lower case
571 */
ToLower()572 void MHString::ToLower () {
573     char* source = aData;
574     while (*source) {
575         *source = tolower (*source);
576         source++;
577     }
578 }
579 
580 
581 
582 /**
583 *  Conver string upper case
584 */
ToUpper()585 void MHString::ToUpper () {
586     char* source = aData;
587     while (*source) {
588         *source = toupper (*source);
589         source++;
590     }
591 }
592