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