1 /* @source ajstr ***************************************************************
2 **
3 ** AJAX string functions
4 **
5 ** AjPStr objects are reference counted strings
6 ** Any change will need a new string object if the use count
7 ** is greater than 1, so the original AjPStr is provided as a pointer
8 ** so that it can be reallocated in any routine where string modification
9 ** may be needed.
10 **
11 ** In many cases the text is always a copy, even of a constant original, so
12 ** that it can be simply freed.
13 **
14 ** @author Copyright (C) 1998 Peter Rice
15 ** @version $Revision: 1.205 $
16 ** @modified 1998-2011 Peter Rice
17 ** @modified $Date: 2013/06/30 12:03:51 $ by $Author: rice $
18 ** @@
19 **
20 ** This library is free software; you can redistribute it and/or
21 ** modify it under the terms of the GNU Lesser General Public
22 ** License as published by the Free Software Foundation; either
23 ** version 2.1 of the License, or (at your option) any later version.
24 **
25 ** This library is distributed in the hope that it will be useful,
26 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
27 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 ** Lesser General Public License for more details.
29 **
30 ** You should have received a copy of the GNU Lesser General Public
31 ** License along with this library; if not, write to the Free Software
32 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33 ** MA 02110-1301, USA.
34 **
35 ******************************************************************************/
36
37
38
39
40 /* ==================================================================== */
41 /* ========================== include files =========================== */
42 /* ==================================================================== */
43
44 #include <math.h>
45 #include <stdarg.h>
46 #include <errno.h>
47 #include <ctype.h>
48 #include <limits.h>
49 #include <float.h>
50 #include <string.h>
51 #include <sys/types.h>
52
53 #include "ajstr.h"
54 #include "ajfmt.h"
55 #include "ajmem.h"
56 #include "ajmess.h"
57 #include "ajsys.h"
58 #include "ajmath.h"
59 #include "ajsort.h"
60
61 #ifndef HAVE_MEMMOVE
62
63
64
65
66 /* @header memmove ************************************************************
67 **
68 ******************************************************************************/
69
memmove(void * dst,const void * src,size_t len)70 static void* memmove(void *dst, const void* src, size_t len)
71 {
72 return (void *)bcopy(src, dst, len);
73 }
74 #endif
75
76
77
78
79 /* ==================================================================== */
80 /* ========================== private data ============================ */
81 /* ==================================================================== */
82
83
84
85
86 #define STRSIZE 32
87 #define LONGSTR 512
88 #define NULL_USE 1
89 char charNULL[1] = "";
90
91 AjOStr strONULL = { 1,0,charNULL,NULL_USE,0}; /* use set to avoid changes */
92 AjPStr strPNULL = &strONULL;
93
94
95 static char* strParseCp = NULL;
96
97
98 /* ==================================================================== */
99 /* ======================== private functions ========================= */
100 /* ==================================================================== */
101
102 static AjPStr strNew(size_t size);
103 static AjPStr strClone(AjPStr* Pstr);
104 static void strCloneL(AjPStr* pthis, size_t size);
105
106 #ifdef AJ_SAVESTATS
107 static ajlong strAlloc = 0;
108 static ajlong strExtra = 0;
109 static ajlong strFree = 0;
110 static ajlong strFreeCount = 0;
111 static ajlong strCount = 0;
112 static ajlong strTotal = 0;
113 #endif
114
115
116
117
118 /* @filesection ajstr ********************************************************
119 **
120 ** @nam1rule aj Function belongs to the AJAX library.
121 **
122 ** @suffix Len Length
123 ** @suffix C C character string
124 ** @suffix S string object
125 ** @suffix K single character
126 */
127
128
129
130
131 /* @datasection [char*] C character string ***********************************
132 **
133 ** Function is for manipulating C-type (char*) strings and
134 ** takes at least one char* argument.
135 **
136 ** @nam2rule Char
137 */
138
139
140
141
142 /* @section constructors ******************************************************
143 **
144 ** Functions for constructing C-type (char*) strings,
145 ** possibly with a starting string.
146 **
147 ** @fdata [char*]
148 ** @fnote Same argrule as "String constructor functions"
149 **
150 ** @nam3rule New Construct a new string.
151 ** @nam4rule NewRes Minimum reserved size.
152 ** @nam3rule Null Return an internal empty string
153 **
154 ** @argrule C txt [const char*] C character string
155 ** @argrule S str [const AjPStr] Text string
156 ** @argrule NewRes size [size_t] Reserved size
157 ** @argrule Len len [size_t] Length of string
158 **
159 ** @valrule * [char*] New C-style string
160 ** @fcategory new
161 **
162 ******************************************************************************/
163
164
165
166
167 /* @func ajCharNewC ***********************************************************
168 **
169 ** A text string constructor which allocates memory for a string
170 ** and initialises it with the text string provided.
171 **
172 ** @param [r] txt [const char*] Initial text, possibly shorter than the
173 ** space allocated.
174 ** @return [char*] A new text string.
175 ** @ure The text provided must fit in the specified length
176 **
177 ** @release 1.0.0
178 ** @@
179 ******************************************************************************/
180
ajCharNewC(const char * txt)181 char* ajCharNewC(const char* txt)
182 {
183 char* cp;
184 size_t len;
185
186 if(txt)
187 {
188 len = strlen(txt);
189 cp = (char*) AJALLOC0(len+1);
190 memmove(cp, txt, len+1);
191 }
192 else
193 {
194 cp = (char*) AJALLOC0(1);
195 }
196
197 return cp;
198 }
199
200
201
202
203 /* @func ajCharNewS ***********************************************************
204 **
205 ** A text string constructor which allocates memory for a string
206 ** and initialises it with the string provided.
207 **
208 ** @param [r] str [const AjPStr] String object as initial value and size
209 ** for the text.
210 ** @return [char*] A new text string.
211 ** @ure The text provided must fit in the specified length
212 **
213 ** @release 4.0.0
214 ** @@
215 ******************************************************************************/
216
ajCharNewS(const AjPStr str)217 char* ajCharNewS(const AjPStr str)
218 {
219 static char* cp;
220
221 cp = (char*) AJALLOC0(str->Len+1);
222 memmove(cp, str->Ptr, str->Len+1);
223
224 return cp;
225 }
226
227
228
229
230 /* @func ajCharNewRes *********************************************************
231 **
232 ** A text string constructor which allocates memory for a string of the
233 ** specified length and initialises the contents as an empty string.
234 **
235 ** @param [r] size [size_t] Length of the Cstring, excluding the trailing NULL.
236 ** @return [char*] A new text string with no contents.
237 **
238 ** @release 4.0.0
239 ** @@
240 ******************************************************************************/
241
ajCharNewRes(size_t size)242 char* ajCharNewRes(size_t size)
243 {
244 static char* cp;
245
246 cp = (char*) AJALLOC0(size+1);
247 cp[0] = '\0';
248
249 return cp;
250 }
251
252
253
254
255 /* @func ajCharNewResC ********************************************************
256 **
257 ** A text string constructor which allocates memory for a string of the
258 ** specified length and initialises it with the text string provided.
259 **
260 ** @param [r] txt [const char*] String object as initial value and size
261 ** for the text.
262 ** @param [r] size [size_t] Maximum string length, as returned by strlen
263 ** @return [char*] A new text string.
264 ** @ure The text provided must fit in the specified length
265 **
266 ** @release 4.0.0
267 ** @@
268 ******************************************************************************/
269
ajCharNewResC(const char * txt,size_t size)270 char* ajCharNewResC(const char* txt, size_t size)
271 {
272 static char* cp;
273 size_t isize;
274 size_t ilen;
275
276 isize = size;
277
278 if(txt)
279 {
280 ilen = strlen(txt);
281
282 if(ilen >= isize)
283 isize = ilen + 1;
284
285 cp = (char*) AJALLOC0(isize);
286 memmove(cp, txt, ilen+1);
287 }
288 else
289 {
290 cp = (char*) AJALLOC0(isize);
291 }
292
293 return cp;
294 }
295
296
297
298
299 /* @func ajCharNewResS ********************************************************
300 **
301 ** A text string constructor which allocates memory for a string of the
302 ** specified length and initialises it with the string provided.
303 **
304 ** @param [r] str [const AjPStr] String object as initial value and size
305 ** for the text.
306 ** @param [r] size [size_t] Maximum string length, as returned by strlen
307 ** @return [char*] A new text string.
308 ** @ure The text provided must fit in the specified length
309 **
310 ** @release 4.0.0
311 ** @@
312 ******************************************************************************/
313
ajCharNewResS(const AjPStr str,size_t size)314 char* ajCharNewResS(const AjPStr str, size_t size)
315 {
316 static char* cp;
317 size_t isize;
318
319 isize = size;
320 if(str->Len >= isize)
321 isize = str->Len + 1;
322
323 cp = (char*) AJALLOC0(isize);
324 memmove(cp, str->Ptr, str->Len+1);
325
326 return cp;
327 }
328
329
330
331
332 /* @func ajCharNewResLenC *****************************************************
333 **
334 ** A text string constructor which allocates memory for a string of the
335 ** specified length and initialises it with the text string provided.
336 **
337 ** @param [r] txt [const char*] String object as initial value and size
338 ** for the text.
339 ** @param [r] size [size_t] Maximum string length, as returned by strlen
340 ** @param [r] len [size_t] Length of txt to save calculation time.
341 ** @return [char*] A new text string.
342 ** @ure The text provided must fit in the specified length
343 **
344 ** @release 4.0.0
345 ** @@
346 ******************************************************************************/
347
ajCharNewResLenC(const char * txt,size_t size,size_t len)348 char* ajCharNewResLenC(const char* txt, size_t size, size_t len)
349 {
350 static char* cp;
351 size_t isize;
352
353 isize = size;
354
355 if(len >= isize)
356 isize = len + 1;
357
358 cp = (char*) AJALLOC0(isize);
359
360 if(len)
361 memmove(cp, txt, len);
362
363 return cp;
364 }
365
366
367
368
369 /* @func ajCharNull ***********************************************************
370 **
371 ** Returns a pointer to an empty string
372 **
373 ** @return [char*] Empty string
374 **
375 ** @release 6.0.0
376 ******************************************************************************/
377
ajCharNull(void)378 char* ajCharNull (void)
379 {
380 return charNULL;
381 }
382
383
384
385
386 /* @section destructors *******************************************************
387 **
388 ** Functions for destruction of C-type (char*) strings.
389 **
390 ** @fdata [char*]
391 ** @fnote None.
392 ** @nam3rule Del Destroy (free) an existing string.
393 ** @argrule Del Ptxt [char**] Pointer to character string to be deleted
394 ** @valrule * [void]
395 ** @fcategory delete
396 ******************************************************************************/
397
398
399
400
401 /* @func ajCharDel ************************************************************
402 **
403 ** A text string destructor to free memory for a text string.
404 **
405 ** @param [d] Ptxt [char**] Text string to be deallocated.
406 ** @return [void]
407 ** @ure The string is freed using free in the C RTL, so it
408 ** must have been allocated by malloc in the C RTL
409 **
410 ** @release 4.0.0
411 ** @@
412 ******************************************************************************/
413
ajCharDel(char ** Ptxt)414 void ajCharDel(char** Ptxt)
415 {
416 AJFREE(*Ptxt);
417
418 return;
419 }
420
421
422
423
424 /* @section filters
425 **
426 ** Functions for creating filters from C-type (char*) strings).
427 **
428 ** @fdata [char*]
429 **
430 ** @nam3rule Getfilter Get a filter array
431 ** @nam4rule Case Case-insensitive filter
432 ** @nam4rule Lower Lower case filter.
433 ** @nam4rule Upper Upper case filter.
434 **
435 ** @argrule * txt [const char*] Character string
436 ** @valrule * [char*] Filter
437 ** @fcategory use
438 */
439
440
441
442
443 /* @func ajCharGetfilter ******************************************************
444 **
445 ** Returns a filter array to test for any character in a string.
446 **
447 ** @param [r] txt [const char*] Character set to test
448 ** @return [char*] Filter array set to 1 for each ascii value accepted
449 ** zero for any character not in the set.
450 **
451 ** @release 6.6.0
452 ** @@
453 ******************************************************************************/
454
ajCharGetfilter(const char * txt)455 char* ajCharGetfilter(const char *txt)
456 {
457 char *ret;
458 const char* cp;
459
460 ret = AJALLOC0(256);
461
462 if(!txt)
463 return ret;
464
465 if(!*txt)
466 return ret;
467
468 cp = txt;
469
470 while (*cp)
471 {
472 ret[((int)*cp++)] = 1;
473 }
474
475 return ret;
476 }
477
478
479
480
481 /* @func ajCharGetfilterCase **************************************************
482 ** Returns a filter array to test for any character in a string.
483 ** The filter is case-insensitive
484 **
485 ** @param [r] txt [const char*] Character set to test
486 ** @return [char*] Filter array set to 1 for each ascii value accepted
487 ** zero for any character not in the set.
488 **
489 ** @release 6.6.0
490 ** @@
491 ******************************************************************************/
492
ajCharGetfilterCase(const char * txt)493 char* ajCharGetfilterCase(const char *txt)
494 {
495 char *ret;
496 const char* cp;
497
498 ret = AJALLOC0(256);
499
500 if(!txt)
501 return ret;
502
503 if(!*txt)
504 return ret;
505
506 cp = txt;
507
508 while (*cp)
509 {
510 ret[tolower((int)*cp)] = 1;
511 ret[toupper((int)*cp++)] = 1;
512 }
513
514 return ret;
515 }
516
517
518
519
520 /* @func ajCharGetfilterLower *************************************************
521 **
522 ** Returns a filter array to test for any character in a string as lower case.
523 **
524 ** @param [r] txt [const char*] Character set to test
525 ** @return [char*] Filter array set to 1 for each ascii value accepted
526 ** zero for any character not in the set.
527 **
528 ** @release 6.6.0
529 ** @@
530 ******************************************************************************/
531
ajCharGetfilterLower(const char * txt)532 char* ajCharGetfilterLower(const char *txt)
533 {
534 char *ret;
535 const char* cp;
536
537 ret = AJALLOC0(256);
538
539 if(!txt)
540 return ret;
541
542 if(!*txt)
543 return ret;
544
545 cp = txt;
546
547 while (*cp)
548 {
549 ret[tolower((int)*cp++)] = 1;
550 }
551
552 return ret;
553 }
554
555
556
557
558 /* @func ajCharGetfilterUpper ************************************************
559 **
560 ** Returns a filter array to test for any character in a string as upper case.
561 **
562 ** @param [r] txt [const char*] Character set to test
563 ** @return [char*] Filter array set to 1 for each ascii value accepted
564 ** zero for any character not in the set.
565 **
566 ** @release 6.6.0
567 ** @@
568 ******************************************************************************/
569
ajCharGetfilterUpper(const char * txt)570 char* ajCharGetfilterUpper(const char *txt)
571 {
572 char *ret;
573 const char* cp;
574
575 ret = AJALLOC0(256);
576
577 if(!txt)
578 return ret;
579
580 if(!*txt)
581 return ret;
582
583 cp = txt;
584
585 while (*cp)
586 {
587 ret[toupper((int)*cp++)] = 1;
588 }
589
590 return ret;
591 }
592
593
594
595
596 /* @section formatting
597 **
598 ** Functions for formatting C-type (char*) strings).
599 **
600 ** @fdata [char*]
601 ** @fnote Same namrule as "String formatting functions"
602 **
603 ** @nam3rule Fmt Change the format of a string.
604 ** @nam4rule FmtCapital Convert each word to title case.
605 ** @nam4rule FmtLower Convert to lower case.
606 ** @nam4rule FmtTitle Convert to title case.
607 ** @nam4rule FmtUpper Convert to upper case.
608 **
609 ** @argrule * txt [char*] Character string
610 ** @valrule * [AjBool]
611 ** @fcategory modify
612 */
613
614
615
616
617 /* @func ajCharFmtLower *******************************************************
618 **
619 ** Converts a text string to lower case.
620 **
621 ** @param [u] txt [char*] Text string
622 ** @return [AjBool] ajTrue on success
623 **
624 ** @release 4.0.0
625 ** @@
626 ******************************************************************************/
627
ajCharFmtLower(char * txt)628 AjBool ajCharFmtLower(char* txt)
629 {
630 char* cp;
631 size_t ispan;
632
633 ispan = strcspn(txt, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
634 if(txt[ispan])
635 {
636 cp = txt;
637
638 while(*cp)
639 {
640 /*
641 * AJB: function ajSysItoC was there as some really fussy compilers
642 * complained about casting ajint to char. However, for conversion of
643 * large databases it's too much of an overhead. Think about a macro
644 * later. In the meantime revert to the standard system call
645 * *cp = ajSysCastItoc(tolower((int) *cp));
646 */
647 *cp = (char)tolower((int) *cp);
648 cp++;
649 }
650 }
651
652 return ajTrue;
653 }
654
655
656
657
658 /* @func ajCharFmtUpper *******************************************************
659 **
660 ** Converts a text string to upper case.
661 **
662 ** @param [u] txt [char*] Text string
663 ** @return [AjBool] ajTrue on success
664 **
665 ** @release 4.0.0
666 ** @@
667 ******************************************************************************/
668
ajCharFmtUpper(char * txt)669 AjBool ajCharFmtUpper(char* txt)
670 {
671 char* cp;
672 size_t ispan;
673
674 ispan = strcspn(txt, "abcdefghijklmnopqrstuvwxyz");
675 if(txt[ispan])
676 {
677 cp = txt;
678
679 while(*cp)
680 {
681 /*
682 * AJB: function ajSysItoC was there as some really fussy compilers
683 * complained about casting ajint to char. However, for conversion of
684 * large databases it's too much of an overhead. Think about a macro
685 * later. In the meantime revert to the standard system call
686 * *cp = ajSysCastItoc(toupper((ajint) *cp));
687 */
688 *cp = (char) toupper((int) *cp);
689 cp++;
690 }
691 }
692
693 return ajTrue;
694 }
695
696
697
698
699 /* @section comparison ********************************************************
700 **
701 ** Functions for comparing C-type (char*) strings.
702 **
703 ** @fdata [char*]
704 ** @fnote Same namrule as "String comparison functions".
705 ** @nam3rule Match Compare two complete strings.
706 ** @nam3rule Prefix Compare start of string to given prefix.
707 ** @nam3rule Suffix Compare end of string to given suffix.
708 ** @nam4rule MatchCase Case-insensitive comparison.
709 ** @nam4rule MatchWild Comparison using wildcard characters.
710 ** @nam5rule MatchWildCase Case-insensitive comparison using
711 ** wildcard characters.
712 ** @nam5rule MatchWildNext Comparison using wildcard characters to
713 ** next word in a string
714 ** @nam6rule MatchWildNextCase Case-insensitive comparison using
715 ** wildcard characters to next word in a string
716 ** @nam5rule MatchWildWord Comparison using wildcard characters to
717 ** whole words within a string.
718 ** @nam6rule MatchWildWordCase Case-insensitive comparison using
719 ** wildcard characters to whole words within a string.
720 ** @nam4rule PrefixCase Case-insensitive comparison.
721 ** @nam4rule SuffixCase Case-insensitive comparison.
722 **
723 ** @argrule * txt [const char*] Character string
724 ** @argrule C txt2 [const char*] Character string to compare
725 ** @argrule S str [const AjPStr] Character string to compare
726 ** @valrule * [AjBool] True on success
727 ** @fcategory use
728 */
729
730
731
732
733 /* @func ajCharMatchC *********************************************************
734 **
735 ** Simple test for matching two text strings.
736 **
737 ** @param [r] txt [const char*] String
738 ** @param [r] txt2 [const char*] Text
739 ** @return [AjBool] ajTrue if text completely matches the start of String
740 **
741 ** @release 4.0.0
742 ** @@
743 ******************************************************************************/
744
ajCharMatchC(const char * txt,const char * txt2)745 AjBool ajCharMatchC(const char* txt, const char* txt2)
746 {
747 if(!txt || !txt2)
748 return ajFalse;
749
750 if(!strcmp(txt, txt2))
751 return ajTrue;
752
753 return ajFalse;
754 }
755
756
757
758
759 /* @func ajCharMatchCaseC *****************************************************
760 **
761 ** Simple case-insensitive test for matching two text strings.
762 **
763 ** @param [r] txt [const char*] String
764 ** @param [r] txt2 [const char*] Text
765 ** @return [AjBool] ajTrue if two strings are exactly the same excluding case
766 **
767 ** @release 4.0.0
768 ** @@
769 ******************************************************************************/
770
ajCharMatchCaseC(const char * txt,const char * txt2)771 AjBool ajCharMatchCaseC(const char* txt, const char* txt2)
772 {
773 const char* cp;
774 const char* cq;
775
776 cp = txt;
777 cq = txt2;
778
779 if(!*cp && !*cq)
780 return ajTrue;
781
782 if(!*cp || !*cq)
783 return ajFalse;
784
785 while(*cp && *cq)
786 if(toupper((int) *cp++) != toupper((int) *cq++))
787 return ajFalse;
788
789 if(*cp || *cq)
790 return ajFalse;
791
792 return ajTrue;
793 }
794
795
796
797
798 /* @func ajCharMatchWildC *****************************************************
799 **
800 ** Simple case-sensitive test for matching two text strings using
801 ** wildcard characters.
802 **
803 ** @param [r] txt [const char*] String
804 ** @param [r] txt2 [const char*] Text
805 ** @return [AjBool] ajTrue if the strings match
806 **
807 ** @release 4.0.0
808 ** @@
809 ******************************************************************************/
810
ajCharMatchWildC(const char * txt,const char * txt2)811 AjBool ajCharMatchWildC(const char* txt, const char* txt2)
812 {
813 ajint i;
814
815 i = ajCharCmpWild(txt, txt2);
816
817 /*
818 ajDebug("ajCharMatchWildC' '%s' cmp: %d\n",
819 str, text, i);
820 */
821
822 if(i)
823 return ajFalse;
824
825 return ajTrue;
826 }
827
828
829
830
831 /* @func ajCharMatchWildS *****************************************************
832 **
833 ** Simple case-sensitive test for matching a text string and a string using
834 ** wildcard characters.
835 **
836 ** @param [r] txt [const char*] String
837 ** @param [r] str [const AjPStr] Wildcard text
838 ** @return [AjBool] ajTrue if the strings match
839 **
840 ** @release 4.0.0
841 ** @@
842 ******************************************************************************/
843
ajCharMatchWildS(const char * txt,const AjPStr str)844 AjBool ajCharMatchWildS(const char* txt, const AjPStr str)
845 {
846 return ajCharMatchWildC(txt, MAJSTRGETPTR(str));
847 }
848
849
850
851
852 /* @func ajCharMatchWildCaseC *************************************************
853 **
854 ** Simple case-insensitive test for matching two text strings using
855 ** wildcard characters.
856 **
857 ** @param [r] txt [const char*] String
858 ** @param [r] txt2 [const char*] Text
859 ** @return [AjBool] ajTrue if the strings match
860 **
861 ** @release 4.1.0
862 ** @@
863 ******************************************************************************/
864
ajCharMatchWildCaseC(const char * txt,const char * txt2)865 AjBool ajCharMatchWildCaseC(const char* txt, const char* txt2)
866 {
867 ajint i;
868
869 i = ajCharCmpWildCase(txt, txt2);
870
871
872 ajDebug("ajCharMatchWildCaseC '%s' '%s' cmp: %d\n",
873 txt, txt2, i);
874
875
876 if(i)
877 return ajFalse;
878
879 return ajTrue;
880 }
881
882
883
884
885 /* @func ajCharMatchWildCaseS *************************************************
886 **
887 ** Simple case-insensitive test for matching a text string and a string using
888 ** wildcard characters.
889 **
890 ** @param [r] txt [const char*] String
891 ** @param [r] str [const AjPStr] Wildcard text
892 ** @return [AjBool] ajTrue if the strings match
893 **
894 ** @release 4.1.0
895 ** @@
896 ******************************************************************************/
897
ajCharMatchWildCaseS(const char * txt,const AjPStr str)898 AjBool ajCharMatchWildCaseS(const char* txt, const AjPStr str)
899 {
900 return ajCharMatchWildCaseC(txt, MAJSTRGETPTR(str));
901 }
902
903
904
905
906 /* @func ajCharMatchWildNextC *************************************************
907 **
908 ** Test for matching the next 'word' in two text strings using
909 ** wildcard characters.
910 **
911 ** @param [r] txt [const char*] String
912 ** @param [r] txt2 [const char*] Text
913 ** @return [AjBool] ajTrue if found
914 **
915 ** @release 4.0.0
916 ** @@
917 ******************************************************************************/
918
ajCharMatchWildNextC(const char * txt,const char * txt2)919 AjBool ajCharMatchWildNextC(const char* txt, const char* txt2)
920 {
921 const char* cp;
922 const char* cq;
923 const char* savecp;
924 char lastch = '\0';
925
926 ajDebug("ajCharMatchWildNextC '%s' '%s'\n", txt, txt2);
927
928 cp = txt2;
929 cq = txt;
930
931 if(!*cp && !*cq)
932 return ajTrue; /* both empty */
933
934 if(!*cp)
935 return ajFalse; /* no query text */
936
937 while(*cp && !isspace((int) *cp))
938 {
939 if(!*cq && *cp != '*')
940 return ajFalse;
941
942 switch(*cp)
943 {
944 case '?': /* skip next character and continue */
945 lastch = *cq;
946 cp++;
947 cq++;
948 break;
949 case '*':
950 cp++; /* recursive call to test the rest */
951
952 if(!*cp)
953 {
954 ajDebug("...matches at end +%d '%s' +%d '%s'\n",
955 (cq - txt), cq, (cp - txt2), cp);
956 return ajTrue; /* just match the rest */
957 }
958
959 if(!*cq) /* no more string to compare */
960 {
961 savecp = cp;
962
963 while(*cp == '*')
964 savecp = cp++; /* may be ***... savecp is last '*' */
965
966 if(!*cp)
967 return ajTrue;
968
969 return ajCharMatchWildNextC(cq,savecp);
970 }
971
972 while(*cq)
973 { /* wildcard in mid name, look for the rest */
974 if(ajCharMatchWildNextC(cq, cp)) /* recursive + repeats */
975 return ajTrue;
976
977 ajDebug("...'*' at +%d '%s' +%d '%s' continuing\n",
978 (cq - txt), cq, (cp - txt2), cp);
979 cq++;
980 }
981
982 return ajFalse; /* if we're still here, it failed */
983
984 /* always returns once '*' is found */
985
986 default: /* for all other characters, keep checking */
987 if(*cp != *cq)
988 return ajFalse;
989
990 cp++;
991
992 if(*cq)
993 {
994 lastch = *cq;
995 cq++;
996 }
997 }
998 }
999
1000 ajDebug("...done comparing at +%d '%s' +%d '%s' lastch '%c'\n",
1001 (cq - txt), cq, (cp - txt2), cp, lastch);
1002
1003 if(!isalnum((int) lastch))
1004 {
1005 ajDebug("not a word boundary at '%c'\n", lastch);
1006
1007 return ajFalse;
1008 }
1009
1010 if(*cp)
1011 {
1012 ajDebug("...incomplete cp, FAILED\n");
1013
1014 return ajFalse ;
1015 }
1016
1017 if(*cq)
1018 {
1019 if(isalnum((int) *cq))
1020 {
1021 ajDebug("word continues, failed\n");
1022
1023 return ajFalse;
1024 }
1025
1026 ajDebug("word end ... success\n");
1027
1028 return ajTrue;
1029 }
1030
1031 ajDebug("...all finished and matched\n");
1032
1033 return ajTrue;
1034 }
1035
1036
1037
1038
1039 /* @func ajCharMatchWildNextCaseC *********************************************
1040 **
1041 ** Test for matching the next 'word' in two text strings using
1042 ** wildcard characters, case-insensitive.
1043 **
1044 ** @param [r] txt [const char*] String
1045 ** @param [r] txt2 [const char*] Text
1046 ** @return [AjBool] ajTrue if found
1047 **
1048 ** @release 4.1.0
1049 ** @@
1050 ******************************************************************************/
1051
ajCharMatchWildNextCaseC(const char * txt,const char * txt2)1052 AjBool ajCharMatchWildNextCaseC(const char* txt, const char* txt2)
1053 {
1054 const char* cp;
1055 const char* cq;
1056 const char* savecp;
1057 char lastch = '\0';
1058
1059 ajDebug("ajCharMatchWildNextCaseC '%s' '%s'\n", txt, txt2);
1060
1061 cp = txt2;
1062 cq = txt;
1063
1064 if(!*cp && !*cq)
1065 return ajTrue; /* both empty */
1066
1067 if(!*cp)
1068 return ajFalse; /* no query text */
1069
1070 while(*cp && !isspace((int) *cp))
1071 {
1072 if(!*cq && *cp != '*')
1073 return ajFalse;
1074
1075 switch(*cp)
1076 {
1077 case '?': /* skip next character and continue */
1078 lastch = *cq;
1079 cp++;
1080 cq++;
1081 break;
1082 case '*':
1083 cp++; /* recursive call to test the rest */
1084
1085 if(!*cp)
1086 {
1087 ajDebug("...matches at end +%d '%s' +%d '%s'\n",
1088 (cq - txt), cq, (cp - txt2), cp);
1089
1090 return ajTrue; /* just match the rest */
1091 }
1092
1093 if(!*cq) /* no more string to compare */
1094 {
1095 savecp = cp;
1096
1097 while(*cp == '*')
1098 savecp = cp++; /* may be ***... savecp is last '*' */
1099
1100 if(!*cp)
1101 return ajTrue;
1102
1103 return ajCharMatchWildNextCaseC(cq,savecp);
1104 }
1105
1106 while(*cq)
1107 { /* wildcard in mid name, look for the rest */
1108 if(ajCharMatchWildNextCaseC(cq, cp)) /* recursive + repeats */
1109 return ajTrue;
1110
1111 ajDebug("...'*' at +%d '%s' +%d '%s' continuing\n",
1112 (cq - txt), cq, (cp - txt2), cp);
1113 cq++;
1114 }
1115
1116 return ajFalse; /* if we're still here, it failed */
1117
1118 /* always returns once '*' is found */
1119
1120 default: /* for all other characters, keep checking */
1121 if(toupper((int) *cp) != toupper((int) *cq))
1122 return ajFalse;
1123
1124 cp++;
1125
1126 if(*cq)
1127 {
1128 lastch = *cq;
1129 cq++;
1130 }
1131 }
1132 }
1133
1134 ajDebug("...done comparing at +%d '%s' +%d '%s' lastch '%c'\n",
1135 (cq - txt), cq, (cp - txt2), cp, lastch);
1136
1137 if(!isalnum((int) lastch))
1138 {
1139 ajDebug("not a word boundary at '%c'\n", lastch);
1140
1141 return ajFalse;
1142 }
1143
1144 if(*cp)
1145 {
1146 ajDebug("...incomplete cp, FAILED\n");
1147
1148 return ajFalse ;
1149 }
1150
1151 if(*cq)
1152 {
1153 if(isalnum((int) *cq))
1154 {
1155 ajDebug("word continues, failed\n");
1156
1157 return ajFalse;
1158 }
1159
1160 ajDebug("word end ... success\n");
1161
1162 return ajTrue;
1163 }
1164
1165 ajDebug("...all finished and matched\n");
1166
1167 return ajTrue;
1168 }
1169
1170
1171
1172
1173 /* @func ajCharMatchWildWordC *************************************************
1174 **
1175 ** Case-sensitive test for matching a text string 'word' against any
1176 ** word in a test text string using wildcard characters.
1177 **
1178 ** 'Word' is defined as starting and ending with an alphanumeric character
1179 ** (A-Z a-z 0-9) with no white space.
1180 **
1181 ** The query text can use '*' or '?' as a wildcard.
1182 **
1183 ** @param [r] txt [const char*] String
1184 ** @param [r] txt2 [const char*] Wildcard word
1185 ** @return [AjBool] ajTrue if found
1186 **
1187 ** @release 4.0.0
1188 ** @@
1189 ******************************************************************************/
1190
ajCharMatchWildWordC(const char * txt,const char * txt2)1191 AjBool ajCharMatchWildWordC(const char* txt, const char* txt2)
1192 {
1193 const char* cp;
1194 const char* cq;
1195 AjBool word = ajFalse;
1196
1197 ajDebug("ajCharMatchWildWordC('%s', '%s')\n", txt, txt2);
1198
1199 cp = txt2;
1200 cq = txt;
1201
1202 if(!*cp && !*cq)
1203 return ajTrue;
1204
1205 if(!*cp)
1206 return ajFalse;
1207
1208 ajDebug("something to test, continue...\n");
1209
1210 /* unlike ajCharMatchWild, we step through the string (str) not the
1211 query (text) */
1212
1213 while(*cq)
1214 {
1215 if(!word)
1216 {
1217 if(isalnum((int) *cq))
1218 { /* start of word */
1219 word = ajTrue;
1220
1221 if(ajCharMatchWildNextC(cq, txt2))
1222 return ajTrue;
1223 }
1224 }
1225 else
1226 {
1227 if(!isalnum((int) *cq))
1228 word = ajFalse;
1229 }
1230
1231 cq++;
1232 }
1233
1234 return ajFalse;
1235 }
1236
1237
1238
1239
1240 /* @func ajCharMatchWildWordCaseC *********************************************
1241 **
1242 ** Case-insensitive test for matching a text string 'word' against any
1243 ** word in a text string using wildcard characters.
1244 **
1245 ** 'Word' is defined as starting and ending with an alphanumeric character
1246 ** (A-Z a-z 0-9) with no white space.
1247 **
1248 ** The query text can use '*' or '?' as a wildcard.
1249 **
1250 ** @param [r] txt [const char*] String
1251 ** @param [r] txt2 [const char*] Wildcard word
1252 ** @return [AjBool] ajTrue if found
1253 **
1254 ** @release 4.1.0
1255 ** @@
1256 ******************************************************************************/
1257
ajCharMatchWildWordCaseC(const char * txt,const char * txt2)1258 AjBool ajCharMatchWildWordCaseC(const char* txt, const char* txt2)
1259 {
1260 const char* cp;
1261 const char* cq;
1262 AjBool word = ajFalse;
1263
1264 ajDebug("ajCharMatchWildWordCaseC('%s', '%s')\n", txt, txt2);
1265
1266 cp = txt2;
1267 cq = txt;
1268
1269 if(!*cp && !*cq)
1270 return ajTrue;
1271
1272 if(!*cp)
1273 return ajFalse;
1274
1275 ajDebug("something to test, continue...\n");
1276
1277 /* unlike ajCharMatchWild, we step through the string (str) not the
1278 query (text) */
1279
1280 while(*cq)
1281 {
1282 if(!word)
1283 {
1284 if(isalnum((int) *cq))
1285 { /* start of word */
1286 word = ajTrue;
1287
1288 if(ajCharMatchWildNextCaseC(cq, txt2))
1289 return ajTrue;
1290 }
1291 }
1292 else
1293 {
1294 if(!isalnum((int) *cq))
1295 word = ajFalse;
1296 }
1297
1298 cq++;
1299 }
1300
1301 return ajFalse;
1302 }
1303
1304
1305
1306
1307 /* @func ajCharPrefixC ********************************************************
1308 **
1309 ** Test for matching the start of a text string against a given prefix text
1310 ** string.
1311 **
1312 ** @param [r] txt [const char*] Test string as text
1313 ** @param [r] txt2 [const char*] Prefix as text
1314 ** @return [AjBool] ajTrue if the string begins with the prefix
1315 **
1316 ** @release 4.0.0
1317 ** @@
1318 ******************************************************************************/
1319
ajCharPrefixC(const char * txt,const char * txt2)1320 AjBool ajCharPrefixC(const char* txt, const char* txt2)
1321 {
1322 size_t ilen;
1323
1324 if(!txt)
1325 return ajFalse;
1326
1327 if(!txt2)
1328 return ajFalse;
1329
1330 ilen = strlen(txt2);
1331
1332 if(!ilen) /* no prefix */
1333 return ajFalse;
1334
1335 if(ilen > strlen(txt)) /* prefix longer */
1336 return ajFalse;
1337
1338 if(strncmp(txt, txt2, ilen)) /* +1 or -1 for a failed match */
1339 return ajFalse;
1340
1341 return ajTrue;
1342 }
1343
1344
1345
1346
1347 /* @func ajCharPrefixS ********************************************************
1348 **
1349 ** Test for matching the start of a text string against a given prefix string.
1350 **
1351 ** @param [r] txt [const char*] Test string as text
1352 ** @param [r] str [const AjPStr] Prefix as string
1353 ** @return [AjBool] ajTrue if the string begins with the prefix
1354 **
1355 ** @release 4.0.0
1356 ** @@
1357 ******************************************************************************/
1358
ajCharPrefixS(const char * txt,const AjPStr str)1359 AjBool ajCharPrefixS(const char* txt, const AjPStr str)
1360 {
1361 if(!txt)
1362 return ajFalse;
1363
1364 if(!str)
1365 return ajFalse;
1366
1367 if(str->Len > strlen(txt)) /* prefix longer */
1368 return ajFalse;
1369
1370 if(strncmp(txt, MAJSTRGETPTR(str), str->Len)) /* +1 or -1 for
1371 a failed match */
1372 return ajFalse;
1373
1374 return ajTrue;
1375 }
1376
1377
1378
1379
1380 /* @func ajCharPrefixCaseC ****************************************************
1381 **
1382 ** Case-insensitive test for matching the start of a text string against a
1383 ** given prefix text string.
1384 **
1385 ** @param [r] txt [const char*] Text
1386 ** @param [r] txt2 [const char*] Prefix
1387 ** @return [AjBool] ajTrue if the string begins with the prefix
1388 **
1389 ** @release 4.0.0
1390 ** @@
1391 ******************************************************************************/
1392
ajCharPrefixCaseC(const char * txt,const char * txt2)1393 AjBool ajCharPrefixCaseC(const char* txt, const char* txt2)
1394 {
1395 const char* cp;
1396 const char* cq;
1397
1398 if(!txt)
1399 return ajFalse;
1400
1401 if(!txt2)
1402 return ajFalse;
1403
1404 cp = txt;
1405 cq = txt2;
1406
1407 /* ajDebug("ajCharPrefixCaseC '%s' '%s'\n", txt, txt2); */
1408
1409 if(!*cq)
1410 return ajFalse;
1411
1412 while(*cp && *cq)
1413 {
1414 if(toupper((int) *cp) != toupper((int) *cq))
1415 return ajFalse;
1416
1417 cp++;cq++;
1418 }
1419
1420 if(*cq)
1421 return ajFalse;
1422
1423 /* ajDebug("ajStrPrefixCaseCC ..TRUE..\n"); */
1424 return ajTrue;
1425 }
1426
1427
1428
1429
1430 /* @func ajCharPrefixCaseS ****************************************************
1431 **
1432 ** Case-insensitive test for matching start of a text string against a given
1433 ** prefix string,
1434 **
1435 ** @param [r] txt [const char*] Text
1436 ** @param [r] str [const AjPStr] Prefix
1437 ** @return [AjBool] ajTrue if the string begins with the prefix
1438 **
1439 ** @release 4.0.0
1440 ** @@
1441 ******************************************************************************/
1442
ajCharPrefixCaseS(const char * txt,const AjPStr str)1443 AjBool ajCharPrefixCaseS(const char* txt, const AjPStr str)
1444 {
1445 if(!str)
1446 return ajFalse;
1447
1448 return ajCharPrefixCaseC(txt, MAJSTRGETPTR(str));
1449 }
1450
1451
1452
1453
1454 /* @func ajCharSuffixC ********************************************************
1455 **
1456 ** Test for matching the end of a text string against a given suffix text
1457 ** string.
1458 **
1459 ** @param [r] txt [const char*] String
1460 ** @param [r] txt2 [const char*] Suffix as text
1461 ** @return [AjBool] ajTrue if the string ends with the suffix
1462 **
1463 ** @release 4.0.0
1464 ** @@
1465 ******************************************************************************/
1466
ajCharSuffixC(const char * txt,const char * txt2)1467 AjBool ajCharSuffixC(const char* txt, const char* txt2)
1468 {
1469 size_t ilen;
1470 size_t jlen;
1471 size_t jstart;
1472
1473 if(!txt)
1474 return ajFalse;
1475
1476 if(!txt2)
1477 return ajFalse;
1478
1479 ilen = strlen(txt2);
1480 jlen = strlen(txt);
1481 jstart = jlen - ilen;
1482
1483 if(ilen > jlen) /* suffix longer */
1484 return ajFalse;
1485
1486 if(strncmp(&txt[jstart], txt2, ilen)) /* +1 or -1 for a
1487 failed match */
1488 return ajFalse;
1489
1490 return ajTrue;
1491 }
1492
1493
1494
1495
1496 /* @func ajCharSuffixS ********************************************************
1497 **
1498 ** Test for matching the end of a text string against a given suffix string.
1499 **
1500 ** @param [r] txt [const char*] Test string as text
1501 ** @param [r] str [const AjPStr] Suffix as string
1502 ** @return [AjBool] ajTrue if the string ends with the suffix
1503 **
1504 ** @release 4.0.0
1505 ** @@
1506 ******************************************************************************/
1507
ajCharSuffixS(const char * txt,const AjPStr str)1508 AjBool ajCharSuffixS(const char* txt, const AjPStr str)
1509 {
1510 size_t jlen;
1511 size_t jstart;
1512
1513 if(!txt)
1514 return ajFalse;
1515
1516 if(!str)
1517 return ajFalse;
1518
1519 jlen = strlen(txt);
1520 jstart = jlen - str->Len;
1521
1522 if(str->Len > jlen) /* suffix longer */
1523 return ajFalse;
1524
1525 if(strncmp(&txt[jstart], MAJSTRGETPTR(str), str->Len)) /* +1 or -1 for a
1526 failed match */
1527 return ajFalse;
1528
1529 return ajTrue;
1530 }
1531
1532
1533
1534
1535 /* @func ajCharSuffixCaseC ****************************************************
1536 **
1537 ** Case-insensitive test for matching the end of a text string against a given
1538 ** suffix text string.
1539 **
1540 ** @param [r] txt [const char*] String
1541 ** @param [r] txt2 [const char*] Suffix as text
1542 ** @return [AjBool] ajTrue if the string ends with the suffix
1543 **
1544 ** @release 4.0.0
1545 ** @@
1546 ******************************************************************************/
1547
ajCharSuffixCaseC(const char * txt,const char * txt2)1548 AjBool ajCharSuffixCaseC(const char* txt, const char* txt2)
1549 {
1550 size_t ilen;
1551 size_t jlen;
1552 size_t jstart;
1553 const char* cp;
1554 const char* cq;
1555
1556 if(!txt)
1557 return ajFalse;
1558
1559 if(!txt2)
1560 return ajFalse;
1561
1562 ilen = strlen(txt2);
1563 jlen = strlen(txt);
1564 jstart = jlen - ilen;
1565
1566 if(ilen > jlen) /* suffix longer */
1567 return ajFalse;
1568
1569 cp = &txt[jstart];
1570 cq = txt2;
1571
1572 while (*cp)
1573 {
1574 if(toupper((int)*cp) != toupper((int)*cq))
1575 return ajFalse;
1576
1577 cp++; cq++;
1578 }
1579
1580 return ajTrue;
1581 }
1582
1583
1584
1585
1586 /* @func ajCharSuffixCaseS ****************************************************
1587 **
1588 ** Case-insensitive test for matching the end of a text string against a given
1589 ** suffix string.
1590 **
1591 ** @param [r] txt [const char*] Test string as text
1592 ** @param [r] str [const AjPStr] Suffix as string
1593 ** @return [AjBool] ajTrue if the string ends with the suffix
1594 **
1595 ** @release 4.0.0
1596 ** @@
1597 ******************************************************************************/
1598
ajCharSuffixCaseS(const char * txt,const AjPStr str)1599 AjBool ajCharSuffixCaseS(const char* txt, const AjPStr str)
1600 {
1601 size_t jlen;
1602 size_t jstart;
1603 const char* cp;
1604 const char* cq;
1605
1606 if(!txt)
1607 return ajFalse;
1608
1609 if(!str)
1610 return ajFalse;
1611
1612 jlen = strlen(txt);
1613 jstart = jlen - str->Len;
1614
1615 if(str->Len > jlen) /* suffix longer */
1616 return ajFalse;
1617
1618 cp = &txt[jstart];
1619 cq = MAJSTRGETPTR(str);
1620
1621 while (cp)
1622 {
1623 if(toupper((int)*cp) != toupper((int)*cq)) return ajFalse;
1624 cp++; cq++;
1625 }
1626
1627 return ajTrue;
1628 }
1629
1630
1631
1632
1633 /* @section comparison (sorting)
1634 **
1635 ** Functions for sorting strings (including C-type char* strings).
1636 **
1637 ** @fdata [char*]
1638 ** @fnote namrule same as "String comparison (sorting) functions".
1639 **
1640 ** @nam3rule Cmp Compare two complete strings & return sort order.
1641 ** @nam4rule CmpCase Case-insensitive comparison.
1642 ** @nam4rule CmpWild Comparison using wildcard characters.
1643 ** @nam5rule CmpWildCase Case-insensitive comparison using
1644 ** wildcard characters.
1645 **
1646 ** @argrule * txt [const char*] Character string
1647 ** @argrule * txt2 [const char*] Comparison string
1648 ** @argrule Len len [size_t] Number of characters to compare
1649 ** @valrule * [int] -1 if first string should sort before second, +1 if the
1650 ** second string should sort first. 0 if they are identical
1651 ** in length and content.
1652 ** @fcategory use
1653 */
1654
1655
1656
1657
1658 /* @func ajCharCmpCase ********************************************************
1659 **
1660 ** Finds the sort order of two text strings.
1661 **
1662 ** @param [r] txt [const char*] Text string
1663 ** @param [r] txt2 [const char*] Text string
1664 ** @return [int] -1 if first string should sort before second, +1 if the
1665 ** second string should sort first. 0 if they are identical
1666 ** in length and content.
1667 **
1668 ** @release 4.0.0
1669 ** @@
1670 ******************************************************************************/
1671
ajCharCmpCase(const char * txt,const char * txt2)1672 int ajCharCmpCase(const char* txt, const char* txt2)
1673 {
1674 const char* cp;
1675 const char* cq;
1676
1677 for(cp = txt, cq = txt2; *cp && *cq; cp++, cq++)
1678 if(toupper((int) *cp) != toupper((int) *cq))
1679 {
1680 if(toupper((int) *cp) > toupper((int) *cq))
1681 return 1;
1682 else
1683 return -1;
1684 }
1685
1686 if(*cp)
1687 return 1;
1688
1689 if(*cq)
1690 return -1;
1691
1692 return 0;
1693 }
1694
1695
1696
1697
1698 /* @func ajCharCmpCaseLen *****************************************************
1699 **
1700 ** Finds the sort order of substrings from the start of two text strings.
1701 **
1702 ** @param [r] txt [const char*] Text string
1703 ** @param [r] txt2 [const char*] Text string
1704 ** @param [r] len [size_t] length
1705 ** @return [int] -1 if first string should sort before second, +1 if the
1706 ** second string should sort first. 0 if they are identical
1707 ** in length and content.
1708 **
1709 ** @release 4.0.0
1710 ** @@
1711 ******************************************************************************/
1712
ajCharCmpCaseLen(const char * txt,const char * txt2,size_t len)1713 int ajCharCmpCaseLen(const char* txt, const char* txt2, size_t len)
1714 {
1715 const char* cp;
1716 const char* cq;
1717 size_t i;
1718
1719 for(cp=txt,cq=txt2,i=0;*cp && *cq && i<len;++i,++cp,++cq)
1720 if(toupper((int) *cp) != toupper((int) *cq))
1721 {
1722 if(toupper((int) *cp) > toupper((int) *cq))
1723 return 1;
1724 else
1725 return -1;
1726 }
1727
1728 if(i==len)
1729 return 0;
1730
1731 if(*cp)
1732 return 1;
1733
1734 return -1;
1735 }
1736
1737
1738
1739
1740 /* @func ajCharCmpWild ********************************************************
1741 **
1742 ** Finds the sort-order (case insensitive) of two text strings using
1743 ** wildcard characters.
1744 **
1745 ** @param [r] txt [const char*] String
1746 ** @param [r] txt2 [const char*] Text
1747 ** @return [int] -1 if first string should sort before second, +1 if the
1748 ** second string should sort first. 0 if they are identical
1749 ** in length and content.
1750 **
1751 ** @release 4.0.0
1752 ** @@
1753 ******************************************************************************/
1754
ajCharCmpWild(const char * txt,const char * txt2)1755 int ajCharCmpWild(const char* txt, const char* txt2)
1756 {
1757 const char* cp;
1758 const char* cq;
1759
1760 /*ajDebug("ajCharCmpWild('%s', '%s')\n", str, text);*/
1761
1762 cp = txt2;
1763 cq = txt;
1764
1765 if(!*cp && !*cq)
1766 return 0;
1767
1768 if(!*cp)
1769 return -1;
1770
1771 /*ajDebug("something to test, continue...\n");*/
1772
1773 while(*cp)
1774 {
1775 if(!*cq && *cp != '*')
1776 return 1;
1777
1778 switch(*cp)
1779 {
1780 case '?': /* skip next character and continue */
1781 cp++;
1782 cq++;
1783 break;
1784 case '*':
1785 cp++;
1786
1787 if(!*cp)
1788 {
1789 /* ajDebug("...matches at end +%d '%s' +%d '%s'\n",
1790 (cq - str), cq, (cp - text), cp);*/
1791
1792 return 0; /* just match the rest */
1793 }
1794
1795 if(!*cq)
1796 {
1797 /*ajDebug("...test match to null string just in case\n");*/
1798
1799 return ajCharCmpWild(cq, cp);
1800 }
1801
1802 while(*cq)
1803 { /* wildcard in mid name, look for the rest */
1804 if(ajCharMatchWildC(cq, cp))
1805 return 0; /* recursive + repeats */
1806
1807 /* ajDebug("...'*' at +%d '%s' +%d '%s' continuing\n",
1808 (cq - str), cq, (cp - text), cp);*/
1809 cq++;
1810 }
1811
1812 return 1;
1813
1814 /* always returns once '*' is found */
1815
1816 default: /* for all other characters, keep checking */
1817 if(*cp != *cq)
1818 {
1819 if(*cp > *cq)
1820 return -1;
1821 else
1822 return 1;
1823 }
1824
1825 cp++;
1826
1827 if(*cq)
1828 cq++;
1829 }
1830 }
1831
1832 /*ajDebug("...done comparing at +%d '%s' +%d '%s'\n",
1833 (cq - str), cq, (cp - text), cp);*/
1834 if(*cp)
1835 {
1836 /*ajDebug("...incomplete cp, FAILED\n");*/
1837 return -1 ;
1838 }
1839
1840 if(*cq)
1841 {
1842 /*ajDebug("...incomplete cq, FAILED\n");*/
1843 return 1;
1844 }
1845 /*ajDebug("...all finished and matched\n");*/
1846
1847 return 0;
1848 }
1849
1850
1851
1852
1853 /* @func ajCharCmpWildCase ****************************************************
1854 **
1855 ** Finds the sort-order (case sensitive) of two text strings using
1856 ** wildcard characters.
1857 **
1858 ** @param [r] txt [const char*] String
1859 ** @param [r] txt2 [const char*] Text
1860 ** @return [int] -1 if first string should sort before second, +1 if the
1861 ** second string should sort first. 0 if they are identical
1862 ** in length and content.
1863 **
1864 ** @release 4.1.0
1865 ** @@
1866 ******************************************************************************/
1867
ajCharCmpWildCase(const char * txt,const char * txt2)1868 int ajCharCmpWildCase(const char* txt, const char* txt2)
1869 {
1870 const char* cp;
1871 const char* cq;
1872
1873 ajDebug("ajCharCmpWildCase('%s', '%s')\n", txt, txt2);
1874
1875 cp = txt2;
1876 cq = txt;
1877
1878 if(!*cp && !*cq)
1879 return 0;
1880
1881 if(!*cp)
1882 return -1;
1883
1884 /*ajDebug("something to test, continue...\n");*/
1885
1886 while(*cp)
1887 {
1888 if(!*cq && *cp != '*')
1889 return 1;
1890
1891 switch(*cp)
1892 {
1893 case '?': /* skip next character and continue */
1894 cp++;
1895 cq++;
1896 break;
1897 case '*':
1898 cp++;
1899
1900 if(!*cp)
1901 {
1902 /* ajDebug("...matches at end +%d '%s' +%d '%s'\n",
1903 (cq - str), cq, (cp - text), cp);*/
1904
1905 return 0; /* just match the rest */
1906 }
1907
1908 if(!*cq)
1909 {
1910 /*ajDebug("...test match to null string just in case\n");*/
1911
1912 return ajCharCmpWildCase(cq, cp);
1913 }
1914
1915 while(*cq)
1916 { /* wildcard in mid name, look for the rest */
1917 if(ajCharMatchWildCaseC(cq, cp))
1918 return 0; /* recursive + repeats */
1919
1920 /* ajDebug("...'*' at +%d '%s' +%d '%s' continuing\n",
1921 (cq - str), cq, (cp - text), cp);*/
1922 cq++;
1923 }
1924
1925 return 1;
1926
1927 /* always returns once '*' is found */
1928
1929 default: /* for all other characters, keep checking */
1930 if(toupper((int) *cp) != toupper((int) *cq))
1931 {
1932 if(toupper((int) *cp) > toupper((int) *cq))
1933 return -1;
1934 else
1935 return 1;
1936 }
1937
1938 cp++;
1939
1940 if(*cq)
1941 cq++;
1942 }
1943 }
1944
1945 /*ajDebug("...done comparing at +%d '%s' +%d '%s'\n",
1946 (cq - str), cq, (cp - text), cp);*/
1947
1948 if(*cp)
1949 {
1950 /*ajDebug("...incomplete cp, FAILED\n");*/
1951
1952 return -1 ;
1953 }
1954
1955 if(*cq)
1956 {
1957 /*ajDebug("...incomplete cq, FAILED\n");*/
1958
1959 return 1;
1960 }
1961
1962 /*ajDebug("...all finished and matched\n");*/
1963
1964 return 0;
1965 }
1966
1967
1968
1969
1970 /* @section parsing functions *************************************************
1971 **
1972 ** Simple token parsing of strings
1973 **
1974 ** @fdata [char*]
1975 **
1976 ** @nam3rule Parse Parsing
1977 ** @argrule * txt [const char*] Text to be parsed
1978 ** @argrule C txtdelim [const char*] Delimiter set
1979 ** @valrule * [AjPStr] String token result, now owned by calling function.
1980 ** @fcategory use
1981 */
1982
1983
1984
1985
1986 /* @func ajCharParseC *********************************************************
1987 **
1988 ** Simple token parsing from text string using a specified set of delimiters.
1989 **
1990 ** @param [r] txt [const char*] String to be parsed (first call) or
1991 ** NULL for follow-up calls using the same string, as for the
1992 ** C RTL function strtok which is eventually called.
1993 ** @param [r] txtdelim [const char*] Delimiter(s) to be used between tokens.
1994 ** @return [AjPStr] Token
1995 ** @error NULL if no further token is found.
1996 **
1997 ** @release 4.0.0
1998 ** @@
1999 ******************************************************************************/
2000
ajCharParseC(const char * txt,const char * txtdelim)2001 AjPStr ajCharParseC (const char* txt, const char* txtdelim)
2002 {
2003 static AjPStr strp = NULL; /* internal AjPStr - do not try to destroy */
2004 static char* cp = NULL;
2005
2006 if (!strp)
2007 {
2008 if (!txt)
2009 {
2010 ajWarn("Error in ajCharParseC: NULL argument and not initialised");
2011
2012 return NULL;
2013 }
2014
2015 AJNEW0(strp);
2016 strp->Use = 1;
2017 }
2018
2019 if (txt)
2020 {
2021 if (cp) ajCharDel(&cp);
2022
2023 cp = ajCharNewC(txt);
2024 strp->Ptr = ajSysFuncStrtok(cp, txtdelim);
2025 }
2026 else
2027 {
2028 strp->Ptr = ajSysFuncStrtok(NULL, txtdelim);
2029 }
2030
2031 if (strp->Ptr)
2032 {
2033 strp->Len = strlen(strp->Ptr);
2034 strp->Res = strp->Len + 1;
2035
2036 return strp;
2037 }
2038 else
2039 {
2040 strp->Len=0;
2041 strp->Res=1;
2042 strp->Use=0;
2043 }
2044
2045 return NULL;
2046 }
2047
2048
2049
2050
2051 /* @datasection [AjPStr] String ***********************************************
2052 **
2053 ** Functions for manipulating AJAX (AjPStr) strings
2054 **
2055 ** @nam2rule Str Function is for manipulating strings
2056 **
2057 */
2058
2059
2060
2061
2062 /* @section constructors ******************************************************
2063 **
2064 ** Functions for constructing string objects, possibly with a starting string.
2065 **
2066 ** @fdata [AjPStr]
2067 ** @fnote Same namrule as "String constructor functions:
2068 ** C-type (char*) strings"
2069 ** @nam3rule New Construct a new string.
2070 ** @nam4rule NewClear Construct with an empty string.
2071 ** @nam4rule NewRef Construct making a reference counted copy of
2072 ** an existing string.
2073 ** @nam4rule NewRes Construct with reserved size.
2074 **
2075 ** @argrule C txt [const char*] Text string
2076 ** @argrule K ch [char] Single character
2077 ** @argrule S str [const AjPStr] Text string
2078 ** @argrule NewRes size [size_t] Reserved size
2079 ** @argrule NewRef refstr [AjPStr] Text string to be duplicated
2080 ** @argrule Len len [size_t] Length of string
2081 ** @valrule * [AjPStr] New string
2082 ** @fcategory new
2083 */
2084
2085
2086
2087
2088 /* @func ajStrNew *************************************************************
2089 **
2090 ** Default string constructor which allocates memory for a string.
2091 **
2092 ** The null string usage pointer is incremented.
2093 **
2094 ** @return [AjPStr] Pointer to an empty string
2095 **
2096 ** @release 1.0.0
2097 ** @@
2098 ******************************************************************************/
2099
ajStrNew(void)2100 AjPStr ajStrNew(void)
2101 {
2102 return ajStrNewRef(strPNULL);
2103 }
2104
2105
2106
2107
2108 /* @func ajStrNewC ************************************************************
2109 **
2110 ** String constructor which allocates memory for a string and initialises it
2111 ** with the text string provided.
2112 **
2113 ** The string size is set just large enough to hold the supplied text.
2114 **
2115 ** @param [r] txt [const char*] Null-terminated character string to initialise
2116 ** the new string.
2117 ** @return [AjPStr] Pointer to a string containing the supplied text
2118 **
2119 ** @release 1.0.0
2120 ** @@
2121 ******************************************************************************/
2122
ajStrNewC(const char * txt)2123 AjPStr ajStrNewC(const char* txt)
2124 {
2125 size_t i;
2126 size_t j;
2127 AjPStr thys;
2128
2129 i = strlen(txt);
2130 j = ajRound(i + 1, STRSIZE);
2131
2132 thys = ajStrNewResLenC(txt, j, i);
2133
2134 return thys;
2135 }
2136
2137
2138
2139
2140 /* @func ajStrNewK ************************************************************
2141 **
2142 ** String constructor which allocates memory for a string and initialises it
2143 ** with the single character provided.
2144 **
2145 ** The string size is set just large enough to hold the supplied text.
2146 **
2147 ** @param [r] ch [char] Null-terminated character string to initialise
2148 ** the new string.
2149 ** @return [AjPStr] Pointer to a string containing the supplied text
2150 **
2151 ** @release 6.2.0
2152 ** @@
2153 ******************************************************************************/
2154
ajStrNewK(char ch)2155 AjPStr ajStrNewK(char ch)
2156 {
2157 char txt[2] = " ";
2158 AjPStr thys;
2159
2160 txt[0] = ch;
2161 thys = ajStrNewResLenC(txt, 2, 1);
2162
2163 return thys;
2164 }
2165
2166
2167
2168
2169 /* @func ajStrNewS ************************************************************
2170 **
2171 ** String constructor which allocates memory for a string and initialises it
2172 ** with the string provided.
2173 **
2174 ** @param [r] str [const AjPStr] String to be cloned
2175 ** @return [AjPStr] Pointer to a string of the specified size
2176 ** containing the supplied text.
2177 **
2178 ** @release 1.0.0
2179 ** @@
2180 ******************************************************************************/
2181
ajStrNewS(const AjPStr str)2182 AjPStr ajStrNewS(const AjPStr str)
2183 {
2184 if(str)
2185 return ajStrNewResLenC(str->Ptr, str->Res, str->Len);
2186
2187 return ajStrNewResLenC("",1,0);
2188 }
2189
2190
2191
2192
2193 /* @func ajStrNewRef **********************************************************
2194 **
2195 ** String referencing function which returns a pointer to the string passed in
2196 ** and increases its reference count.
2197 **
2198 ** Not a true string copy, but if modified the new string will behave
2199 ** as a copy.
2200 **
2201 ** @param [u] refstr [AjPStr] AJAX string object
2202 ** @return [AjPStr] Pointer to the string passed as an argument,
2203 ** with its use count increased by 1.
2204 **
2205 ** @release 4.0.0
2206 ** @@
2207 ******************************************************************************/
2208
ajStrNewRef(AjPStr refstr)2209 AjPStr ajStrNewRef(AjPStr refstr)
2210 {
2211 if(!refstr)
2212 ajFatal("ajStrNewRef source string NULL");
2213
2214 refstr->Use++;
2215
2216 return refstr;
2217 }
2218
2219
2220
2221
2222 /* @func ajStrNewRes **********************************************************
2223 **
2224 ** String constructor which allocates memory for a string of an initial
2225 ** reserved size (including a possible null).
2226 **
2227 ** @param [r] size [size_t] Reserved size (including a possible null).
2228 ** @return [AjPStr] Pointer to an empty string of specified size.
2229 **
2230 ** @release 4.0.0
2231 ** @@
2232 ******************************************************************************/
2233
ajStrNewRes(size_t size)2234 AjPStr ajStrNewRes(size_t size)
2235 {
2236 AjPStr thys;
2237
2238 thys = ajStrNewResLenC("", size, 0);
2239
2240 return thys;
2241 }
2242
2243
2244
2245
2246 /* @func ajStrNewResC *********************************************************
2247 **
2248 ** String constructor which allocates memory for a string of an initial
2249 ** reserved size (including a possible null) and initialises it with the text
2250 ** string provided.
2251 **
2252 ** @param [r] txt [const char*] Null-terminated character string to initialise
2253 ** the new string.
2254 ** @param [r] size [size_t] Reserved size (including a possible null).
2255 ** @return [AjPStr] Pointer to a string of the specified size
2256 ** containing the supplied text.
2257 **
2258 ** @release 4.0.0
2259 ** @@
2260 ******************************************************************************/
2261
ajStrNewResC(const char * txt,size_t size)2262 AjPStr ajStrNewResC(const char* txt, size_t size)
2263 {
2264 size_t i;
2265 AjPStr thys;
2266
2267 i = strlen(txt);
2268
2269 thys = ajStrNewResLenC(txt, size, i);
2270
2271 return thys;
2272 }
2273
2274
2275
2276
2277 /* @func ajStrNewResS *********************************************************
2278 **
2279 ** String constructor which allocates memory for a string of an initial
2280 ** reserved size (including a possible null) and initialises it with the string
2281 ** provided.
2282 **
2283 ** @param [r] str [const AjPStr] String to initialise
2284 ** the new string.
2285 ** @param [r] size [size_t] Reserved size (including a possible null).
2286 ** @return [AjPStr] Pointer to a string of the specified size
2287 ** containing the supplied text.
2288 **
2289 ** @release 4.0.0
2290 ** @@
2291 ******************************************************************************/
2292
ajStrNewResS(const AjPStr str,size_t size)2293 AjPStr ajStrNewResS(const AjPStr str, size_t size)
2294 {
2295 AjPStr thys;
2296
2297 if(str)
2298 thys = ajStrNewResLenC(str->Ptr, size, str->Len);
2299 else
2300 thys = ajStrNewResLenC("", size, 0);
2301
2302 return thys;
2303 }
2304
2305
2306
2307
2308 /* @func ajStrNewResLenC ******************************************************
2309 **
2310 ** String constructor which allocates memory for a string of a given length
2311 ** and of an initial reserved size (including a possible null) and initialises
2312 ** it with the text string provided.
2313 **
2314 ** @param [r] txt [const char*] Null-terminated character string to initialise
2315 ** the new string.
2316 ** @param [r] size [size_t] Reserved size, including a trailing null and
2317 ** possible space for expansion
2318 ** @param [r] len [size_t] Length of txt to save calculation time.
2319 ** @return [AjPStr] Pointer to a string of the specified size
2320 ** containing the supplied text.
2321 **
2322 ** @release 4.0.0
2323 ** @@
2324 ******************************************************************************/
2325
ajStrNewResLenC(const char * txt,size_t size,size_t len)2326 AjPStr ajStrNewResLenC(const char* txt, size_t size, size_t len)
2327 {
2328 AjPStr thys;
2329 size_t minlen;
2330
2331 minlen = size;
2332
2333 if(size <= len)
2334 minlen = len+1;
2335
2336 thys = strNew(minlen);
2337 thys->Len = len;
2338
2339 if(txt && len)
2340 memmove(thys->Ptr, txt, len);
2341
2342 thys->Ptr[len] = '\0';
2343
2344 return thys;
2345 }
2346
2347
2348
2349
2350 /* @funcstatic strClone *******************************************************
2351 **
2352 ** Makes a new clone of a string with a usage count of one and unchanged
2353 ** reserved size.
2354 **
2355 ** @param [w] Pstr [AjPStr*] String
2356 ** @return [AjPStr] New String
2357 **
2358 ** @release 1.0.0
2359 ** @@
2360 ******************************************************************************/
2361
strClone(AjPStr * Pstr)2362 static AjPStr strClone(AjPStr* Pstr)
2363 {
2364 AjPStr thys;
2365 AjPStr ret;
2366
2367 thys = *Pstr;
2368 ret = ajStrNewResLenC(thys->Ptr, thys->Res, thys->Len);
2369
2370 if(thys)
2371 {
2372 if(thys->Use <= 1)
2373 ajStrDel(Pstr);
2374 else
2375 thys->Use--;
2376 }
2377
2378 *Pstr = ret;
2379
2380 return ret;
2381 }
2382
2383
2384
2385
2386 /* @funcstatic strCloneL ******************************************************
2387 **
2388 ** Makes a new clone of a string with a usage count of one and a minimum
2389 ** reserved size.
2390 **
2391 ** @param [w] Pstr [AjPStr*] String
2392 ** @param [r] size [size_t] Minimum reserved size.
2393 ** @return [void]
2394 **
2395 ** @release 1.0.0
2396 ** @@
2397 ******************************************************************************/
2398
strCloneL(AjPStr * Pstr,size_t size)2399 static void strCloneL(AjPStr* Pstr, size_t size)
2400 {
2401 AjPStr thys;
2402 AjPStr ret;
2403
2404 thys = *Pstr;
2405 ret = ajStrNewResLenC(thys->Ptr, size, thys->Len);
2406
2407 if(thys)
2408 {
2409 if(thys->Use <= 1)
2410 ajStrDel(Pstr);
2411 else
2412 thys->Use--;
2413 }
2414
2415 *Pstr = ret;
2416
2417 return;
2418 }
2419
2420
2421
2422
2423 /* @funcstatic strNew *********************************************************
2424 **
2425 ** Internal constructor for modifiable AJAX strings. Used by all the string
2426 ** Parameterised constructors to allocate the space for the text string.
2427 ** The only exception is ajStrNew which returns a clone of the null string.
2428 **
2429 ** @param [rE] size [size_t] size of the reserved space, including the
2430 ** terminating NULL character. Zero uses a default string size STRSIZE.
2431 ** @return [AjPStr] A pointer to an empty string
2432 **
2433 ** @release 4.0.0
2434 ** @@
2435 ******************************************************************************/
2436
strNew(size_t size)2437 static AjPStr strNew(size_t size)
2438 {
2439 AjPStr ret;
2440
2441 if(!size)
2442 size = STRSIZE;
2443 else
2444 size = ajRound(size, 16);
2445
2446 AJNEW0(ret);
2447 ret->Res = size;
2448 ret->Ptr = AJALLOC0(size);
2449 ret->Len = 0;
2450 ret->Use = 1;
2451 ret->Ptr[0] = '\0';
2452
2453 #ifdef AJ_SAVESTATS
2454 strAlloc += size;
2455 strCount++;
2456 strTotal++;
2457 #endif
2458
2459 return ret;
2460 }
2461
2462
2463
2464
2465 /* @section destructors *******************************************************
2466 **
2467 ** Functions for destruction of string objects.
2468 **
2469 ** @fdata [AjPStr]
2470 ** @fnote Return type could be standardised.
2471 **
2472 ** @nam3rule Del Destroy (free) an existing string.
2473 ** @nam3rule Delarray Destroy (free) an array of strings
2474 ** @nam4rule DelStatic Destroy (clear) a string without freeing memory
2475 ** to save reallocation of static string variables
2476 **
2477 ** @argrule Del Pstr [AjPStr*]
2478 ** @argrule Delarray PPstr [AjPStr**]
2479 **
2480 ** @valrule * [void]
2481 ** @valrule *DelStatic [AjBool] True if the string still exists as empty
2482 ** False if the string was reference counted
2483 ** and this instance was deleted
2484 ** @fcategory delete
2485 ******************************************************************************/
2486
2487
2488
2489
2490 /* @macro MAJSTRDEL ***********************************************************
2491 **
2492 ** Default string destructor which frees memory for a string.
2493 **
2494 ** Decrements the use count. When it reaches zero, the string is removed from
2495 ** memory. If the given string is NULL, or a NULL pointer, simply returns.
2496 **
2497 ** A macro version of {ajStrDel} available in case it is needed for speed.
2498 **
2499 ** @param [d] Pstr [AjPStr*] Pointer to the string to be deleted.
2500 ** The pointer is always deleted.
2501 ** @return [void]
2502 ** @@
2503 ******************************************************************************/
2504
2505
2506
2507
2508 /* @func ajStrDel *************************************************************
2509 **
2510 ** Default string destructor which frees memory for a string.
2511 **
2512 ** Decrements the use count. When it reaches zero, the string is removed from
2513 ** memory. If the given string is NULL, or a NULL pointer, simply returns.
2514 **
2515 ** @param [d] Pstr [AjPStr*] Pointer to the string to be deleted.
2516 ** The pointer is always deleted.
2517 ** @return [void]
2518 ** @cre The default null string must not be deleted. Calling this
2519 ** routine for copied pointers could cause this. An error message
2520 ** is issued and the null string use count is restored.
2521 **
2522 ** @release 1.0.0
2523 ** @@
2524 ******************************************************************************/
2525
ajStrDel(AjPStr * Pstr)2526 void ajStrDel(AjPStr* Pstr)
2527 {
2528 AjPStr thys;
2529
2530 if(!Pstr)
2531 return;
2532
2533 if(!*Pstr)
2534 return;
2535
2536 thys = *Pstr;
2537
2538 if(!thys->Use)
2539 ajErr("trying to delete unused string");
2540
2541 --thys->Use;
2542
2543 if(!thys->Use)
2544 { /* any other references? */
2545 if(thys == strPNULL)
2546 {
2547 ajErr("Error - trying to delete the null string constant\n");
2548 thys->Use = NULL_USE; /* restore the original value */
2549 }
2550 else
2551 {
2552 AJFREE(thys->Ptr); /* free the string */
2553
2554 #ifdef AJ_SAVESTATS
2555 strFree += thys->Res;
2556 strFreeCount++;
2557 strCount--;
2558 #endif
2559
2560 thys->Res = 0; /* in case of copied pointers */
2561 thys->Len = 0;
2562
2563 AJFREE(*Pstr); /* free the object */
2564 }
2565 }
2566
2567 *Pstr = NULL;
2568
2569 return;
2570 }
2571
2572
2573
2574
2575 /* @func ajStrDelStatic *******************************************************
2576 **
2577 ** String dereferencing function which sets a string pointer to NULL and
2578 ** decrements the use count of the string to which it referred. Strings with a
2579 ** use count of 1 are *not* freed to avoid freeing and reallocating memory when
2580 ** they are reused.
2581 **
2582 ** Memory reserved for the string is never deleted and can always be
2583 ** reused by any remaining AjPStr that points to it even if this pointer
2584 ** is cleared.
2585 **
2586 ** Use for more efficient memory management for static strings, to avoid
2587 ** reallocation when used in a subsequent call.
2588 **
2589 ** If the given string is NULL, or a NULL pointer, simply returns.
2590 **
2591 ** @param [w] Pstr [AjPStr*] Pointer to the string to be deleted.
2592 ** @return [AjBool] True if the string exists and can be reused
2593 ** False if the string was deleted.
2594 **
2595 ** @release 4.0.0
2596 ** @@
2597 ******************************************************************************/
2598
ajStrDelStatic(AjPStr * Pstr)2599 AjBool ajStrDelStatic(AjPStr* Pstr)
2600 {
2601 AjPStr thys;
2602
2603 if(!*Pstr)
2604 return ajFalse;
2605
2606 thys = *Pstr;
2607
2608 if(thys->Use == 1)
2609 { /* last reference - clear the string */
2610 *thys->Ptr = '\0';
2611 thys->Len = 0;
2612 return ajTrue;
2613 }
2614 else
2615 {
2616 --thys->Use;
2617 *Pstr = NULL;
2618 }
2619
2620 return ajFalse;
2621 }
2622
2623
2624
2625
2626 /* @func ajStrDelarray ********************************************************
2627 **
2628 ** Default string destructor which frees memory for an array of strings.
2629 **
2630 ** Decrements the use count. When it reaches zero, the string is removed from
2631 ** memory. If the given string is NULL, or a NULL pointer, simply returns.
2632 **
2633 ** @param [d] PPstr [AjPStr**] Pointer to the string array to be deleted.
2634 ** The last string is a NULL pointer
2635 ** The pointer is always deleted.
2636 ** @return [void]
2637 ** @cre The default null string must not be deleted. Calling this
2638 ** routine for copied pointers could cause this. An error message
2639 ** is issued and the null string use count is restored.
2640 **
2641 ** @release 4.0.0
2642 ** @@
2643 ******************************************************************************/
2644
ajStrDelarray(AjPStr ** PPstr)2645 void ajStrDelarray(AjPStr** PPstr)
2646 {
2647 ajuint i = 0;
2648
2649 if(!PPstr)
2650 return;
2651
2652 if(!*PPstr)
2653 return;
2654
2655 for(i=0;(*PPstr)[i];i++)
2656 ajStrDel(&(*PPstr)[i]);
2657
2658 AJFREE(*PPstr);
2659
2660 return;
2661 }
2662
2663
2664
2665
2666 /* @section assignment ********************************************************
2667 **
2668 ** Functions for assigning a string.
2669 **
2670 ** @fdata [AjPStr]
2671 ** @fnote Memory for the string is allocated if necessary.
2672 **
2673 ** @nam3rule Assign Assign a string (or substring) either by reference
2674 ** or duplication.
2675 ** @nam4rule AssignRef Copy by setting pointer reference only.
2676 ** @nam4rule AssignSub Copy a substring.
2677 ** @nam4rule AssignRes Copy into string of a reserved size (at least).
2678 ** @nam4rule AssignMax Copy up to a maximum number of characters only.
2679 ** @nam4rule AssignEmpty Copy only if existing string is empty.
2680 ** @nam4rule AssignClear Assign an empty string
2681 **
2682 ** @argrule * Pstr [AjPStr*] Modifiable string
2683 ** @argrule Ref refstr [AjPStr] Master string
2684 ** @argrule Res size [size_t] Reserved maximum size
2685 ** @argrule C txt [const char*] Text string
2686 ** @argrule K chr [char] Single character
2687 ** @argrule S str [const AjPStr] Text string
2688 ** @argrule Len len [size_t] Length of string
2689 ** @argrule Sub pos1 [ajlong] Start position, negative value counts
2690 ** from end
2691 ** @argrule Sub pos2 [ajlong] End position, negative value counts from end
2692 ** @valrule * [AjBool]
2693 **
2694 ** @fcategory assign
2695 */
2696
2697
2698
2699
2700 /* @func ajStrAssignC *********************************************************
2701 **
2702 ** Copy a text string to a string.
2703 **
2704 ** @param [w] Pstr [AjPStr*] Target string.
2705 ** @param [r] txt [const char*] Source text.
2706 ** @return [AjBool] ajTrue if string was reallocated
2707 **
2708 ** @release 4.0.0
2709 ** @@
2710 ******************************************************************************/
2711
ajStrAssignC(AjPStr * Pstr,const char * txt)2712 AjBool ajStrAssignC(AjPStr* Pstr, const char* txt)
2713 {
2714 AjBool ret = ajFalse;
2715 AjPStr thys;
2716 size_t i;
2717 size_t ires;
2718
2719 if(!*Pstr)
2720 {
2721 if(txt)
2722 *Pstr = ajStrNewC(txt);
2723 else
2724 *Pstr = ajStrNew();
2725
2726 return ajTrue;
2727 }
2728
2729 if (!txt)
2730 i = 0;
2731 else
2732 i = strlen(txt);
2733
2734 ires = i+1;
2735
2736 thys = *Pstr;
2737
2738 if(thys->Use != 1 || thys->Res <= i)
2739 {
2740 ret = ajStrSetResRound(Pstr, ires);
2741 thys = *Pstr;
2742 }
2743
2744 thys->Len = i;
2745
2746 if(i)
2747 memmove(thys->Ptr, txt, ires);
2748 else
2749 thys->Ptr[0] = '\0';
2750
2751 return ret;
2752 }
2753
2754
2755
2756
2757 /* @func ajStrAssignK *********************************************************
2758 **
2759 ** Copy a single character to a string.
2760 **
2761 ** @param [w] Pstr [AjPStr*] Target string.
2762 ** @param [r] chr [char] Source text.
2763 ** @return [AjBool] ajTrue if string was reallocated
2764 **
2765 ** @release 4.0.0
2766 ** @@
2767 ******************************************************************************/
2768
ajStrAssignK(AjPStr * Pstr,char chr)2769 AjBool ajStrAssignK(AjPStr* Pstr, char chr)
2770 {
2771 AjBool ret = ajFalse;
2772 AjPStr thys;
2773
2774 if(!*Pstr)
2775 *Pstr=ajStrNewRes(2);
2776
2777 thys = *Pstr;
2778
2779 if(thys->Use != 1 || thys->Res <= 1)
2780 {
2781 ret = ajStrSetRes(Pstr, 2);
2782 thys = *Pstr;
2783 }
2784
2785 thys->Ptr[0] = chr;
2786 thys->Ptr[1] = '\0';
2787 thys->Len = 1;
2788
2789 return ret;
2790 }
2791
2792
2793
2794
2795 /* @func ajStrAssignS *********************************************************
2796 **
2797 ** Copy a string to a string.
2798 **
2799 ** This is a genuine copy (reference count isn't used). Useful where both
2800 ** strings will be separately overwritten later so that they can both remain
2801 ** modifiable.
2802 **
2803 ** @param [w] Pstr [AjPStr*] Target string.
2804 ** @param [rN] str [const AjPStr] Source string.
2805 ** @return [AjBool] ajTrue if string was reallocated
2806 **
2807 ** @release 4.0.0
2808 ** @@
2809 ******************************************************************************/
2810
ajStrAssignS(AjPStr * Pstr,const AjPStr str)2811 AjBool ajStrAssignS(AjPStr* Pstr, const AjPStr str)
2812 {
2813 AjBool ret = ajFalse;
2814 AjPStr thys;
2815 size_t size;
2816 size_t roundsize = STRSIZE;
2817
2818 if(!*Pstr)
2819 {
2820 if(str)
2821 {
2822 size = str->Len + 1;
2823
2824 if(size >= LONGSTR)
2825 roundsize = ajRound(size, LONGSTR);
2826 else
2827 roundsize = ajRound(size, STRSIZE);
2828 }
2829
2830 *Pstr = ajStrNewResS(str,roundsize);
2831
2832 return ajTrue;
2833 }
2834
2835 if(!str)
2836 return ajStrAssignClear(Pstr);
2837
2838 thys = *Pstr;
2839
2840 if(thys->Use != 1 || thys->Res <= str->Len)
2841 {
2842 /* min. reserved size OR more */
2843 ret = ajStrSetResRound(Pstr, str->Len+1);
2844 thys = *Pstr;
2845 }
2846
2847 thys->Len = str->Len;
2848 memmove(thys->Ptr, str->Ptr, str->Len+1);
2849
2850 return ret;
2851 }
2852
2853
2854
2855
2856 /* @func ajStrAssignClear *****************************************************
2857 **
2858 ** Clear the string value
2859 **
2860 ** @param [w] Pstr [AjPStr*] Target string.
2861 ** @return [AjBool] ajTrue if string was reallocated
2862 **
2863 ** @release 6.0.0
2864 ** @@
2865 ******************************************************************************/
2866
ajStrAssignClear(AjPStr * Pstr)2867 AjBool ajStrAssignClear(AjPStr* Pstr)
2868 {
2869 AjBool ret = ajFalse;
2870 AjPStr thys;
2871
2872 if(!*Pstr)
2873 {
2874 *Pstr = strNew(0);
2875
2876 return ajTrue;
2877 }
2878
2879 thys = *Pstr;
2880
2881 if(thys->Use != 1)
2882 {
2883 ajStrGetuniqueStr(Pstr);
2884 thys = *Pstr;
2885 ret = ajTrue;
2886 }
2887
2888 thys->Len = 0;
2889
2890 thys->Ptr[0] = '\0';
2891
2892 return ret;
2893 }
2894
2895
2896
2897
2898 /* @func ajStrAssignEmptyC ****************************************************
2899 **
2900 ** Ensures a string is set (has a value). If the string is set it is left
2901 ** alone, otherwise it is initialised with a text string.
2902 **
2903 ** @param [w] Pstr [AjPStr*] Target string which is overwritten.
2904 ** @param [r] txt [const char*] Source text.
2905 ** @return [AjBool] ajTrue if string was reallocated
2906 **
2907 ** @release 4.0.0
2908 ** @@
2909 ******************************************************************************/
2910
ajStrAssignEmptyC(AjPStr * Pstr,const char * txt)2911 AjBool ajStrAssignEmptyC(AjPStr* Pstr, const char* txt)
2912 {
2913 AjBool ret = ajFalse;
2914
2915 if(!*Pstr)
2916 ret = ajStrAssignC(Pstr, txt);
2917 else if(!(*Pstr)->Len)
2918 ret = ajStrAssignC(Pstr, txt);
2919
2920 return ret;
2921 }
2922
2923
2924
2925
2926 /* @func ajStrAssignEmptyS ****************************************************
2927 **
2928 ** Ensures a string is set (has a value). If the string is set it is left
2929 ** alone, otherwise it is initialised with a string.
2930 **
2931 ** @param [w] Pstr [AjPStr*] Target string which is overwritten.
2932 ** @param [r] str [const AjPStr] Source string object.
2933 ** @return [AjBool] ajTrue if string was reallocated
2934 **
2935 ** @release 4.0.0
2936 ** @@
2937 ******************************************************************************/
2938
ajStrAssignEmptyS(AjPStr * Pstr,const AjPStr str)2939 AjBool ajStrAssignEmptyS(AjPStr* Pstr, const AjPStr str)
2940 {
2941 AjBool ret = ajFalse; /* true if ajStrDup is used */
2942
2943 if(!*Pstr)
2944 ret = ajStrAssignS(Pstr, str);
2945 else if(!(*Pstr)->Len)
2946 ret = ajStrAssignS(Pstr, str);
2947
2948 return ret;
2949 }
2950
2951
2952
2953
2954 /* @func ajStrAssignLenC ******************************************************
2955 **
2956 ** Copy a text string of a given length to a string.
2957 **
2958 ** @param [w] Pstr [AjPStr*] Target string.
2959 ** @param [rN] txt [const char*] Source text.
2960 ** @param [r] len [size_t] Length of source text.
2961 ** @return [AjBool] ajTrue if string was reallocated
2962 **
2963 ** @release 4.0.0
2964 ** @@
2965 ******************************************************************************/
2966
ajStrAssignLenC(AjPStr * Pstr,const char * txt,size_t len)2967 AjBool ajStrAssignLenC(AjPStr* Pstr, const char* txt, size_t len)
2968 {
2969 AjBool ret = ajFalse;
2970 AjPStr thys;
2971
2972 if (!txt)
2973 ajFatal("ajStrAssignLenC source text NULL");
2974
2975 thys = *Pstr;
2976
2977 if(!thys)
2978 {
2979 ret = ajStrSetResRound(Pstr, len+1);
2980 thys = *Pstr;
2981 }
2982 else if(thys->Res < len+1)
2983 {
2984 ret = ajStrSetResRound(Pstr, len+1);
2985 thys = *Pstr;
2986 }
2987
2988 thys->Len = len;
2989
2990 if (len)
2991 memmove(thys->Ptr, txt, len);
2992
2993 thys->Ptr[len] = '\0';
2994
2995 return ret;
2996 }
2997
2998
2999
3000
3001 /* @func ajStrAssignRef *******************************************************
3002 **
3003 ** String referencing function which makes a string point to another.
3004 ** Increases the reference count of the string pointed to.
3005 **
3006 ** Not a true string copy, but if modified the new string will behave
3007 ** as a copy.
3008 **
3009 ** Sets the destination string to NULL if the source string is NULL.
3010 **
3011 ** @param [w] Pstr [AjPStr*] Target string which is overwritten.
3012 ** @param [u] refstr [AjPStr] Source string object
3013 ** Copy by reference count so not const.
3014 ** @return [AjBool] ajTrue if string was reallocated
3015 ** @cre If both arguments point to the same string object, nothing happens.
3016 **
3017 ** @release 4.0.0
3018 ** @@
3019 ******************************************************************************/
3020
ajStrAssignRef(AjPStr * Pstr,AjPStr refstr)3021 AjBool ajStrAssignRef(AjPStr* Pstr, AjPStr refstr)
3022 {
3023 AjBool ret = ajTrue; /* true if ajStrNewRef is used */
3024
3025 if(*Pstr)
3026 {
3027 if((*Pstr)->Use <= 1)
3028 ajStrDel(Pstr);
3029 else
3030 (*Pstr)->Use--;
3031 }
3032
3033 if(!refstr)
3034 *Pstr = ajStrNewRef(strPNULL);
3035 else
3036 *Pstr = ajStrNewRef(refstr);
3037
3038 return ret;
3039 }
3040
3041
3042
3043
3044 /* @func ajStrAssignResC ******************************************************
3045 **
3046 ** Copy a text string to a string with a minimum reserved size.
3047 **
3048 ** @param [w] Pstr [AjPStr*] Target string.
3049 ** @param [r] size [size_t] Space to reserve.
3050 ** @param [r] txt [const char*] Source text.
3051 ** @return [AjBool] ajTrue if string was reallocated
3052 **
3053 ** @release 4.0.0
3054 ** @@
3055 ******************************************************************************/
3056
ajStrAssignResC(AjPStr * Pstr,size_t size,const char * txt)3057 AjBool ajStrAssignResC(AjPStr* Pstr, size_t size, const char* txt)
3058 {
3059 AjBool ret = ajFalse;
3060 AjPStr thys;
3061 size_t ilen;
3062 size_t isize;
3063
3064 if (txt)
3065 ilen = strlen(txt);
3066 else
3067 ilen = 0;
3068
3069 isize = size;
3070
3071 if(ilen >= isize)
3072 isize = ilen + 1;
3073
3074 ret = ajStrSetResRound(Pstr, isize);
3075 thys = *Pstr;
3076
3077 thys->Len = ilen;
3078
3079 if(ilen)
3080 memmove(thys->Ptr, txt, ilen);
3081
3082 thys->Ptr[ilen] = '\0';
3083
3084 return ret;
3085 }
3086
3087
3088
3089
3090 /* @func ajStrAssignResS ******************************************************
3091 **
3092 ** Copy a string to a string with a minimum reserved size.
3093 **
3094 ** @param [w] Pstr [AjPStr*] Target string.
3095 ** @param [r] size [size_t] Size of new string.
3096 ** @param [rN] str [const AjPStr] Source text.
3097 ** @return [AjBool] ajTrue if string was reallocated
3098 **
3099 ** @release 4.0.0
3100 ** @@
3101 ******************************************************************************/
3102
ajStrAssignResS(AjPStr * Pstr,size_t size,const AjPStr str)3103 AjBool ajStrAssignResS(AjPStr* Pstr, size_t size, const AjPStr str)
3104 {
3105 AjBool ret = ajFalse;
3106 AjPStr thys;
3107 size_t isize;
3108
3109 isize = size;
3110
3111 if (str)
3112 {
3113 if(isize <= str->Len)
3114 isize = str->Len+1;
3115 }
3116
3117 ret = ajStrSetResRound(Pstr, isize);
3118 thys = *Pstr;
3119
3120 if (str)
3121 {
3122 thys->Len = str->Len;
3123 memmove(thys->Ptr, str->Ptr, str->Len);
3124 thys->Ptr[str->Len] = '\0';
3125 }
3126 else
3127 {
3128 thys->Len = 0;
3129 thys->Ptr[0] = '\0';
3130 }
3131
3132 return ret;
3133 }
3134
3135
3136
3137
3138 /* @func ajStrAssignSubC ******************************************************
3139 **
3140 ** Copies a substring of a text string to a string.
3141 **
3142 ** @param [w] Pstr [AjPStr*] Target string
3143 ** @param [r] txt [const char*] Source text
3144 ** @param [r] pos1 [ajlong] start position for substring
3145 ** @param [r] pos2 [ajlong] end position for substring
3146 ** @return [AjBool] ajTrue if string was reallocated
3147 **
3148 ** @release 4.0.0
3149 ** @@
3150 ******************************************************************************/
3151
ajStrAssignSubC(AjPStr * Pstr,const char * txt,ajlong pos1,ajlong pos2)3152 AjBool ajStrAssignSubC(AjPStr* Pstr, const char* txt, ajlong pos1, ajlong pos2)
3153 {
3154 AjBool ret = ajFalse;
3155 size_t ilen;
3156 size_t ibegin;
3157 size_t iend;
3158 AjPStr thys;
3159
3160 ibegin = (size_t) pos1;
3161 iend = (size_t) pos2;
3162
3163 if(pos1 < 0)
3164 ibegin = strlen(txt) + (size_t) pos1;
3165
3166 if(pos2 < 0)
3167 iend = strlen(txt) + (size_t) pos2;
3168
3169 ilen = iend - ibegin + 1;
3170
3171 if(!*Pstr)
3172 {
3173 ret = ajTrue;
3174 ret = ajStrSetResRound(Pstr, ilen+1);
3175 }
3176 else if((*Pstr)->Use > 1)
3177 {
3178 ret = ajTrue;
3179 ajStrGetuniqueStr(Pstr);
3180 }
3181
3182 if((*Pstr)->Res < ilen+1)
3183 ret = ajStrSetResRound(Pstr, ilen+1);
3184
3185 thys = *Pstr;
3186
3187 thys->Len = ilen;
3188
3189 if (ilen)
3190 memmove(thys->Ptr, &txt[ibegin], ilen);
3191
3192 thys->Ptr[ilen] = '\0';
3193
3194 return ret;
3195 }
3196
3197
3198
3199
3200 /* @func ajStrAssignSubS ******************************************************
3201 **
3202 ** Copies a substring of a string to a string.
3203 **
3204 ** The substring is defined from character positions pos1 to pos2.
3205 **
3206 ** ajTrue is returned if target was
3207 ** (re)allocated, ajFalse is returned otherwise.
3208 **
3209 ** @short Copies a substring of a string to a string.
3210 **
3211 ** @param [w] Pstr [AjPStr*] Target string
3212 ** {memory will be automatically allocated if required}
3213 ** @param [r] str [const AjPStr] Source string
3214 ** @param [r] pos1 [ajlong] Start position in src of substring
3215 ** {negative values count from the end of the string
3216 ** with -1 as the last position}
3217 ** @param [r] pos2 [ajlong] End position in src of substring
3218 ** {negative values count from the end of the string
3219 ** with -1 as the last position}
3220 ** @return [AjBool] ajTrue if Pstr was (re)allocated, ajFalse otherwise
3221 ** @release 1.0.0
3222 ** @@
3223 ******************************************************************************/
3224
ajStrAssignSubS(AjPStr * Pstr,const AjPStr str,ajlong pos1,ajlong pos2)3225 AjBool ajStrAssignSubS(AjPStr* Pstr, const AjPStr str,
3226 ajlong pos1, ajlong pos2)
3227 {
3228 AjBool ret = ajFalse;
3229 size_t ilen;
3230 size_t ibegin;
3231 size_t iend;
3232 AjPStr thys;
3233
3234 ibegin = ajCvtSposToPos(str->Len, pos1);
3235 iend = ajCvtSposToPosStart(str->Len, ibegin, pos2);
3236
3237 if(iend == str->Len)
3238 iend--;
3239
3240 ilen = iend - ibegin + 1;
3241
3242 if(!*Pstr)
3243 {
3244 ret = ajTrue;
3245 ret = ajStrSetResRound(Pstr, ilen+1);
3246 }
3247 else if((*Pstr)->Use > 1)
3248 {
3249 ret = ajTrue;
3250 ajStrGetuniqueStr(Pstr);
3251 }
3252
3253 if((*Pstr)->Res < ilen+1)
3254 ret = ajStrSetResRound(Pstr, ilen+1);
3255
3256 thys = *Pstr;
3257
3258 thys->Len = ilen;
3259
3260 if (ilen)
3261 memmove(thys->Ptr, &str->Ptr[ibegin], ilen);
3262
3263 thys->Ptr[ilen] = '\0';
3264
3265 return ret;
3266 }
3267
3268
3269
3270
3271 /* @section combination functions *********************************************
3272 **
3273 ** Functions for appending, inserting or overwriting a string
3274 ** or substring to another.
3275 **
3276 ** @fdata [AjPStr]
3277 ** @fnote Memory for the object is allocated if necessary
3278 **
3279 ** @nam3rule Append Append one string to another.
3280 ** @nam4rule AppendSub Append substring.
3281 ** @nam4rule AppendCount Append number of characters.
3282 ** @nam3rule Join Append one string to another after cutting strings.
3283 ** @nam3rule Insert Insert one string into another.
3284 ** @nam3rule Paste Overwrite one string with another.
3285 ** @nam4rule PasteCount Overwrite with a number of single characters
3286 ** @nam4rule PasteMax Length of overwrite string specified
3287 ** @nam3rule Mask Mask characters.
3288 ** @nam4rule MaskIdent Mask matching characters.
3289 ** @nam4rule MaskRange Mask a range of characters.
3290 **
3291 ** @argrule * Pstr [AjPStr*] Modifiable string
3292 ** @argrule Insert pos [ajlong] Position in string to start inserting,
3293 ** negative values count from the end
3294 ** @argrule Paste pos [ajlong] Position in string to start inserting,
3295 ** negative values count from the end
3296 ** @argrule Join pos [ajlong] Position in string to start inserting,
3297 ** negative values count from the end
3298 ** @argrule C txt [const char*] Text string
3299 ** @argrule K chr [char] Single character
3300 ** @argrule S str [const AjPStr] Text string
3301 ** @argrule Count num [ajulong] Number of single characters to copy
3302 ** @argrule Len len [size_t] Number of characters to copy from string
3303 ** @argrule Max len [size_t] Length of string
3304 ** @argrule Sub pos1 [ajlong] Start position,
3305 ** negative value counts from end
3306 ** @argrule MaskRange pos1 [ajlong] Start position,
3307 ** negative value counts from end
3308 ** @argrule Sub pos2 [ajlong] End position,
3309 ** negative value counts from end
3310 ** @argrule MaskRange pos2 [ajlong] End position,
3311 ** negative value counts from end
3312 ** @argrule Join posb [ajlong] Position in source string
3313 ** negative values count from the end
3314 ** @argrule MaskIdent str [const AjPStr] Comparison master string
3315 ** @argrule Mask maskchr [char] Masking character
3316 **
3317 ** @valrule * [AjBool]
3318 **
3319 ** @fcategory modify
3320 ** @@
3321 */
3322
3323
3324
3325
3326 /* @func ajStrAppendC *********************************************************
3327 **
3328 ** Appends a text string to the end of a string.
3329 **
3330 ** Uses {ajStrSetRes} to make sure target string is modifiable.
3331 **
3332 ** @param [w] Pstr [AjPStr*] Target string
3333 ** @param [r] txt [const char*] Source text
3334 ** @return [AjBool] ajTrue if string was reallocated
3335 **
3336 ** @release 4.0.0
3337 ** @@
3338 ******************************************************************************/
3339
ajStrAppendC(AjPStr * Pstr,const char * txt)3340 AjBool ajStrAppendC(AjPStr* Pstr, const char* txt)
3341 {
3342 size_t i;
3343
3344 i = strlen(txt);
3345
3346 return ajStrAppendLenC(Pstr, txt, i);
3347 }
3348
3349
3350
3351
3352 /* @func ajStrAppendK *********************************************************
3353 **
3354 ** Appends a character to the end of a string.
3355 **
3356 ** Uses {ajStrSetRes} to make sure target string is modifiable.
3357 **
3358 ** @param [w] Pstr [AjPStr*] Target string
3359 ** @param [rN] chr [char] Source character
3360 ** @return [AjBool] ajTrue if string was reallocated
3361 **
3362 ** @release 4.0.0
3363 ** @@
3364 ******************************************************************************/
3365
ajStrAppendK(AjPStr * Pstr,char chr)3366 AjBool ajStrAppendK(AjPStr* Pstr, char chr)
3367 {
3368 AjBool ret = ajFalse;
3369 AjPStr thys;
3370 size_t j;
3371
3372 thys = *Pstr;
3373
3374 if(thys)
3375 j = AJMAX(thys->Res, thys->Len+2);
3376 else
3377 j = 2;
3378
3379 ret = ajStrSetResRound(Pstr, j);
3380 thys = *Pstr; /* possible new location */
3381
3382 thys->Ptr[thys->Len] = chr;
3383 thys->Ptr[++thys->Len] = '\0';
3384
3385 return ret;
3386 }
3387
3388
3389
3390
3391 /* @func ajStrAppendS *********************************************************
3392 **
3393 ** Appends a string to the end of another string.
3394 **
3395 ** Uses {ajStrSetResRound} to make sure target string is modifiable.
3396 **
3397 ** @param [w] Pstr [AjPStr*] Target string
3398 ** @param [r] str [const AjPStr] Source string
3399 ** @return [AjBool] ajTrue if string was reallocated
3400 **
3401 ** @release 4.0.0
3402 ** @@
3403 ******************************************************************************/
3404
ajStrAppendS(AjPStr * Pstr,const AjPStr str)3405 AjBool ajStrAppendS(AjPStr* Pstr, const AjPStr str)
3406 {
3407 AjBool ret = ajFalse;
3408
3409 AjPStr thys;
3410 size_t j;
3411
3412 if(!str)
3413 return ajFalse;
3414
3415 thys = *Pstr;
3416
3417 if(thys)
3418 {
3419 j = AJMAX(thys->Res, thys->Len+str->Len+1);
3420 }
3421 else
3422 j = str->Len+1;
3423
3424 ret = ajStrSetResRound(Pstr, j);
3425 thys = *Pstr; /* possible new location */
3426
3427 memmove(thys->Ptr+thys->Len, str->Ptr, str->Len+1); /* include the null */
3428 thys->Len += str->Len;
3429
3430 return ret;
3431 }
3432
3433
3434
3435
3436 /* @func ajStrAppendCountK ****************************************************
3437 **
3438 ** Appends any number of a given character to the end of a string.
3439 **
3440 ** Equivalent to a repeat count for ajStrAppK.
3441 **
3442 ** Uses {ajStrSetRes} to make sure target string is modifiable.
3443 **
3444 ** @param [w] Pstr [AjPStr*] Target string
3445 ** @param [r] chr [char] Source character
3446 ** @param [r] num [ajulong] Repeat count
3447 ** @return [AjBool] ajTrue if string was reallocated
3448 **
3449 ** @release 4.0.0
3450 ** @@
3451 ******************************************************************************/
3452
ajStrAppendCountK(AjPStr * Pstr,char chr,ajulong num)3453 AjBool ajStrAppendCountK(AjPStr* Pstr, char chr, ajulong num)
3454 {
3455 AjBool ret = ajFalse;
3456 AjPStr thys;
3457 size_t i;
3458 size_t j;
3459 char* cp;
3460 size_t snum;
3461
3462 thys = *Pstr;
3463
3464 snum = (size_t) num;
3465
3466 if(thys)
3467 j = AJMAX(thys->Res, (thys->Len+snum+1));
3468 else
3469 j = snum+1;
3470
3471 ret = ajStrSetResRound(Pstr, j);
3472 thys = *Pstr; /* possible new location */
3473
3474 cp = &thys->Ptr[thys->Len];
3475
3476 for(i=0; i<num; i++)
3477 {
3478 *cp++ = chr;
3479 }
3480
3481 *cp = '\0';
3482 thys->Len += snum;
3483
3484 return ret;
3485 }
3486
3487
3488
3489
3490 /* @func ajStrAppendLenC ******************************************************
3491 **
3492 ** Appends a text string of a given length to the end of a string.
3493 **
3494 ** Uses {ajStrSetRes} to make sure target string is modifiable.
3495 **
3496 ** @param [w] Pstr [AjPStr*] Target string
3497 ** @param [rN] txt [const char*] Source text
3498 ** @param [r] len [size_t] String length
3499 ** @return [AjBool] ajTrue if string was reallocated
3500 **
3501 ** @release 4.0.0
3502 ** @@
3503 ******************************************************************************/
3504
ajStrAppendLenC(AjPStr * Pstr,const char * txt,size_t len)3505 AjBool ajStrAppendLenC(AjPStr* Pstr, const char* txt, size_t len)
3506 {
3507 AjBool ret = ajFalse;
3508
3509 AjPStr thys;
3510 size_t j;
3511
3512 thys = *Pstr;
3513
3514 if(!txt)
3515 return ajFalse;
3516
3517 if(*Pstr)
3518 j = AJMAX(thys->Res, (thys->Len+len+1));
3519 else
3520 j = len+1;
3521
3522 ret = ajStrSetResRound(Pstr, j);
3523 thys = *Pstr; /* possible new location */
3524
3525 if(len)
3526 memmove(thys->Ptr+thys->Len, txt, len);
3527
3528 thys->Len += len;
3529
3530 thys->Ptr[thys->Len] = '\0';
3531
3532 return ret;
3533 }
3534
3535
3536
3537
3538 /* @func ajStrAppendSubC ******************************************************
3539 **
3540 ** Appends a substring of a string to the end of another string.
3541 **
3542 ** @param [w] Pstr [AjPStr*] Target string
3543 ** @param [r] txt [const char*] Source string
3544 ** @param [r] pos1 [ajlong] start position for substring
3545 ** @param [r] pos2 [ajlong] end position for substring
3546 ** @return [AjBool] ajTrue if string was reallocated
3547 **
3548 ** @release 6.0.0
3549 ** @@
3550 ******************************************************************************/
3551
ajStrAppendSubC(AjPStr * Pstr,const char * txt,ajlong pos1,ajlong pos2)3552 AjBool ajStrAppendSubC(AjPStr* Pstr, const char* txt, ajlong pos1, ajlong pos2)
3553 {
3554 size_t ilen;
3555 size_t jlen;
3556 size_t ibegin;
3557 size_t iend;
3558 AjBool ret = ajFalse;
3559
3560 AjPStr thys;
3561 size_t j;
3562
3563 thys = *Pstr;
3564
3565 jlen = strlen(txt);
3566 ibegin = ajCvtSposToPosStart(jlen, 0, pos1);
3567 iend = ajCvtSposToPosStart(jlen, ibegin, pos2);
3568
3569 ilen = iend - ibegin + 1;
3570
3571 if(thys)
3572 j = AJMAX(thys->Res, thys->Len+ilen+1);
3573 else
3574 j = ilen+1;
3575
3576 ret = ajStrSetResRound(Pstr, j);
3577 thys = *Pstr; /* possible new location */
3578
3579 if(ilen)
3580 memmove(thys->Ptr+thys->Len, &txt[ibegin], ilen);
3581
3582 thys->Len += ilen;
3583
3584 thys->Ptr[thys->Len] = '\0';
3585
3586 return ret;
3587 }
3588
3589
3590
3591
3592 /* @func ajStrAppendSubS ******************************************************
3593 **
3594 ** Appends a substring of a string to the end of another string.
3595 **
3596 ** Uses {ajStrSetRes} to make sure target string is modifiable.
3597 **
3598 ** @param [w] Pstr [AjPStr*] Target string
3599 ** @param [r] str [const AjPStr] Source string
3600 ** @param [r] pos1 [ajlong] start position for substring
3601 ** @param [r] pos2 [ajlong] end position for substring
3602 ** @return [AjBool] ajTrue if string was reallocated
3603 **
3604 ** @release 4.0.0
3605 ** @@
3606 ******************************************************************************/
3607
ajStrAppendSubS(AjPStr * Pstr,const AjPStr str,ajlong pos1,ajlong pos2)3608 AjBool ajStrAppendSubS(AjPStr* Pstr, const AjPStr str, ajlong pos1, ajlong pos2)
3609 {
3610 size_t ilen;
3611 size_t ibegin;
3612 size_t iend;
3613 AjBool ret = ajFalse;
3614
3615 AjPStr thys;
3616 size_t j;
3617
3618 thys = *Pstr;
3619
3620 ibegin = ajCvtSposToPosStart(str->Len, 0, pos1);
3621 iend = ajCvtSposToPosStart(str->Len, ibegin, pos2);
3622
3623 ilen = iend - ibegin + 1;
3624
3625 if(thys)
3626 j = AJMAX(thys->Res, thys->Len+ilen+1);
3627 else
3628 j = ilen+1;
3629
3630 ret = ajStrSetResRound(Pstr, j);
3631 thys = *Pstr; /* possible new location */
3632
3633 if(ilen)
3634 memmove(thys->Ptr+thys->Len, &str->Ptr[ibegin], ilen);
3635
3636 thys->Len += ilen;
3637
3638 thys->Ptr[thys->Len] = '\0';
3639
3640 return ret;
3641 }
3642
3643
3644
3645
3646 /* @func ajStrInsertC *********************************************************
3647 **
3648 ** Insert a text string into a string at a specified position.
3649 **
3650 ** @param [u] Pstr [AjPStr*] Target string
3651 ** @param [r] pos [ajlong] Position where text is to be inserted.
3652 ** Negative position counts from the end
3653 ** @param [r] txt [const char*] Text to be inserted
3654 ** @return [AjBool] ajTrue if string was reallocated
3655 **
3656 ** @release 1.0.0
3657 ** @@
3658 ******************************************************************************/
3659
ajStrInsertC(AjPStr * Pstr,ajlong pos,const char * txt)3660 AjBool ajStrInsertC(AjPStr* Pstr, ajlong pos, const char* txt )
3661 {
3662 AjBool ret = ajFalse;
3663 AjPStr thys;
3664 size_t j = 0;
3665 size_t y = 0;
3666 size_t ibegin;
3667 char* ptr1;
3668 const char* ptr2;
3669 size_t len;
3670
3671 len = strlen(txt);
3672
3673 thys = *Pstr;
3674
3675 if(!thys)
3676 {
3677 ajStrAssignResC(Pstr, len+1, "");
3678 thys = *Pstr;
3679 }
3680
3681 /* can be at start or after end */
3682 ibegin = ajCvtSposToPosStart(thys->Len+1, 0, pos);
3683
3684 j = thys->Len+len+1;
3685
3686 if(j > thys->Res)
3687 ret = ajStrSetResRound(Pstr, j);
3688 else
3689 {
3690 if(thys->Use > 1)
3691 {
3692 ajStrGetuniqueStr(Pstr);
3693 ret = ajTrue;
3694 }
3695 }
3696
3697 thys = *Pstr; /* possible new location */
3698
3699 /* move characters "i" places up to leave place for insertion */
3700 ptr1 = &thys->Ptr[thys->Len+len];
3701 ptr2 = &thys->Ptr[thys->Len];
3702
3703 for(y=0; y<=thys->Len-ibegin ; y++)
3704 {
3705 *ptr1 = *ptr2;
3706 ptr1--;
3707 ptr2--;
3708 }
3709
3710 thys->Len += len; /* set the new length */
3711 thys->Ptr[thys->Len] = '\0'; /* ### was Len+1 ### add the
3712 end character */
3713
3714 /* add the new text */
3715 ptr1 = & thys->Ptr[ibegin];
3716 ptr2 = txt;
3717
3718 for(y=0; y< len; y++)
3719 {
3720 *ptr1 = *ptr2;
3721 ptr1++;
3722 ptr2++;
3723 }
3724
3725 return ret;
3726 }
3727
3728
3729
3730
3731 /* @func ajStrInsertK *********************************************************
3732 **
3733 ** Inserts a character into a string at a specified position.
3734 **
3735 ** @param [u] Pstr [AjPStr*] Target string
3736 ** @param [r] pos [ajlong] Position where text is to be inserted.
3737 ** Negative position counts from the end
3738 ** @param [r] chr [char] Text to be inserted
3739 ** @return [AjBool] ajTrue if string was reallocated
3740 **
3741 ** @release 2.9.0
3742 ** @@
3743 ******************************************************************************/
3744
ajStrInsertK(AjPStr * Pstr,ajlong pos,char chr)3745 AjBool ajStrInsertK(AjPStr* Pstr, ajlong pos, char chr )
3746 {
3747 char tmpstr[2] = "?";
3748 *tmpstr = chr;
3749
3750 return ajStrInsertC(Pstr, pos, tmpstr);
3751 }
3752
3753
3754
3755
3756 /* @func ajStrInsertS *********************************************************
3757 **
3758 ** Inserts a text string into a string at a specified position.
3759 **
3760 ** @param [u] Pstr [AjPStr*] Target string
3761 ** @param [r] pos [ajlong] Position where text is to be inserted.
3762 ** Negative position counts from the end
3763 ** @param [r] str [const AjPStr] String to be inserted
3764 ** @return [AjBool] ajTrue on successful completion else ajFalse;
3765 ** @error ajFalse if the insert failed. Currently this happens if
3766 ** pos is negative, but this could be reassigned to a position
3767 ** from the end of the string in future.
3768 **
3769 ** @release 4.0.0
3770 ** @@
3771 ******************************************************************************/
3772
ajStrInsertS(AjPStr * Pstr,ajlong pos,const AjPStr str)3773 AjBool ajStrInsertS(AjPStr* Pstr, ajlong pos, const AjPStr str)
3774 {
3775 return ajStrInsertC(Pstr, pos, str->Ptr);
3776 }
3777
3778
3779
3780
3781 /* @func ajStrJoinC ***********************************************************
3782 **
3783 ** Cut down string at pos1 and add string2 from position pos2.
3784 **
3785 ** @param [u] Pstr [AjPStr*] Target string.
3786 ** @param [r] pos [ajlong] Number of characters to keep in target string.
3787 ** @param [r] txt [const char*] Text to append.
3788 ** @param [r] posb [ajlong] Position of first character to copy from text.
3789 ** @return [AjBool] ajTrue on success
3790 **
3791 ** @release 1.0.0
3792 ** @@
3793 ******************************************************************************/
3794
ajStrJoinC(AjPStr * Pstr,ajlong pos,const char * txt,ajlong posb)3795 AjBool ajStrJoinC(AjPStr* Pstr, ajlong pos, const char* txt,
3796 ajlong posb)
3797 {
3798 AjPStr thys;
3799 size_t len;
3800 size_t ibegin;
3801 size_t ibegin2;
3802 size_t i = 0;
3803 size_t j = 0;
3804 size_t newlen = 0;
3805
3806 len = strlen(txt);
3807
3808 if(!*Pstr)
3809 *Pstr = ajStrNewResLenC("", 1, 0);
3810 else if((*Pstr)->Use > 1)
3811 ajStrGetuniqueStr(Pstr);
3812 thys = *Pstr;
3813
3814 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos);
3815 ibegin2 = ajCvtSposToPosStart(len, 0, posb);
3816
3817 if(thys->Len < ibegin || len < ibegin2)
3818 return ajFalse;
3819
3820 newlen = ibegin + len - ibegin2 + 1;
3821
3822 if(newlen > thys->Res)
3823 {
3824 ajStrSetResRound(Pstr, newlen);
3825 thys = *Pstr;
3826 }
3827
3828 for(i=ibegin,j=ibegin2; j <= len; i++,j++)
3829 thys->Ptr[i] = txt[j];
3830
3831 thys->Len = i-1;
3832
3833 return ajTrue;
3834 }
3835
3836
3837
3838
3839 /* @func ajStrJoinS ***********************************************************
3840 **
3841 ** Appends one string to another after cutting both strings.
3842 **
3843 ** Cuts down string at pos1 and add string2 from position pos2.
3844 **
3845 ** @param [u] Pstr [AjPStr*] Target string.
3846 ** @param [r] pos [ajlong] Start position in target string,
3847 ** negative numbers count from the end.
3848 ** @param [r] str [const AjPStr] String to append.
3849 ** @param [r] posb [ajlong] Starts position to copy,
3850 ** negative numbers count from the end.
3851 ** @return [AjBool] ajTrue on success.
3852 **
3853 ** @release 4.0.0
3854 ** @@
3855 ******************************************************************************/
3856
ajStrJoinS(AjPStr * Pstr,ajlong pos,const AjPStr str,ajlong posb)3857 AjBool ajStrJoinS(AjPStr* Pstr, ajlong pos, const AjPStr str,
3858 ajlong posb)
3859 {
3860 size_t ibegin1;
3861 size_t ibegin2;
3862
3863 ibegin1 = ajCvtSposToPosStart((*Pstr)->Len, 0, pos);
3864 ibegin2 = ajCvtSposToPosStart(str->Len, 0, posb);
3865
3866 return ajStrJoinC(Pstr, ibegin1, str->Ptr, ibegin2);
3867 }
3868
3869
3870
3871
3872 /* @func ajStrMaskIdent *******************************************************
3873 **
3874 ** Masks out characters from a string that are identical to a second string.
3875 **
3876 ** @param [w] Pstr [AjPStr*] Target string
3877 ** @param [r] str [const AjPStr] Comparison string
3878 ** @param [r] maskchr [char] masking character
3879 ** @return [AjBool] ajTrue on success
3880 **
3881 ** @release 6.1.0
3882 ** @@
3883 ******************************************************************************/
3884
ajStrMaskIdent(AjPStr * Pstr,const AjPStr str,char maskchr)3885 AjBool ajStrMaskIdent(AjPStr* Pstr, const AjPStr str, char maskchr)
3886 {
3887 char *cp;
3888 const char* cq;
3889
3890 cp = ajStrGetuniquePtr(Pstr);
3891 cq = str->Ptr;
3892
3893 while(*cq)
3894 {
3895 if(!*cp)
3896 return ajFalse;
3897
3898 if(*cp == *cq)
3899 *cp = maskchr;
3900
3901 cp++;
3902 cq++;
3903 }
3904
3905 if(*cp)
3906 return ajFalse;
3907
3908 return ajTrue;
3909 }
3910
3911
3912
3913
3914 /* @func ajStrMaskRange *******************************************************
3915 **
3916 ** Masks out characters from a string over a specified range.
3917 **
3918 ** @param [w] Pstr [AjPStr*] Target string
3919 ** @param [r] pos1 [ajlong] start position to be masked
3920 ** @param [r] pos2 [ajlong] end position to be masked
3921 ** @param [r] maskchr [char] masking character
3922 ** @return [AjBool] ajTrue on success, ajFalse if begin is out of range
3923 **
3924 ** @release 6.1.0
3925 ** @@
3926 ******************************************************************************/
3927
ajStrMaskRange(AjPStr * Pstr,ajlong pos1,ajlong pos2,char maskchr)3928 AjBool ajStrMaskRange(AjPStr* Pstr, ajlong pos1, ajlong pos2, char maskchr)
3929 {
3930 AjPStr thys;
3931 size_t ibegin;
3932 size_t iend;
3933 size_t i;
3934
3935 if(!*Pstr)
3936 *Pstr = ajStrNewResLenC("", 1, 0);
3937 else if((*Pstr)->Use > 1)
3938 ajStrGetuniqueStr(Pstr);
3939
3940 thys = *Pstr;
3941
3942 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos1);
3943 iend = ajCvtSposToPosStart(thys->Len, ibegin, pos2);
3944
3945 /*
3946 ajDebug("ajStrMask %d %d len: %d ibegin: %d iend: %d char '%c'\n",
3947 begin, end, thys->Len, ibegin, iend, maskchar);
3948 */
3949
3950 if(iend < ibegin)
3951 return ajFalse;
3952
3953 for(i=ibegin; i<=iend; i++)
3954 thys->Ptr[i] = maskchr;
3955
3956 return ajTrue;
3957 }
3958
3959
3960
3961
3962 /* @func ajStrPasteS **********************************************************
3963 **
3964 ** Overwrite one string with another.
3965 **
3966 ** Replace string at pos1 with new string.
3967 **
3968 ** @param [u] Pstr [AjPStr*] Target string
3969 ** @param [r] pos [ajlong] Position in target string
3970 ** @param [r] str [const AjPStr] String to replace.
3971 ** @return [AjBool] ajTrue on success
3972 **
3973 ** @release 4.0.0
3974 ** @@
3975 ******************************************************************************/
3976
ajStrPasteS(AjPStr * Pstr,ajlong pos,const AjPStr str)3977 AjBool ajStrPasteS(AjPStr* Pstr, ajlong pos, const AjPStr str)
3978 {
3979 return ajStrPasteMaxC(Pstr, pos, str->Ptr, str->Len);
3980 }
3981
3982
3983
3984
3985 /* @func ajStrPasteCountK *****************************************************
3986 **
3987 ** Overwrites a string with a number of single characters.
3988 **
3989 ** Replace string at pos and add num copies of character chr. Or to the end
3990 ** of the existing string
3991 **
3992 ** @param [u] Pstr [AjPStr*] Target string
3993 ** @param [r] pos [ajlong] position in string
3994 ** @param [r] chr [char] Character to replace.
3995 ** @param [r] num [ajulong] Number of characters to copy from text.
3996 ** @return [AjBool] ajTrue on success
3997 **
3998 ** @release 4.0.0
3999 ** @@
4000 ******************************************************************************/
4001
ajStrPasteCountK(AjPStr * Pstr,ajlong pos,char chr,ajulong num)4002 AjBool ajStrPasteCountK( AjPStr* Pstr, ajlong pos, char chr,
4003 ajulong num)
4004 {
4005 AjPStr thys;
4006 size_t ibegin;
4007 size_t iend;
4008 char* ptr1 = 0;
4009 size_t i;
4010
4011 if(!*Pstr)
4012 *Pstr = ajStrNewResLenC("", 1, 0);
4013 else if((*Pstr)->Use > 1)
4014 ajStrGetuniqueStr(Pstr);
4015
4016 thys = *Pstr;
4017
4018 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos);
4019 iend = ibegin + (size_t) num;
4020
4021 if(iend > thys->Len) /* can't fit */
4022 iend = thys->Len - 1;
4023
4024 ptr1 = &thys->Ptr[ibegin];
4025
4026 for(i=ibegin;i<iend;i++)
4027 *ptr1++ = chr;
4028
4029 return ajTrue;
4030 }
4031
4032
4033
4034
4035 /* @func ajStrPasteMaxC *******************************************************
4036 **
4037 ** Overwrite one string with a specified number of characters from a text
4038 ** string.
4039 **
4040 ** Replaces string at pos ands add len characters from text string txt.
4041 ** Or to the end of the existing string
4042 **
4043 ** @param [u] Pstr [AjPStr*] Target string
4044 ** @param [r] pos [ajlong] Start position in target string.
4045 ** @param [r] txt [const char*] String to replace.
4046 ** @param [r] len [size_t] Number of characters to copy from text.
4047 ** @return [AjBool] ajTrue on success
4048 **
4049 ** @release 4.0.0
4050 ** @@
4051 ******************************************************************************/
4052
ajStrPasteMaxC(AjPStr * Pstr,ajlong pos,const char * txt,size_t len)4053 AjBool ajStrPasteMaxC (AjPStr* Pstr, ajlong pos, const char* txt,
4054 size_t len)
4055 {
4056 AjPStr thys;
4057 size_t ibegin;
4058 size_t iend;
4059 char* ptr1 = 0;
4060 const char* ptr2 = 0;
4061 size_t slen;
4062 size_t ilen;
4063
4064 slen = strlen(txt);
4065
4066 if(!*Pstr)
4067 *Pstr = ajStrNewResLenC("", 1, 0);
4068 else if((*Pstr)->Use > 1)
4069 ajStrGetuniqueStr(Pstr);
4070
4071 thys = *Pstr;
4072
4073 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos);
4074 iend = ibegin + (size_t) len;
4075
4076 if((iend > thys->Len) || (len > slen) ) /* can't fit */
4077 return ajFalse;
4078
4079 ptr1 = &thys->Ptr[ibegin];
4080 ptr2 = txt;
4081
4082 for(ilen=(size_t )len; ilen > 0; --ilen)
4083 *ptr1++ = *ptr2++;
4084
4085 return ajTrue;
4086 }
4087
4088
4089
4090
4091 /* @func ajStrPasteMaxS *******************************************************
4092 **
4093 ** Overwrite one string with a specified number of characters from another
4094 ** string.
4095
4096 ** Replaces string at pos and add len characters from string str.
4097 ** Or to the end of the existing string
4098 **
4099 ** @param [u] Pstr [AjPStr*] Target string
4100 ** @param [r] pos [ajlong] Start position in target string.
4101 ** @param [r] str [const AjPStr] Replacement string
4102 ** @param [r] len [size_t] Number of characters to copy from text.
4103 ** @return [AjBool] ajTrue on success
4104 **
4105 ** @release 4.0.0
4106 ** @@
4107 ******************************************************************************/
4108
ajStrPasteMaxS(AjPStr * Pstr,ajlong pos,const AjPStr str,size_t len)4109 AjBool ajStrPasteMaxS(AjPStr* Pstr, ajlong pos, const AjPStr str,
4110 size_t len)
4111 {
4112 return ajStrPasteMaxC(Pstr, pos, str->Ptr, len);
4113 }
4114
4115
4116
4117
4118 /* @section cutting ***********************************************************
4119 **
4120 ** Functions for removing characters or regions (substrings) from a string.
4121 **
4122 ** @fdata [AjPStr]
4123 ** @fnote None.
4124 ** @nam3rule Cut Remove region(s) from a string.
4125 ** @nam4rule CutBraces Remove comments in training braces
4126 ** @nam4rule CutComments Remove comment lines.
4127 ** @nam5rule CutCommentsStart Remove comment lines beginning with '#' only.
4128 ** @nam5rule CutCommentsRestpos Remove comment lines and note start position
4129 ** @nam4rule CutEnd Remove one end or another.
4130 ** @nam4rule CutRange Remove a substring.
4131 ** @nam4rule CutStart Remove one end or another.
4132 ** @nam4rule CutWild Remove end from first wildcard character.
4133 ** @nam4rule CutHtml Remove HTML (i.e. everything between
4134 ** '<' and '>').
4135 ** @nam3rule Keep Keep part of a string.
4136 ** @nam4rule KeepRange Keep range of character positions.
4137 ** @nam4rule KeepSet Keep only characters in a set.
4138 ** @nam5rule KeepSetAscii Keep a range of ASCII characters.
4139 ** @nam5rule KeepSetAlpha Also remove non-alphabetic.
4140 ** @nam6rule KeepSetAlphaRest Also remove non-alphabetic and report non-space
4141 ** @nam5rule KeepSetFilter Use a saved filter object
4142 ** @nam3rule Quote Editing quotes in quoted strings
4143 ** @nam4rule QuoteStrip Removing quotes
4144 ** @nam5rule QuoteStripAll Removing internal and external quotes
4145 ** @nam3rule Remove Remove individual characters from a string.
4146 ** @nam4rule RemoveGap Remove non-sequence characters.
4147 ** @nam4rule RemoveHtml Remove HTML tags.
4148 ** @nam4rule RemoveLast Remove last character.
4149 ** @nam5rule RemoveLastNewline Remove last character if a newline only.
4150 ** @nam4rule RemoveNonseq Remove non-sequence characters
4151 ** (all chars except alphabetic & '*')
4152 ** @nam4rule RemoveDupchar Remove duplicated characters.
4153 ** @nam4rule RemoveSet Remove a set of characters.
4154 ** @nam4rule RemoveWhite Remove all whitespace characters.
4155 ** @nam5rule RemoveWhiteExcess Remove excess whitespace only.
4156 ** @nam5rule RemoveWhiteSpaces Remove excess space characters only.
4157 ** @nam4rule RemoveWild Remove characters after a wildcard.
4158 ** @nam3rule Trim Remove region(s) of a given character
4159 ** composition only from start and / or end
4160 ** of a string.
4161 ** @nam4rule TrimEnd Trim from end only.
4162 ** @nam4rule TrimStart Trim from start only.
4163 ** @nam3rule Truncate Intuitively named end-cut function.
4164 ** @nam4rule TruncateLen Truncate to a specified length
4165 ** @nam4rule TruncatePos Truncate after a specified position
4166 ** @nam4rule TrimWhite Trim whitespace only.
4167 ** @nam5rule TrimWhiteEnd Trim whitespace from end.
4168 ** @nam5rule TrimWhiteStart Trim whitespace from start.
4169 ** @suffix F Float array to be kept in step with one value per character
4170 **
4171 ** @argrule * Pstr [AjPStr*] Modifiable string
4172 ** @argrule Pos pos [ajlong] First position to be deleted.
4173 Negative values count from the end
4174 ** @argrule Restpos Pcomment [AjPStr*] Removed (comment) characters
4175 ** @argrule Restpos Pstartpos [size_t*] Position at start of comment
4176 ** @argrule C txt [const char*] Text string
4177 ** @argrule K chr [char] Single character
4178 ** @argrule S str [const AjPStr] Text string
4179 ** @argrule F Pfloat [float*] Array of floats
4180 ** @argrule Len len [size_t] Number of characters to process
4181 ** @argrule CutEnd len [size_t] Number of characters to remove
4182 ** @argrule CutStart len [size_t] Number of characters to remove
4183 ** @argrule Filter filter [const char*] Filter array non-zero per character
4184 ** @argrule Range pos1 [ajlong] Start position in string, negative
4185 ** numbers count from end
4186 ** @argrule Range pos2 [ajlong] End position in string, negative
4187 ** numbers count from end
4188 ** @argrule Rest Prest [AjPStr*] Excluded characters
4189 ** @argrule Ascii minchar [int] Lowest ASCII code to keep
4190 ** @argrule Ascii maxchar [int] Highest ASCII code to keep
4191 **
4192 ** @valrule * [AjBool]
4193 **
4194 ** @fcategory modify
4195 */
4196
4197
4198
4199
4200 /* @func ajStrCutBraces *******************************************************
4201 **
4202 ** Removes comments enclosed in braces from a string.
4203 **
4204 ** A comment is enclosed in curly braces at the end of a string.
4205 **
4206 ** @param [u] Pstr [AjPStr*] Line of text from input file
4207 ** @return [AjBool] ajTrue if there is some text remaining
4208 **
4209 ** @release 6.4.0
4210 ** @@
4211 ******************************************************************************/
4212
ajStrCutBraces(AjPStr * Pstr)4213 AjBool ajStrCutBraces(AjPStr* Pstr)
4214 {
4215 AjPStr thys;
4216 char *cp;
4217 AjBool inbrace = ajFalse;
4218 AjBool skipbrace = ajFalse;
4219
4220 if(!*Pstr)
4221 *Pstr = ajStrNewResLenC("", 1, 0);
4222 else if((*Pstr)->Use > 1)
4223 ajStrGetuniqueStr(Pstr);
4224
4225 thys = *Pstr;
4226
4227 if(!thys->Len) /* empty string */
4228 return ajFalse;
4229
4230 cp = &thys->Ptr[thys->Len-1];
4231
4232 while(cp >= thys->Ptr)
4233 {
4234 if(!isspace((int)*cp))
4235 {
4236 if(!inbrace)
4237 {
4238 if(*cp != '}')
4239 return ajTrue;
4240 else
4241 inbrace = ajTrue;
4242 }
4243 else
4244 {
4245 if(*cp == '{')
4246 {
4247 skipbrace = ajTrue;
4248 inbrace = ajFalse;
4249 *cp = '\0';
4250 thys->Len = cp - thys->Ptr;
4251 }
4252 }
4253 }
4254 else if (skipbrace)
4255 {
4256 *cp = '\0';
4257 thys->Len = cp - thys->Ptr;
4258 }
4259
4260 cp--;
4261 }
4262
4263 if(!thys->Len) /* no text before the comment */
4264 return ajFalse;
4265
4266 return ajTrue;
4267 }
4268
4269
4270
4271
4272 /* @func ajStrCutComments *****************************************************
4273 **
4274 ** Removes comments from a string.
4275 **
4276 ** A comment begins with a "#" character and may appear anywhere in the string.
4277 ** See ajStrCutCommentsStart for alternative definition of a comment.
4278 **
4279 ** @param [u] Pstr [AjPStr*] Line of text from input file
4280 ** @return [AjBool] ajTrue if there is some text remaining
4281 **
4282 ** @release 4.0.0
4283 ** @@
4284 ******************************************************************************/
4285
ajStrCutComments(AjPStr * Pstr)4286 AjBool ajStrCutComments(AjPStr* Pstr)
4287 {
4288 AjPStr thys;
4289 char *cp;
4290
4291 if(!*Pstr)
4292 *Pstr = ajStrNewResLenC("", 1, 0);
4293 else if((*Pstr)->Use > 1)
4294 ajStrGetuniqueStr(Pstr);
4295
4296 thys = *Pstr;
4297
4298 if(!thys->Len) /* empty string */
4299 return ajFalse;
4300
4301 cp = strchr(thys->Ptr, '#');
4302
4303 if(cp)
4304 { /* comment found and removed */
4305 *cp = '\0';
4306 thys->Len = cp - thys->Ptr;
4307 }
4308
4309 if(!thys->Len) /* no text before the comment */
4310 return ajFalse;
4311
4312 return ajTrue;
4313 }
4314
4315
4316
4317
4318 /* @func ajStrCutCommentsRestpos **********************************************
4319 **
4320 ** Removes comments from a string.
4321 **
4322 ** A comment begins with a "#" character and may appear anywhere in the string.
4323 ** See ajStrCutCommentsStart for alternative definition of a comment.
4324 **
4325 ** @param [u] Pstr [AjPStr*] Line of text from input file
4326 ** @param [w] Pcomment [AjPStr*] Comment characters deleted
4327 ** @param [w] Pstartpos [size_t*] Comment start position
4328 ** @return [AjBool] ajTrue if there is some text remaining
4329 **
4330 ** @release 6.0.0
4331 ** @@
4332 ******************************************************************************/
4333
ajStrCutCommentsRestpos(AjPStr * Pstr,AjPStr * Pcomment,size_t * Pstartpos)4334 AjBool ajStrCutCommentsRestpos(AjPStr* Pstr,
4335 AjPStr* Pcomment, size_t* Pstartpos)
4336 {
4337 AjPStr thys;
4338 char *cp;
4339
4340 if(!*Pstr)
4341 *Pstr = ajStrNewResLenC("", 1, 0);
4342 else if((*Pstr)->Use > 1)
4343 ajStrGetuniqueStr(Pstr);
4344
4345 thys = *Pstr;
4346
4347 *Pstartpos=0;
4348 ajStrAssignClear(Pcomment);
4349
4350 if(!thys->Len) /* empty string */
4351 return ajFalse;
4352
4353 cp = strchr(thys->Ptr, '#');
4354
4355 if(cp)
4356 {
4357 /* comment found and removed */
4358 *Pstartpos = cp -thys->Ptr;
4359 ajStrAssignC(Pcomment, cp);
4360 *cp = '\0';
4361 thys->Len = cp - thys->Ptr;
4362 }
4363
4364 if(!thys->Len) /* no text before the comment */
4365 return ajFalse;
4366
4367 return ajTrue;
4368 }
4369
4370
4371
4372
4373 /* @func ajStrCutCommentsStart ************************************************
4374 **
4375 ** Removes comments from a string.
4376 **
4377 ** A comment is a blank line or any text starting with a "#" character.
4378 **
4379 ** @param [u] Pstr [AjPStr*] Line of text from input file
4380 ** @return [AjBool] ajTrue if there is some text remaining
4381 **
4382 ** @release 4.0.0
4383 ** @@
4384 ******************************************************************************/
4385
ajStrCutCommentsStart(AjPStr * Pstr)4386 AjBool ajStrCutCommentsStart(AjPStr* Pstr)
4387 {
4388 AjPStr thys;
4389
4390 if(!*Pstr)
4391 *Pstr = ajStrNewResLenC("", 1, 0);
4392 else if((*Pstr)->Use > 1)
4393 ajStrGetuniqueStr(Pstr);
4394
4395 thys = *Pstr;
4396
4397 if(!MAJSTRGETLEN(thys)) /* empty string */
4398 return ajFalse;
4399
4400 if(thys->Ptr[0] == '#')
4401 { /* comment found */
4402 ajStrAssignClear(Pstr);
4403 return ajFalse;
4404 }
4405
4406 return ajTrue;
4407 }
4408
4409
4410
4411
4412 /* @func ajStrCutEnd **********************************************************
4413 **
4414 ** Removes a number of characters from the end of a string
4415 **
4416 ** @param [u] Pstr [AjPStr*] string
4417 ** @param [r] len [size_t] Number of characters to delete from the end
4418 ** @return [AjBool] ajTrue if string was reallocated
4419 **
4420 ** @release 4.0.0
4421 ** @@
4422 ******************************************************************************/
4423
ajStrCutEnd(AjPStr * Pstr,size_t len)4424 AjBool ajStrCutEnd(AjPStr* Pstr, size_t len)
4425 {
4426 AjPStr thys;
4427
4428 if(!*Pstr)
4429 *Pstr = ajStrNewResLenC("", 1, 0);
4430 else if((*Pstr)->Use > 1)
4431 ajStrGetuniqueStr(Pstr);
4432
4433 thys = *Pstr;
4434
4435 if(!len)
4436 return ajTrue;
4437
4438 if(len > thys->Len)
4439 thys->Len = 0;
4440 else
4441 thys->Len -= len;
4442
4443 thys->Ptr[thys->Len] = '\0';
4444
4445 return ajTrue;
4446 }
4447
4448
4449
4450
4451 /* @func ajStrCutRange ********************************************************
4452 **
4453 ** Removes a substring from a string.
4454 **
4455 ** @param [w] Pstr [AjPStr*] Target string
4456 ** @param [r] pos1 [ajlong] start position to be cut
4457 ** @param [r] pos2 [ajlong] end position to be cut
4458 ** @return [AjBool] ajTrue on success, ajFalse if begin is out of range
4459 **
4460 ** @release 4.0.0
4461 ** @@
4462 ******************************************************************************/
4463
ajStrCutRange(AjPStr * Pstr,ajlong pos1,ajlong pos2)4464 AjBool ajStrCutRange(AjPStr* Pstr, ajlong pos1, ajlong pos2)
4465 {
4466 AjPStr thys;
4467 size_t ilen;
4468 size_t ibegin;
4469 size_t iend;
4470 size_t irest;
4471
4472 if(!*Pstr)
4473 *Pstr = ajStrNewResLenC("", 1, 0);
4474 else if((*Pstr)->Use > 1)
4475 ajStrGetuniqueStr(Pstr);
4476
4477 thys = *Pstr;
4478
4479 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos1);
4480 iend = ajCvtSposToPosStart(thys->Len, ibegin, pos2) + 1;
4481 ilen = iend - ibegin;
4482
4483 /*ajDebug("ajStrCut %d %d len: %d ibegin: %d iend: %d\n",
4484 begin, end, thys->Len, ibegin, iend);*/
4485
4486 irest = thys->Len - iend + 1;
4487
4488 if(irest > 0)
4489 memmove(&thys->Ptr[ibegin], &thys->Ptr[iend], irest);
4490
4491 thys->Len -= ilen;
4492 thys->Ptr[thys->Len] = '\0';
4493
4494 return ajTrue;
4495 }
4496
4497
4498
4499
4500 /* @func ajStrCutStart ********************************************************
4501 **
4502 ** Removes a number of characters from the start of a string
4503 **
4504 ** @param [u] Pstr [AjPStr*] string
4505 ** @param [r] len [size_t] Number of characters to delete from the start
4506 ** @return [AjBool] ajTrue if string was reallocated
4507 **
4508 ** @release 4.0.0
4509 ** @@
4510 ******************************************************************************/
4511
ajStrCutStart(AjPStr * Pstr,size_t len)4512 AjBool ajStrCutStart(AjPStr* Pstr, size_t len)
4513 {
4514 AjPStr thys;
4515
4516 if(!*Pstr)
4517 *Pstr = ajStrNewResLenC("", 1, 0);
4518 else if((*Pstr)->Use > 1)
4519 ajStrGetuniqueStr(Pstr);
4520 thys = *Pstr;
4521
4522 if(!len)
4523 return ajTrue;
4524
4525 if(len > thys->Len)
4526 thys->Len = 0;
4527 else
4528 {
4529 memmove(thys->Ptr, &thys->Ptr[len], thys->Len - len);
4530 thys->Len -= len;
4531 thys->Ptr[thys->Len] = '\0';
4532 }
4533
4534 return ajTrue;
4535 }
4536
4537
4538
4539
4540 /* @func ajStrKeepRange *******************************************************
4541 **
4542 ** Reduces target string to a substring of itself by deleting all except
4543 ** a range of character positions.
4544 **
4545 ** The end is allowed to be before begin, in which case the output is an
4546 ** empty string.
4547 **
4548 ** @param [w] Pstr [AjPStr*] Target string.
4549 ** @param [r] pos1 [ajlong] Start position for substring.
4550 ** @param [r] pos2 [ajlong] End position for substring.
4551 ** @return [AjBool] ajTrue if string was reallocated
4552 **
4553 ** @release 4.0.0
4554 ** @@
4555 ******************************************************************************/
4556
ajStrKeepRange(AjPStr * Pstr,ajlong pos1,ajlong pos2)4557 AjBool ajStrKeepRange(AjPStr* Pstr, ajlong pos1, ajlong pos2)
4558 {
4559 AjBool ret = ajFalse;
4560 AjPStr str;
4561 size_t ibegin;
4562 size_t ilen;
4563 size_t iend;
4564
4565 str = *Pstr;
4566
4567 if(str->Use > 1)
4568 str = ajStrGetuniqueStr(Pstr);
4569
4570 ibegin = ajCvtSposToPosStart(str->Len, 0, pos1);
4571 iend = ajCvtSposToPosStart(str->Len, 0, pos2);
4572
4573 if(iend == str->Len)
4574 iend--;
4575
4576 if(iend < ibegin)
4577 ilen = 0;
4578 else
4579 ilen = iend - ibegin + 1;
4580
4581 if(ilen)
4582 {
4583 if(ibegin)
4584 ajMemMove(str->Ptr, &str->Ptr[ibegin], ilen);
4585
4586 str->Len = ilen;
4587 str->Ptr[ilen] = '\0';
4588 }
4589 else
4590 {
4591 str->Len = 0;
4592 str->Ptr[0] = '\0';
4593 }
4594
4595 return ret;
4596 }
4597
4598
4599
4600
4601 /* @func ajStrKeepSetC ********************************************************
4602 **
4603 ** Removes all characters from a string that are not in a given set.
4604 **
4605 ** @param [u] Pstr [AjPStr *] String to clean.
4606 ** @param [r] txt [const char*] Character set to keep
4607 ** @return [AjBool] ajTrue if string was reallocated
4608 **
4609 ** @release 4.0.0
4610 ** @@
4611 ******************************************************************************/
4612
ajStrKeepSetC(AjPStr * Pstr,const char * txt)4613 AjBool ajStrKeepSetC(AjPStr* Pstr, const char* txt)
4614 {
4615 AjPStr thys;
4616 char *p;
4617 char *q;
4618
4619 if(!*Pstr)
4620 *Pstr = ajStrNewResLenC("", 1, 0);
4621 else if((*Pstr)->Use > 1)
4622 ajStrGetuniqueStr(Pstr);
4623
4624 thys = *Pstr;
4625
4626 p = thys->Ptr;
4627 q = thys->Ptr;
4628
4629 while(*p)
4630 {
4631 if(strchr(txt, *p))
4632 *q++=*p;
4633
4634 p++;
4635 }
4636
4637 *q='\0';
4638 thys->Len = q - thys->Ptr;
4639
4640 if(!thys->Len)
4641 return ajFalse;
4642
4643 return ajTrue;
4644 }
4645
4646
4647
4648
4649 /* @func ajStrKeepSetFilter ***************************************************
4650 **
4651 ** Removes all characters from a string that are not defined by a filter
4652 **
4653 ** @param [u] Pstr [AjPStr*] String
4654 ** @param [r] filter [const char*] Filter non-zero for each allowed value
4655 ** @return [AjBool] ajTrue if the string is entirely composed of characters
4656 ** in the specified set
4657 **
4658 ** @release 6.6.0
4659 ** @@
4660 ******************************************************************************/
4661
ajStrKeepSetFilter(AjPStr * Pstr,const char * filter)4662 AjBool ajStrKeepSetFilter(AjPStr *Pstr, const char* filter)
4663 {
4664 const char* cp;
4665 char* cq;
4666
4667 if(!*Pstr)
4668 *Pstr = ajStrNewResLenC("", 1, 0);
4669 else if((*Pstr)->Use > 1)
4670 ajStrGetuniqueStr(Pstr);
4671
4672 cp = cq = (*Pstr)->Ptr;
4673
4674 while(*cp)
4675 {
4676 if(filter[(int)*cp])
4677 *cq++ = *cp;
4678 cp++;
4679 }
4680
4681 if(cp != cq)
4682 {
4683 *cq = '\0';
4684 (*Pstr)->Len -= (cp - cq);
4685
4686 return ajFalse;
4687 }
4688
4689 return ajTrue;
4690 }
4691
4692
4693
4694
4695 /* @func ajStrKeepSetS ********************************************************
4696 **
4697 ** Removes all characters from a string that are not in a given set.
4698 **
4699 ** @param [u] Pstr [AjPStr *] String to clean.
4700 ** @param [r] str [const AjPStr] Character set to keep
4701 ** @return [AjBool] ajTrue if string is not empty
4702 **
4703 ** @release 4.1.0
4704 ** @@
4705 ******************************************************************************/
4706
ajStrKeepSetS(AjPStr * Pstr,const AjPStr str)4707 AjBool ajStrKeepSetS(AjPStr* Pstr, const AjPStr str)
4708 {
4709 AjPStr thys;
4710 char *p = NULL;
4711 char *q = NULL;
4712 const char* txt;
4713
4714 if(!str)
4715 {
4716 if(MAJSTRGETLEN(*Pstr))
4717 return ajTrue;
4718 else
4719 return ajFalse;
4720 }
4721
4722 if(!*Pstr)
4723 *Pstr = ajStrNewResLenC("", 1, 0);
4724 else if((*Pstr)->Use > 1)
4725 ajStrGetuniqueStr(Pstr);
4726
4727 thys = *Pstr;
4728
4729 txt = MAJSTRGETPTR(str);
4730
4731 p = thys->Ptr;
4732 q = thys->Ptr;
4733
4734 while(*p)
4735 {
4736 if(strchr(txt, *p))
4737 *q++=*p;
4738
4739 p++;
4740 }
4741
4742 *q='\0';
4743 thys->Len = q - thys->Ptr;
4744
4745 if(!thys->Len)
4746 return ajFalse;
4747
4748 return ajTrue;
4749 }
4750
4751
4752
4753
4754 /* @func ajStrKeepSetAlpha ****************************************************
4755 **
4756 ** Removes all characters from a string that are not alphabetic.
4757 **
4758 ** @param [u] Pstr [AjPStr *] String to clean.
4759 ** @return [AjBool] ajTrue if string is not empty
4760 **
4761 ** @release 4.1.0
4762 ** @@
4763 ******************************************************************************/
4764
ajStrKeepSetAlpha(AjPStr * Pstr)4765 AjBool ajStrKeepSetAlpha(AjPStr* Pstr)
4766 {
4767 AjPStr thys;
4768 char *p;
4769 char *q;
4770
4771 if(!*Pstr)
4772 *Pstr = ajStrNewResLenC("", 1, 0);
4773 else if((*Pstr)->Use > 1)
4774 ajStrGetuniqueStr(Pstr);
4775
4776 thys = *Pstr;
4777
4778 p = thys->Ptr;
4779 q = thys->Ptr;
4780
4781 while(*p)
4782 {
4783 if(isalpha((ajint)*p))
4784 *q++=*p;
4785
4786 p++;
4787 }
4788
4789 *q='\0';
4790 thys->Len = q - thys->Ptr;
4791
4792 if(!thys->Len)
4793 return ajFalse;
4794
4795 return ajTrue;
4796 }
4797
4798
4799
4800
4801 /* @func ajStrKeepSetAlphaC ***************************************************
4802 **
4803 ** Removes all characters from a string that are not alphabetic and
4804 ** are not in a given set.
4805 **
4806 ** @param [u] Pstr [AjPStr *] String to clean.
4807 ** @param [r] txt [const char*] Non-alphabetic character set to keep
4808 ** @return [AjBool] ajTrue if string is not empty
4809 **
4810 ** @release 4.0.0
4811 ** @@
4812 ******************************************************************************/
4813
ajStrKeepSetAlphaC(AjPStr * Pstr,const char * txt)4814 AjBool ajStrKeepSetAlphaC(AjPStr* Pstr, const char* txt)
4815 {
4816 AjPStr thys;
4817 char *p = NULL;
4818 char *q = NULL;
4819
4820 if(!*Pstr)
4821 *Pstr = ajStrNewResLenC("", 1, 0);
4822 else if((*Pstr)->Use > 1)
4823 ajStrGetuniqueStr(Pstr);
4824
4825 thys = *Pstr;
4826
4827 p = thys->Ptr;
4828
4829 while(*p && (isalpha((ajint)*p) || strchr(txt, (ajint)*p)))
4830 p++;
4831 q = p;
4832
4833 while(*p)
4834 {
4835 if(isalpha((ajint)*p) || strchr(txt, (ajint)*p))
4836 *q++=*p;
4837
4838 p++;
4839 }
4840
4841 *q='\0';
4842 thys->Len = q - thys->Ptr;
4843
4844 if(!thys->Len)
4845 return ajFalse;
4846
4847 return ajTrue;
4848 }
4849
4850
4851
4852
4853 /* @func ajStrKeepSetAlphaS ***************************************************
4854 **
4855 ** Removes all characters from a string that are not alphabetic and
4856 ** are not in a given set.
4857 **
4858 ** @param [u] Pstr [AjPStr *] String to clean.
4859 ** @param [r] str [const AjPStr] Non-alphabetic character set to keep
4860 ** @return [AjBool] ajTrue if string is not empty
4861 **
4862 ** @release 5.0.0
4863 ** @@
4864 ******************************************************************************/
4865
ajStrKeepSetAlphaS(AjPStr * Pstr,const AjPStr str)4866 AjBool ajStrKeepSetAlphaS(AjPStr* Pstr, const AjPStr str)
4867 {
4868 return ajStrKeepSetAlphaC(Pstr, str->Ptr);
4869 }
4870
4871
4872
4873
4874 /* @func ajStrKeepSetAlphaRest ************************************************
4875 **
4876 ** Removes all characters from a string that are not alphabetic.
4877 **
4878 ** Also returns any non-whitespace characters in the strings
4879 **
4880 ** @param [u] Pstr [AjPStr *] String to clean.
4881 ** @param [u] Prest [AjPStr *] Excluded non-whitespace characters.
4882 ** @return [AjBool] ajTrue if string is not empty
4883 **
4884 ** @release 5.0.0
4885 ** @@
4886 ******************************************************************************/
4887
ajStrKeepSetAlphaRest(AjPStr * Pstr,AjPStr * Prest)4888 AjBool ajStrKeepSetAlphaRest(AjPStr* Pstr, AjPStr* Prest)
4889 {
4890 AjPStr thys = NULL;
4891 char *p = NULL;
4892 char *q = NULL;
4893
4894 ajStrAssignClear(Prest);
4895
4896 if(!*Pstr)
4897 *Pstr = ajStrNewResLenC("", 1, 0);
4898 else if((*Pstr)->Use > 1)
4899 ajStrGetuniqueStr(Pstr);
4900
4901 thys = *Pstr;
4902
4903 p = thys->Ptr;
4904 q = thys->Ptr;
4905
4906 while(*p)
4907 {
4908 if(isalpha((ajint)*p))
4909 *q++=*p;
4910 else if(!isspace((ajint)*p))
4911 ajStrAppendK(Prest, *p);
4912
4913 p++;
4914 }
4915
4916 *q='\0';
4917 thys->Len = q - thys->Ptr;
4918
4919 if(!thys->Len)
4920 return ajFalse;
4921
4922 return ajTrue;
4923 }
4924
4925
4926
4927
4928 /* @func ajStrKeepSetAlphaRestC ***********************************************
4929 **
4930 ** Removes all characters from a string that are not alphabetic and
4931 ** are not in a given set.
4932 **
4933 ** Also returns any non-whitespace characters in the strings
4934 **
4935 ** @param [u] Pstr [AjPStr *] String to clean.
4936 ** @param [r] txt [const char*] Non-alphabetic character set to keep
4937 ** @param [u] Prest [AjPStr *] Excluded non-whitespace characters.
4938 ** @return [AjBool] ajTrue if string is not empty
4939 **
4940 ** @release 5.0.0
4941 ** @@
4942 ******************************************************************************/
4943
ajStrKeepSetAlphaRestC(AjPStr * Pstr,const char * txt,AjPStr * Prest)4944 AjBool ajStrKeepSetAlphaRestC(AjPStr* Pstr, const char* txt, AjPStr* Prest)
4945 {
4946 AjPStr thys = NULL;
4947 char *p = NULL;
4948 char *q = NULL;
4949
4950 ajStrAssignClear(Prest);
4951
4952 if(!*Pstr)
4953 *Pstr = ajStrNewResLenC("", 1, 0);
4954 else if((*Pstr)->Use > 1)
4955 ajStrGetuniqueStr(Pstr);
4956
4957 thys = *Pstr;
4958
4959 p = thys->Ptr;
4960 q = thys->Ptr;
4961
4962 while(*p)
4963 {
4964 if(isalpha((ajint)*p))
4965 *q++=*p;
4966 else if(strchr(txt, *p))
4967 *q++=*p;
4968 else if(!isspace((ajint)*p))
4969 ajStrAppendK(Prest, *p);
4970
4971 p++;
4972 }
4973
4974 *q='\0';
4975 thys->Len = q - thys->Ptr;
4976
4977 if(!thys->Len)
4978 return ajFalse;
4979
4980 return ajTrue;
4981 }
4982
4983
4984
4985
4986 /* @func ajStrKeepSetAlphaRestS ***********************************************
4987 **
4988 ** Removes all characters from a string that are not alphabetic and
4989 ** are not in a given set.
4990 **
4991 ** Also returns any non-whitespace characters in the strings
4992 **
4993 ** @param [u] Pstr [AjPStr *] String to clean.
4994 ** @param [r] str [const AjPStr] Non-alphabetic character set to keep
4995 ** @param [u] Prest [AjPStr *] Excluded non-whitespace characters.
4996 ** @return [AjBool] ajTrue if string is not empty
4997 **
4998 ** @release 5.0.0
4999 ** @@
5000 ******************************************************************************/
5001
ajStrKeepSetAlphaRestS(AjPStr * Pstr,const AjPStr str,AjPStr * Prest)5002 AjBool ajStrKeepSetAlphaRestS(AjPStr* Pstr, const AjPStr str, AjPStr* Prest)
5003 {
5004 return ajStrKeepSetAlphaRestC(Pstr, str->Ptr, Prest);
5005 }
5006
5007
5008
5009
5010 /* @func ajStrKeepSetAscii ****************************************************
5011 **
5012 ** Removes all characters from a string that are not within a range of
5013 ** ASCII character codes.
5014 **
5015 ** @param [u] Pstr [AjPStr *] String to clean.
5016 ** @param [r] minchar [int] Lowest ASCII code to keep
5017 ** @param [r] maxchar [int] Highest ASCII code to keep
5018 ** @return [AjBool] ajTrue if string is not empty
5019 **
5020 ** @release 6.1.0
5021 ** @@
5022 ******************************************************************************/
5023
ajStrKeepSetAscii(AjPStr * Pstr,int minchar,int maxchar)5024 AjBool ajStrKeepSetAscii(AjPStr* Pstr, int minchar, int maxchar)
5025 {
5026 AjPStr thys;
5027 char *p;
5028 char *q;
5029
5030 if(!*Pstr)
5031 *Pstr = ajStrNewResLenC("", 1, 0);
5032 else if((*Pstr)->Use > 1)
5033 ajStrGetuniqueStr(Pstr);
5034
5035 thys = *Pstr;
5036
5037 p = thys->Ptr;
5038
5039 while(*p && (*p >= minchar) && (*p <= maxchar))
5040 {
5041 p++;
5042 }
5043 q = p;
5044
5045 while(*p)
5046 {
5047 if((*p >= minchar) && (*p <= maxchar))
5048 *q++=*p;
5049
5050 p++;
5051 }
5052
5053 *q='\0';
5054 thys->Len = q - thys->Ptr;
5055
5056 if(!thys->Len)
5057 return ajFalse;
5058
5059 return ajTrue;
5060 }
5061
5062
5063
5064
5065 /* @func ajStrQuoteStrip ******************************************************
5066 **
5067 ** Removes any double quotes from a string.
5068 **
5069 ** Internal escaped or double quotes are converted to single quotes.
5070 **
5071 ** @param [u] Pstr [AjPStr *] string
5072 **
5073 ** @return [AjBool] ajTrue if string is not empty
5074 **
5075 ** @release 2.0.1
5076 ** @@
5077 ******************************************************************************/
ajStrQuoteStrip(AjPStr * Pstr)5078 AjBool ajStrQuoteStrip(AjPStr* Pstr)
5079 {
5080 AjPStr thys;
5081
5082 if(!*Pstr)
5083 *Pstr = ajStrNewResLenC("", 1, 0);
5084 else if((*Pstr)->Use > 1)
5085 ajStrGetuniqueStr(Pstr);
5086
5087 thys = *Pstr;
5088
5089 if(ajStrGetCharLast(thys) == '"')
5090 ajStrCutEnd(Pstr, 1);
5091
5092 if(ajStrGetCharFirst(thys) == '"')
5093 ajStrCutStart(Pstr, 1);
5094
5095 ajStrExchangeCC(Pstr, "\"\"", "\""); /* doubled quotes to single */
5096 ajStrExchangeCC(Pstr, "\\\"", "\""); /* escaped quotes to single */
5097
5098 if(!thys->Len)
5099 return ajFalse;
5100
5101 return ajTrue;
5102 }
5103
5104
5105
5106
5107 /* @func ajStrQuoteStripAll ***************************************************
5108 **
5109 ** Removes any single or double quotes from a string.
5110 **
5111 ** Internal escaped or doubled-up quotes are converted to single quotes.
5112 **
5113 ** @param [u] Pstr [AjPStr *] string
5114 **
5115 ** @return [AjBool] True on success
5116 **
5117 ** @release 3.0.0
5118 ** @@
5119 ******************************************************************************/
ajStrQuoteStripAll(AjPStr * Pstr)5120 AjBool ajStrQuoteStripAll(AjPStr* Pstr)
5121 {
5122 AjPStr thys;
5123
5124 if(!*Pstr)
5125 *Pstr = ajStrNewResLenC("", 1, 0);
5126 else if((*Pstr)->Use > 1)
5127 ajStrGetuniqueStr(Pstr);
5128
5129 thys = *Pstr;
5130
5131 if(ajStrGetCharLast(thys) == '"')
5132 {
5133 ajStrCutEnd(Pstr, 1);
5134
5135 if(ajStrGetCharFirst(thys) == '"')
5136 ajStrCutStart(Pstr, 1);
5137
5138 ajStrExchangeCC(Pstr, "\"\"", "\""); /* doubled quotes to single */
5139 ajStrExchangeCC(Pstr, "\\\"", "\""); /* escaped quotes to single */
5140 }
5141 else if(ajStrGetCharLast(thys) == '\'')
5142 {
5143 ajStrCutEnd(Pstr, 1);
5144
5145 if(ajStrGetCharFirst(thys) == '\'')
5146 ajStrCutStart(Pstr, 1);
5147
5148 ajStrExchangeCC(Pstr, "''", "'"); /* doubled quotes to single */
5149 ajStrExchangeCC(Pstr, "\\'", "'"); /* escaped quotes to single */
5150 }
5151
5152 if(!thys->Len)
5153 return ajFalse;
5154
5155 return ajTrue;
5156 }
5157
5158
5159
5160
5161 /* @func ajStrRemoveDupchar ***************************************************
5162 **
5163 ** Removes duplicate characters from a string
5164 **
5165 ** @param [w] Pstr [AjPStr*] String
5166 ** @return [AjBool] True if string is not empty
5167 **
5168 ** @release 6.2.0
5169 ** @@
5170 ******************************************************************************/
5171
ajStrRemoveDupchar(AjPStr * Pstr)5172 AjBool ajStrRemoveDupchar(AjPStr* Pstr)
5173 {
5174 char filter[256] = {'\0'}; /* should make all zero */
5175 char *cp;
5176 char *cq;
5177 AjPStr thys;
5178
5179 if(!*Pstr)
5180 *Pstr = ajStrNewResLenC("", 1, 0);
5181 else if((*Pstr)->Use > 1)
5182 ajStrGetuniqueStr(Pstr);
5183
5184 thys = *Pstr;
5185
5186 cp = thys->Ptr;
5187 while(*cp && !filter[(ajint)*cp])
5188 filter[(ajint)*cp++] = 1;
5189 cq = cp;
5190
5191 while(*cp)
5192 {
5193 if(!filter[(ajint)*cp])
5194 {
5195 filter[(ajint)*cp] = 1;
5196 *cq++ = *cp;
5197 }
5198 else
5199 {
5200 --thys->Len;
5201 }
5202
5203 cp++;
5204 }
5205 *cq = '\0';
5206
5207 if(!thys->Len)
5208 return ajFalse;
5209
5210 return ajTrue;
5211 }
5212
5213
5214
5215
5216 /* @func ajStrRemoveGap *******************************************************
5217 **
5218 ** Removes non-sequence characters (all but alphabetic characters and asterisk)
5219 ** from a string.
5220 **
5221 ** @param [w] Pstr [AjPStr*] String
5222 ** @return [AjBool] True if string is not empty
5223 **
5224 ** @release 4.0.0
5225 ** @@
5226 ******************************************************************************/
5227
ajStrRemoveGap(AjPStr * Pstr)5228 AjBool ajStrRemoveGap(AjPStr* Pstr)
5229 {
5230 char *p;
5231 char *q;
5232 size_t i;
5233 size_t len;
5234 char c;
5235 size_t ispan;
5236 AjPStr thys;
5237
5238 if(!*Pstr)
5239 *Pstr = ajStrNewResLenC("", 1, 0);
5240 else if((*Pstr)->Use > 1)
5241 ajStrGetuniqueStr(Pstr);
5242
5243 thys = *Pstr;
5244
5245 p = q = thys->Ptr;
5246 len = thys->Len;
5247
5248 ispan = strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*");
5249
5250 if(p[ispan])
5251 {
5252 for(i=0;i<len;++i)
5253 {
5254 c = *(p++);
5255
5256 /* O is a gap character for Phylip ... but now valid for proteins */
5257 if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c=='*'))
5258 *(q++) = c;
5259 else
5260 --thys->Len;
5261 }
5262
5263 thys->Ptr[thys->Len] = '\0';
5264 }
5265
5266 if(!thys->Len)
5267 return ajFalse;
5268
5269 return ajTrue;
5270 }
5271
5272
5273
5274
5275 /* @func ajStrRemoveGapF ******************************************************
5276 **
5277 ** Removes non-sequence characters (all but alphabetic characters and asterisk)
5278 ** from a string. Also removes floats from an array of the same size
5279 **
5280 ** @param [w] Pstr [AjPStr*] String
5281 ** @param [w] Pfloat [float*] Floating point array (e.g. quality scores)
5282 ** @return [AjBool] True if string is not empty
5283 **
5284 ** @release 6.2.0
5285 ** @@
5286 ******************************************************************************/
5287
ajStrRemoveGapF(AjPStr * Pstr,float * Pfloat)5288 AjBool ajStrRemoveGapF(AjPStr* Pstr, float* Pfloat)
5289 {
5290 char *p;
5291 char *q;
5292 size_t i;
5293 size_t len;
5294 char c;
5295 size_t ispan;
5296 AjPStr thys;
5297 float *fp;
5298 float *fq;
5299 float f;
5300
5301 if(!*Pstr)
5302 *Pstr = ajStrNewResLenC("", 1, 0);
5303 else if((*Pstr)->Use > 1)
5304 ajStrGetuniqueStr(Pstr);
5305
5306 thys = *Pstr;
5307
5308 p = q = thys->Ptr;
5309 fp = fq = Pfloat;
5310 len = thys->Len;
5311
5312 ispan = strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*");
5313
5314 if(p[ispan])
5315 {
5316 for(i=0;i<len;++i)
5317 {
5318 c = *(p++);
5319 f = (*fp++);
5320
5321 /* O is a gap character for Phylip ... but now valid for proteins */
5322 if((c>='A' && c<='Z') || (c>='a' && c<='z') || (c=='*'))
5323 {
5324 *(q++) = c;
5325 *(fq++) = f;
5326 }
5327 else
5328 --thys->Len;
5329 }
5330
5331 thys->Ptr[thys->Len] = '\0';
5332 }
5333
5334 if(!thys->Len)
5335 return ajFalse;
5336
5337 return ajTrue;
5338 }
5339
5340
5341
5342
5343 /* @func ajStrRemoveHtml ******************************************************
5344 **
5345 ** Removes html from a string.
5346 **
5347 ** html is defined as all substrings between and including angle brackets.
5348 **
5349 ** @param [w] Pstr [AjPStr*] String
5350 ** @return [AjBool] ajTrue on success
5351 **
5352 ** @release 1.9.0
5353 ** @@
5354 ******************************************************************************/
5355
ajStrRemoveHtml(AjPStr * Pstr)5356 AjBool ajStrRemoveHtml(AjPStr* Pstr)
5357 {
5358 char *p;
5359 char *q;
5360 AjPStr thys;
5361
5362 if(!*Pstr)
5363 *Pstr = ajStrNewResLenC("", 1, 0);
5364 else if((*Pstr)->Use > 1)
5365 ajStrGetuniqueStr(Pstr);
5366
5367 thys = *Pstr;
5368
5369 p = q = thys->Ptr;
5370
5371 while(*p)
5372 {
5373 if(*p!='<')
5374 {
5375 *q++=*p++;
5376 continue;
5377 }
5378
5379 while(*p)
5380 {
5381 --thys->Len;
5382 if(*p=='>')
5383 {
5384 ++p;
5385 break;
5386 }
5387 ++p;
5388 }
5389 }
5390
5391 *q='\0';
5392
5393 if(!thys->Len)
5394 return ajFalse;
5395
5396 return ajTrue;
5397 }
5398
5399
5400
5401
5402 /* @func ajStrRemoveLastNewline ***********************************************
5403 **
5404 ** Removes last character from a string if it is a newline character.
5405 **
5406 ** @param [w] Pstr [AjPStr*] String
5407 ** @return [AjBool] True is string is not empty
5408 **
5409 ** @release 4.0.0
5410 ** @@
5411 ******************************************************************************/
5412
ajStrRemoveLastNewline(AjPStr * Pstr)5413 AjBool ajStrRemoveLastNewline(AjPStr* Pstr)
5414 {
5415 AjPStr thys;
5416
5417 thys = *Pstr;
5418
5419 if(thys->Len)
5420 if(thys->Ptr[thys->Len-1]=='\n')
5421 {
5422 thys->Ptr[thys->Len-1]='\0';
5423 --thys->Len;
5424 }
5425
5426 if(!thys->Len)
5427 return ajFalse;
5428
5429 return ajTrue;
5430 }
5431
5432
5433
5434
5435 /* @func ajStrRemoveSetC ******************************************************
5436 **
5437 ** Removes all of a given set of characters from a string.
5438 **
5439 ** @param [w] Pstr [AjPStr*] String
5440 ** @param [r] txt [const char*] characters to remove
5441 ** @return [AjBool] True on success
5442 **
5443 ** @release 4.0.0
5444 ** @@
5445 ******************************************************************************/
5446
ajStrRemoveSetC(AjPStr * Pstr,const char * txt)5447 AjBool ajStrRemoveSetC(AjPStr* Pstr, const char *txt)
5448 {
5449 char *p = NULL;
5450 char *q = NULL;
5451 char *r = NULL;
5452 AjPStr thys = NULL;
5453
5454 if(!(*Pstr))
5455 return ajFalse;
5456
5457 thys = *Pstr;
5458
5459 if(!MAJSTRGETLEN(thys))
5460 return ajFalse;
5461
5462
5463 p = thys->Ptr;
5464 q = p;
5465
5466 while((r=strpbrk(p,txt)))
5467 {
5468 while(p!=r)
5469 *(q++) = *(p++);
5470
5471 ++p;
5472 --thys->Len;
5473 *q = '\0';
5474 }
5475
5476 while(*p)
5477 *(q++) = *(p++);
5478
5479 *q = '\0';
5480
5481 if(!thys->Len)
5482 return ajFalse;
5483
5484 return ajTrue;
5485 }
5486
5487
5488
5489
5490 /* @func ajStrRemoveWhite *****************************************************
5491 **
5492 ** Removes all whitespace characters from a string.
5493 **
5494 ** @param [u] Pstr [AjPStr *] String to clean.
5495 ** @return [AjBool] ajTrue if string was reallocated
5496 **
5497 ** @release 4.0.0
5498 ** @@
5499 ******************************************************************************/
5500
ajStrRemoveWhite(AjPStr * Pstr)5501 AjBool ajStrRemoveWhite(AjPStr* Pstr)
5502 {
5503 AjPStr thys;
5504 size_t i = 0;
5505 size_t j = 0;
5506 size_t len;
5507 char *p;
5508
5509 if(!*Pstr)
5510 *Pstr = ajStrNewResLenC("", 1, 0);
5511 else if((*Pstr)->Use > 1)
5512 ajStrGetuniqueStr(Pstr);
5513
5514 thys = *Pstr;
5515
5516 p = thys->Ptr;
5517 len = thys->Len;
5518
5519 for(i=0;i<len;++i)
5520 if(p[i]=='\t' || p[i]=='\n' || p[i]=='\r')
5521 p[i]=' ';
5522
5523 for(i=0;i<len;++i)
5524 if(p[i]!=' ')
5525 p[j++]=p[i];
5526 else
5527 --thys->Len;
5528
5529 p[j]='\0';
5530
5531 if(!thys->Len)
5532 return ajFalse;
5533
5534 return ajTrue;
5535 }
5536
5537
5538
5539
5540 /* @func ajStrRemoveWhiteExcess ***********************************************
5541 **
5542 ** Removes excess whitespace characters from a string.
5543 **
5544 ** Leading/trailing whitespace removed. Multiple spaces replaced by single
5545 ** spaces.
5546 **
5547 ** @param [u] Pstr [AjPStr *] String to clean.
5548 ** @return [AjBool] ajTrue if string was reallocated
5549 **
5550 ** @release 4.0.0
5551 ** @@
5552 ******************************************************************************/
5553
ajStrRemoveWhiteExcess(AjPStr * Pstr)5554 AjBool ajStrRemoveWhiteExcess(AjPStr* Pstr)
5555 {
5556 AjBool ret = ajFalse;
5557 AjPStr thys = NULL;
5558
5559 size_t i = 0;
5560 size_t j = 0;
5561 size_t len;
5562 char *p = NULL;
5563
5564 if(!*Pstr)
5565 *Pstr = ajStrNewResLenC("", 1, 0);
5566 else if((*Pstr)->Use > 1)
5567 ajStrGetuniqueStr(Pstr);
5568
5569 thys = *Pstr;
5570
5571 p = thys->Ptr;
5572
5573 /* if string was already empty, no need to do anything */
5574
5575 len = thys->Len;
5576
5577 if(!len)
5578 return ajFalse;
5579
5580 /* tabs converted to spaces */
5581
5582 for(i=0;i<len;++i)
5583 if(p[i]=='\t' || p[i]=='\n' || p[i]=='\r')
5584 p[i]=' ';
5585
5586 /* remove leading spaces */
5587
5588 i = 0;
5589 while(p[i])
5590 {
5591 if(p[i]!=' ')
5592 break;
5593
5594 ++i;
5595 --len;
5596 }
5597
5598 if(i)
5599 {
5600 len++;
5601 memmove(p,&p[i], len);
5602 len=strlen(p);
5603
5604 if(!len)
5605 { /* if that emptied it, so be it */
5606 thys->Len = 0;
5607
5608 return ajFalse;
5609 }
5610 }
5611
5612 /* remove newline at the end (if any) */
5613
5614 if(p[len-1]=='\n')
5615 {
5616 --len;
5617 p[len]='\0';
5618 }
5619
5620 if(!len)
5621 { /* if that emptied it, so be it */
5622 thys->Len = 0;
5623
5624 return ajFalse;
5625 }
5626
5627 /* clean up any space at the end */
5628
5629 for(i=len;i>0;--i)
5630 if(p[i-1]!=' ')
5631 break;
5632
5633 p[i]='\0';
5634
5635 len=strlen(p);
5636
5637 for(i=j=0;i<len;++i)
5638 {
5639 if(p[i]!=' ')
5640 {
5641 p[j++]=p[i];
5642 continue;
5643 }
5644
5645 p[j++]=' ';
5646
5647 for(++i;;++i)
5648 if(p[i]!=' ')
5649 {
5650 p[j++]=p[i];
5651 break;
5652 }
5653 }
5654
5655 p[j]='\0';
5656
5657 thys->Len = j;
5658
5659 if(!MAJSTRGETLEN(thys))
5660 return ajFalse;
5661
5662 return ret;
5663 }
5664
5665
5666
5667
5668 /* @func ajStrRemoveWhiteSpaces ***********************************************
5669 **
5670 ** Removes excess space characters from a string.
5671 **
5672 ** Leading/trailing whitespace removed. Multiple spaces replaced by single
5673 ** spaces. Tabs converted to spaces. Newlines left unchanged
5674 **
5675 ** @param [u] Pstr [AjPStr *] String to clean.
5676 ** @return [AjBool] ajTrue if string was reallocated
5677 **
5678 ** @release 4.1.0
5679 ** @@
5680 ******************************************************************************/
5681
ajStrRemoveWhiteSpaces(AjPStr * Pstr)5682 AjBool ajStrRemoveWhiteSpaces(AjPStr* Pstr)
5683 {
5684 AjBool ret = ajFalse;
5685 AjPStr thys;
5686
5687 size_t i = 0;
5688 size_t j = 0;
5689 size_t len;
5690 char *p;
5691
5692 if(!*Pstr)
5693 *Pstr = ajStrNewResLenC("", 1, 0);
5694 else if((*Pstr)->Use > 1)
5695 ajStrGetuniqueStr(Pstr);
5696
5697 thys = *Pstr;
5698
5699 p = thys->Ptr;
5700
5701 /* if string was already empty, no need to do anything */
5702
5703 len = thys->Len;
5704
5705 if(!len)
5706 return ajFalse;
5707
5708 /* tabs converted to spaces */
5709
5710 for(i=0;i<len;++i)
5711 if(p[i]=='\t')
5712 p[i]=' ';
5713
5714 /* remove leading spaces */
5715
5716 i = 0;
5717
5718 while(p[i])
5719 {
5720 if(p[i]!=' ')
5721 break;
5722
5723 ++i;
5724 --len;
5725 }
5726
5727 if(i)
5728 {
5729 len++;
5730 memmove(p,&p[i], len);
5731 len=strlen(p);
5732
5733 if(!len)
5734 { /* if that emptied it, so be it */
5735 thys->Len = 0;
5736
5737 return ajFalse;
5738 }
5739 }
5740
5741 /* remove newline at the end (if any) */
5742
5743 if(p[len-1]=='\n')
5744 {
5745 --len;
5746 p[len]='\0';
5747 }
5748
5749 if(!len)
5750 { /* if that emptied it, so be it */
5751 thys->Len = 0;
5752
5753 return ajFalse;
5754 }
5755
5756 /* clean up any space at the end */
5757
5758 for(i=len;i>0;--i)
5759 if(p[i-1]!=' ')
5760 break;
5761
5762 p[i]='\0';
5763
5764 len=strlen(p);
5765
5766 for(i=j=0;i<len;++i)
5767 {
5768 if(p[i]!=' ')
5769 {
5770 p[j++]=p[i];
5771 continue;
5772 }
5773
5774 p[j++]=' ';
5775
5776 for(++i;;++i)
5777 if(p[i]!=' ')
5778 {
5779 p[j++]=p[i];
5780 break;
5781 }
5782 }
5783
5784 p[j]='\0';
5785
5786 thys->Len = j;
5787
5788 if(!MAJSTRGETLEN(thys))
5789 return ajFalse;
5790
5791 return ret;
5792 }
5793
5794
5795
5796
5797 /* @func ajStrRemoveWild ******************************************************
5798 **
5799 ** Removes all characters after the first wildcard character (if found).
5800 **
5801 ** @param [u] Pstr [AjPStr*] String
5802 ** @return [AjBool] ajTrue if the string contained a wildcard and was
5803 ** truncated.
5804 **
5805 ** @release 4.0.0
5806 ** @@
5807 ******************************************************************************/
5808
ajStrRemoveWild(AjPStr * Pstr)5809 AjBool ajStrRemoveWild(AjPStr* Pstr)
5810 {
5811 char* cp;
5812 AjPStr thys;
5813
5814 if(!*Pstr)
5815 *Pstr = ajStrNewResLenC("", 1, 0);
5816 else if((*Pstr)->Use > 1)
5817 ajStrGetuniqueStr(Pstr);
5818
5819 thys = *Pstr;
5820
5821 cp = thys->Ptr;
5822
5823 while(*cp)
5824 {
5825 switch(*cp)
5826 {
5827 case '?':
5828 case '*':
5829 *cp = '\0';
5830 thys->Len = cp - thys->Ptr;
5831 return ajTrue;
5832 default:
5833 cp++;
5834 }
5835 }
5836
5837 return ajFalse;
5838 }
5839
5840
5841
5842
5843 /* @func ajStrTrimC ***********************************************************
5844 **
5845 ** Removes regions with a given character composition from start and end of a
5846 ** string.
5847 **
5848 ** @param [u] Pstr [AjPStr*] string
5849 ** @param [r] txt [const char*] Characters to delete from each end
5850 ** @return [AjBool] ajTrue if string was reallocated
5851 **
5852 ** @release 1.0.0
5853 ** @@
5854 ******************************************************************************/
5855
ajStrTrimC(AjPStr * Pstr,const char * txt)5856 AjBool ajStrTrimC(AjPStr* Pstr, const char* txt)
5857 {
5858 AjPStr thys;
5859 const char* cp;
5860 size_t i;
5861
5862 if(!*Pstr)
5863 *Pstr = ajStrNewResLenC("", 1, 0);
5864 else if((*Pstr)->Use > 1)
5865 ajStrGetuniqueStr(Pstr);
5866
5867 thys = *Pstr;
5868
5869 cp = thys->Ptr;
5870 i = strspn(cp, txt);
5871
5872 if(i)
5873 {
5874 thys->Len -= i;
5875
5876 if(thys->Len)
5877 memmove(thys->Ptr, &thys->Ptr[i], thys->Len);
5878 else
5879 *thys->Ptr = '\0';
5880 }
5881
5882 if(i)
5883 thys->Ptr[thys->Len] = '\0';
5884
5885 if(!thys->Len)
5886 return ajFalse;
5887
5888
5889 cp = &thys->Ptr[thys->Len-1];
5890 i = 0;
5891
5892 while(thys->Len && strchr(txt, *cp))
5893 {
5894 i++;
5895 thys->Len--;
5896
5897 if(thys->Len)
5898 cp--;
5899 }
5900
5901 if(i)
5902 thys->Ptr[thys->Len] = '\0';
5903
5904 return ajTrue;
5905 }
5906
5907
5908
5909
5910 /* @func ajStrTrimEndC ********************************************************
5911 **
5912 ** Removes a region with a given character composition from end of a string.
5913 **
5914 ** @param [u] Pstr [AjPStr*] string
5915 ** @param [r] txt [const char*] Characters to delete from the end
5916 ** @return [AjBool] ajTrue if string was reallocated
5917 **
5918 ** @release 2.3.1
5919 ** @@
5920 ******************************************************************************/
5921
ajStrTrimEndC(AjPStr * Pstr,const char * txt)5922 AjBool ajStrTrimEndC(AjPStr* Pstr, const char* txt)
5923 {
5924 AjPStr thys;
5925 const char* cp;
5926 size_t i;
5927
5928 if(!*Pstr)
5929 *Pstr = ajStrNewResLenC("", 1, 0);
5930 else if((*Pstr)->Use > 1)
5931 ajStrGetuniqueStr(Pstr);
5932
5933 thys = *Pstr;
5934
5935 if(!thys->Len)
5936 return ajFalse;
5937
5938 cp = &thys->Ptr[thys->Len-1];
5939 i = 0;
5940
5941 while(thys->Len && strchr(txt, *cp))
5942 {
5943 i++;
5944 thys->Len--;
5945
5946 if(thys->Len)
5947 cp--;
5948 }
5949
5950 if(i)
5951 thys->Ptr[thys->Len] = '\0';
5952
5953 return ajTrue;
5954 }
5955
5956
5957
5958
5959 /* @func ajStrTrimStartC ******************************************************
5960 **
5961 ** Removes a region with a given character composition from start of a string.
5962 **
5963 ** @param [u] Pstr [AjPStr*] string
5964 ** @param [r] txt [const char*] Characters to delete from the end
5965 ** @return [AjBool] ajTrue if string was reallocated
5966 **
5967 ** @release 3.0.0
5968 ** @@
5969 ******************************************************************************/
5970
ajStrTrimStartC(AjPStr * Pstr,const char * txt)5971 AjBool ajStrTrimStartC(AjPStr* Pstr, const char* txt)
5972 {
5973 AjPStr thys;
5974 const char* cp;
5975 size_t i;
5976
5977 if(!*Pstr)
5978 *Pstr = ajStrNewResLenC("", 1, 0);
5979 else if((*Pstr)->Use > 1)
5980 ajStrGetuniqueStr(Pstr);
5981
5982 thys = *Pstr;
5983
5984 if(!thys->Len)
5985 return ajFalse;
5986
5987 cp = thys->Ptr;
5988 i = 0;
5989
5990 while(thys->Len && strchr(txt, *cp))
5991 {
5992 i++;
5993 thys->Len--;
5994 cp++;
5995 }
5996
5997 if(i)
5998 memmove(thys->Ptr, &thys->Ptr[i], thys->Len+1);
5999
6000 return ajTrue;
6001 }
6002
6003
6004
6005
6006 /* @func ajStrTrimWhite *******************************************************
6007 **
6008 ** Removes regions composed of white space characters only from the start and
6009 ** end of a string.
6010 **
6011 ** @param [u] Pstr [AjPStr*] String
6012 ** @return [AjBool] ajTrue if string was reallocated
6013 **
6014 ** @release 4.0.0
6015 ** @@
6016 ******************************************************************************/
6017
ajStrTrimWhite(AjPStr * Pstr)6018 AjBool ajStrTrimWhite(AjPStr* Pstr)
6019 {
6020 return ajStrTrimC(Pstr, "\t \n\r");
6021 }
6022
6023
6024
6025
6026 /* @func ajStrTrimWhiteEnd ****************************************************
6027 **
6028 ** Removes regions composed of white space characters only from the end of a
6029 ** string.
6030 **
6031 ** @param [u] Pstr [AjPStr*] String
6032 ** @return [AjBool] ajTrue if string was reallocated
6033 **
6034 ** @release 4.0.0
6035 ** @@
6036 ******************************************************************************/
6037
ajStrTrimWhiteEnd(AjPStr * Pstr)6038 AjBool ajStrTrimWhiteEnd(AjPStr* Pstr)
6039 {
6040 return ajStrTrimEndC(Pstr, "\t \n\r");
6041 }
6042
6043
6044
6045
6046 /* @func ajStrTrimWhiteStart **************************************************
6047 **
6048 ** Removes regions composed of white space characters only from the start of a
6049 ** string.
6050 **
6051 ** @param [u] Pstr [AjPStr*] String
6052 ** @return [AjBool] ajTrue if string was reallocated
6053 **
6054 ** @release 6.2.0
6055 ** @@
6056 ******************************************************************************/
6057
ajStrTrimWhiteStart(AjPStr * Pstr)6058 AjBool ajStrTrimWhiteStart(AjPStr* Pstr)
6059 {
6060 return ajStrTrimStartC(Pstr, "\t \n\r");
6061 }
6062
6063
6064
6065
6066 /* @func ajStrTruncateLen *****************************************************
6067 **
6068 ** Removes the end from a string reducing it to a defined length.
6069 **
6070 ** @param [u] Pstr [AjPStr*] Target string
6071 ** @param [r] len [size_t] Length of required string.
6072 **
6073 ** @return [AjBool] ajTrue if string was reallocated
6074 **
6075 ** @release 4.0.0
6076 ** @@
6077 ******************************************************************************/
6078
ajStrTruncateLen(AjPStr * Pstr,size_t len)6079 AjBool ajStrTruncateLen(AjPStr* Pstr, size_t len)
6080 {
6081 AjPStr thys;
6082 AjBool ret = ajFalse;
6083
6084 if(!*Pstr)
6085 {
6086 ret = ajTrue;
6087 *Pstr = ajStrNewResLenC("", 1, 0);
6088 }
6089 else if((*Pstr)->Use > 1)
6090 {
6091 ret = ajTrue;
6092 ajStrGetuniqueStr(Pstr);
6093 }
6094
6095 thys = *Pstr;
6096
6097 if(len >= thys->Len)
6098 return ret;
6099
6100 thys->Ptr[len] = '\0';
6101 thys->Len = len;
6102
6103 return ret;
6104 }
6105
6106
6107
6108
6109 /* @func ajStrTruncatePos *****************************************************
6110 **
6111 ** Removes the end from a string by cutting at a defined position.
6112 **
6113 ** @param [u] Pstr [AjPStr*] target string
6114 ** @param [r] pos [ajlong] First position to be deleted. Negative values
6115 ** count from the end
6116 ** @return [AjBool] True is string was reallocated
6117 **
6118 ** @release 4.0.0
6119 ** @@
6120 ******************************************************************************/
6121
ajStrTruncatePos(AjPStr * Pstr,ajlong pos)6122 AjBool ajStrTruncatePos(AjPStr* Pstr, ajlong pos)
6123 {
6124 AjPStr thys = NULL;
6125 size_t ibegin;
6126
6127 if(!*Pstr)
6128 *Pstr = ajStrNewResLenC("", 1, 0);
6129 else if((*Pstr)->Use > 1)
6130 ajStrGetuniqueStr(Pstr);
6131
6132 thys = *Pstr;
6133
6134 ibegin = 1 + ajCvtSposToPosStart(thys->Len, 0, pos);
6135 thys->Ptr[ibegin] = '\0';
6136 thys->Len = ibegin;
6137
6138 return ajTrue;
6139 }
6140
6141
6142
6143
6144 /* @section substitution ******************************************************
6145 **
6146 ** Functions for substitutions of characters or regions (substrings)
6147 ** within a string.
6148 **
6149 ** @fdata [AjPStr]
6150 ** @fnote None.
6151 **
6152 ** @nam3rule Exchange Substitute substrings in a string with other
6153 ** strings.
6154 ** @nam3rule Random Randomly rearrange characters.
6155 ** @nam3rule Reverse Reverse order of characters.
6156 ** @nam4rule ExchangePos Substitute character(s) at a set position
6157 ** @nam4rule ExchangeSet Substitute character(s) in a string with
6158 ** other character(s).
6159 ** @nam5rule ExchangeSetRest Substitute character(s) in a string with
6160 ** other character(s).
6161 **
6162 ** @argrule * Pstr [AjPStr*] String to be edited
6163 ** @argrule Pos ipos [ajlong] String position to be edited
6164 ** @arg1rule C txt [const char*] Text to be replaced
6165 ** @arg1rule K chr [char] Text to be replaced
6166 ** @arg1rule S str [const AjPStr] Text to be replaced
6167 ** @arg2rule C txtnew [const char*] New text
6168 ** @arg2rule K chrnew [char] New text
6169 ** @arg2rule S strnew [const AjPStr] New text
6170 **
6171 ** @valrule * [AjBool] True if string was reallocated
6172 **
6173 ** @fcategory modify
6174 */
6175
6176
6177
6178
6179 /* @func ajStrExchangeCC ******************************************************
6180 **
6181 ** Replace all occurrences in a string of one substring with another.
6182 **
6183 ** @param [u] Pstr [AjPStr*] Target string.
6184 ** @param [r] txt [const char*] string to replace.
6185 ** @param [r] txtnew [const char*] string to insert.
6186 ** @return [AjBool] ajTrue if string was reallocated
6187 **
6188 ** @release 4.0.0
6189 ** @@
6190 ******************************************************************************/
6191
ajStrExchangeCC(AjPStr * Pstr,const char * txt,const char * txtnew)6192 AjBool ajStrExchangeCC(AjPStr* Pstr, const char* txt,
6193 const char* txtnew)
6194 {
6195 ajlong findpos = 0;
6196 size_t tlen;
6197 size_t newlen;
6198 ajlong lastpos = 0; /* make sure we don't loop forever */
6199 AjPStr thys;
6200 const char* cp;
6201
6202 if(!txt || !txtnew)
6203 return ajFalse;
6204
6205 tlen = strlen(txt);
6206 newlen = strlen(txtnew);
6207
6208 if(!tlen && !newlen)
6209 return ajFalse;
6210
6211 thys = *Pstr;
6212
6213 if(*txt)
6214 {
6215 findpos = ajStrFindC(thys, txt);
6216 if(findpos < 0)
6217 return ajFalse;
6218
6219 cp = strstr(&thys->Ptr[lastpos], txt);
6220
6221 while(cp)
6222 {
6223 findpos = cp - &thys->Ptr[lastpos];
6224
6225 if(findpos < ((ajlong)thys->Len - lastpos))
6226 {
6227 lastpos += findpos;
6228 ajStrCutRange(Pstr,lastpos,lastpos+tlen-1);
6229 ajStrInsertC(Pstr,lastpos,txtnew);
6230 lastpos += newlen;
6231 ajDebug("new lastpos %Ld len %Ld\n",
6232 lastpos, (ajlong) thys->Len);
6233 }
6234
6235 cp = strstr(&thys->Ptr[lastpos], txt);
6236
6237 }
6238 }
6239
6240 return ajTrue;
6241 }
6242
6243
6244
6245
6246 /* @func ajStrExchangeCS ******************************************************
6247 **
6248 ** Replace all occurrences in a string of one substring with another.
6249 **
6250 ** @param [u] Pstr [AjPStr*] Target string.
6251 ** @param [r] txt [const char*] string to replace.
6252 ** @param [r] strnew [const AjPStr] string to insert.
6253 ** @return [AjBool] ajTrue if string was reallocated
6254 **
6255 ** @release 4.0.0
6256 ** @@
6257 ******************************************************************************/
6258
ajStrExchangeCS(AjPStr * Pstr,const char * txt,const AjPStr strnew)6259 AjBool ajStrExchangeCS(AjPStr* Pstr, const char* txt,
6260 const AjPStr strnew)
6261 {
6262 AjBool cycle = ajTrue;
6263 ajlong findpos = 0;
6264 size_t tlen;
6265 size_t newlen;
6266 ajlong lastpos = 0; /* make sure we don't loop forever */
6267
6268 if(!txt || !strnew)
6269 return ajFalse;
6270
6271 tlen = strlen(txt);
6272 newlen = strnew->Len;
6273
6274 if(!tlen && !newlen)
6275 return ajFalse;
6276
6277 if(*txt)
6278 {
6279 while(cycle)
6280 {
6281 findpos = ajStrFindC(*Pstr, txt);
6282
6283 if(findpos >= lastpos)
6284 {
6285 ajStrCutRange(Pstr,findpos,findpos+tlen-1);
6286 ajStrInsertS(Pstr,findpos,strnew);
6287 lastpos = findpos+newlen;
6288 }
6289 else
6290 cycle = ajFalse;
6291 }
6292 }
6293
6294 return ajTrue;
6295 }
6296
6297
6298
6299
6300 /* @func ajStrExchangeKK ******************************************************
6301 **
6302 ** Replace all occurrences in a string of one character with another.
6303 **
6304 ** @param [u] Pstr [AjPStr*] Target string.
6305 ** @param [r] chr [char] Character to replace.
6306 ** @param [r] chrnew [char] Character to insert.
6307 ** @return [AjBool] ajTrue if string was reallocated
6308 **
6309 ** @release 4.0.0
6310 ** @@
6311 ******************************************************************************/
6312
ajStrExchangeKK(AjPStr * Pstr,char chr,char chrnew)6313 AjBool ajStrExchangeKK(AjPStr* Pstr, char chr, char chrnew)
6314 {
6315 AjBool ret = ajFalse;
6316 AjPStr thys;
6317 char* cp;
6318
6319 if(!*Pstr)
6320 *Pstr = ajStrNewResLenC("", 1, 0);
6321 else if((*Pstr)->Use > 1)
6322 ajStrGetuniqueStr(Pstr);
6323
6324 thys = *Pstr;
6325
6326 cp = thys->Ptr;
6327
6328 while(*cp)
6329 {
6330 if(*cp == chr)
6331 *cp = chrnew;
6332
6333 cp++;
6334 }
6335
6336 return ret;
6337 }
6338
6339
6340
6341
6342 /* @func ajStrExchangeSC ******************************************************
6343 **
6344 ** Replace all occurrences in a string of one substring with another.
6345 **
6346 **
6347 ** @param [u] Pstr [AjPStr*] Target string.
6348 ** @param [r] str [const AjPStr] string to replace.
6349 ** @param [r] txtnew [const char*] string to insert.
6350 ** @return [AjBool] ajTrue if string was reallocated
6351 **
6352 ** @release 4.0.0
6353 ** @@
6354 ******************************************************************************/
6355
ajStrExchangeSC(AjPStr * Pstr,const AjPStr str,const char * txtnew)6356 AjBool ajStrExchangeSC(AjPStr* Pstr, const AjPStr str,
6357 const char* txtnew)
6358 {
6359 AjBool cycle = ajTrue;
6360 ajlong findpos = 0;
6361
6362 if(!str || !txtnew)
6363 return ajFalse;
6364
6365 if(str->Len)
6366 {
6367 while(cycle)
6368 {
6369 findpos = ajStrFindS(*Pstr, str);
6370
6371 if(findpos >= 0)
6372 {
6373 ajStrCutRange(Pstr,findpos,findpos+str->Len-1);
6374 ajStrInsertC(Pstr,findpos,txtnew);
6375 }
6376 else
6377 cycle = ajFalse;
6378 }
6379 }
6380
6381 return ajTrue;
6382 }
6383
6384
6385
6386
6387 /* @func ajStrExchangeSS ******************************************************
6388 **
6389 ** Replace all occurrences in a string of one substring with another.
6390 **
6391 ** @param [u] Pstr [AjPStr*] Target string.
6392 ** @param [r] str [const AjPStr] string to replace.
6393 ** @param [r] strnew [const AjPStr] string to insert.
6394 ** @return [AjBool] ajTrue if string was reallocated
6395 **
6396 ** @release 4.0.0
6397 ** @@
6398 ******************************************************************************/
6399
ajStrExchangeSS(AjPStr * Pstr,const AjPStr str,const AjPStr strnew)6400 AjBool ajStrExchangeSS(AjPStr* Pstr, const AjPStr str, const AjPStr strnew)
6401 {
6402 AjBool cycle = ajTrue;
6403 ajlong findpos = 0;
6404
6405 if(!str || !strnew)
6406 return ajFalse;
6407
6408 if(str->Len !=0)
6409 {
6410 while(cycle)
6411 {
6412 findpos = ajStrFindC(*Pstr, str->Ptr);
6413
6414 if(findpos >= 0)
6415 {
6416 ajStrCutRange(Pstr,findpos,findpos+str->Len-1);
6417 ajStrInsertS(Pstr,findpos,strnew);
6418 }
6419 else
6420 cycle = ajFalse;
6421 }
6422 }
6423
6424 return ajTrue;
6425 }
6426
6427
6428
6429
6430 /* @func ajStrExchangePosCC ***************************************************
6431 **
6432 ** Replace one substring with another at a given position in the text.
6433 **
6434 ** @param [u] Pstr [AjPStr*] Target string.
6435 ** @param [r] ipos [ajlong] Position in the string, negative values are
6436 ** from the end of the string.
6437 ** @param [r] txt [const char*] string to replace.
6438 ** @param [r] txtnew [const char*] string to insert.
6439 ** @return [AjBool] ajTrue if string was reallocated
6440 **
6441 ** @release 5.0.0
6442 ** @@
6443 ******************************************************************************/
6444
ajStrExchangePosCC(AjPStr * Pstr,ajlong ipos,const char * txt,const char * txtnew)6445 AjBool ajStrExchangePosCC(AjPStr* Pstr, ajlong ipos, const char* txt,
6446 const char* txtnew)
6447 {
6448 size_t tlen;
6449 ajlong jpos;
6450
6451 if(!txt || !txtnew)
6452 return ajFalse;
6453
6454 tlen = strlen(txt);
6455 jpos = ajCvtSposToPosStart((*Pstr)->Len, 0, ipos);
6456
6457 if(ajCharPrefixC(&(*Pstr)->Ptr[jpos], txt))
6458 {
6459 ajStrCutRange(Pstr,jpos,jpos+tlen-1);
6460 ajStrInsertC(Pstr,jpos,txtnew);
6461 }
6462
6463 return ajTrue;
6464 }
6465
6466
6467
6468
6469 /* @func ajStrExchangeSetCC ***************************************************
6470 **
6471 ** Replace all occurrences in a string of one set of characters with another
6472 ** set.
6473 **
6474 ** @param [w] Pstr [AjPStr*] String
6475 ** @param [r] txt [const char*] Unwanted characters
6476 ** @param [r] txtnew [const char*] Replacement characters
6477 ** @return [AjBool] ajTrue if string was reallocated
6478 **
6479 ** @release 4.0.0
6480 ** @@
6481 ******************************************************************************/
6482
ajStrExchangeSetCC(AjPStr * Pstr,const char * txt,const char * txtnew)6483 AjBool ajStrExchangeSetCC(AjPStr* Pstr, const char* txt, const char* txtnew)
6484 {
6485 char filter[256] = {'\0'}; /* should make all zero */
6486 size_t i;
6487 size_t ilen;
6488
6489 const char *co = NULL;
6490 const char *cn;
6491 char* cp;
6492 AjPStr thys;
6493
6494 if(!txt || !txtnew)
6495 return ajFalse;
6496
6497 if(ajStrFindAnyC(*Pstr, txt) < 0)
6498 return ajFalse;
6499
6500 i = strlen(txtnew);
6501
6502 if(strlen(txt) > i)
6503 ajErr("ajStrExchangeSetCC new char set '%s' shorter than old '%s'",
6504 txt, txtnew);
6505 if(!*Pstr)
6506 *Pstr = ajStrNewResLenC("", 1, 0);
6507 else if((*Pstr)->Use > 1)
6508 ajStrGetuniqueStr(Pstr);
6509
6510 thys = *Pstr;
6511
6512 cp = thys->Ptr;
6513 ilen = thys->Len;
6514 i = strcspn(cp, txt);
6515 while(i < ilen)
6516 {
6517 if(!co)
6518 {
6519 co = txt;
6520 cn = txtnew;
6521 while(*co)
6522 {
6523 if(!*cn) /* oops, too short, use first */
6524 filter[(ajint)*co++] = *txtnew;
6525 else
6526 filter[(ajint)*co++] = *cn++;
6527 }
6528 }
6529 cp += i++;
6530 *cp = filter[(ajint)*cp];
6531 ilen -= i;
6532 i = strcspn(++cp, txt);
6533 }
6534
6535 /*
6536 for(cp = thys->Ptr; *cp; cp++)
6537 if(filter[(ajint)*cp])
6538 *cp = filter[(ajint)*cp];
6539 */
6540 return ajTrue;
6541 }
6542
6543
6544
6545
6546 /* @func ajStrExchangeSetSS ***************************************************
6547 **
6548 ** Replace all occurrences in a string of one set of characters with another
6549 ** set.
6550 **
6551 ** @param [w] Pstr [AjPStr*] String
6552 ** @param [r] str [const AjPStr] Unwanted characters
6553 ** @param [r] strnew [const AjPStr] Replacement characters
6554 ** @return [AjBool] ajTrue if string was reallocated
6555 **
6556 ** @release 4.0.0
6557 ** @@
6558 ******************************************************************************/
6559
ajStrExchangeSetSS(AjPStr * Pstr,const AjPStr str,const AjPStr strnew)6560 AjBool ajStrExchangeSetSS(AjPStr* Pstr, const AjPStr str, const AjPStr strnew)
6561 {
6562 if(!str || !strnew)
6563 return ajFalse;
6564
6565 return ajStrExchangeSetCC(Pstr, str->Ptr, strnew->Ptr);
6566 }
6567
6568
6569
6570
6571 /* @func ajStrExchangeSetRestCK ***********************************************
6572 **
6573 ** Replace all occurrences in a string of one set of characters with
6574 ** a substitute character
6575 **
6576 ** @param [w] Pstr [AjPStr*] String
6577 ** @param [r] txt [const char*] Wanted characters
6578 ** @param [r] chrnew [char] Replacement character
6579 ** @return [AjBool] ajTrue if string was reallocated
6580 **
6581 ** @release 4.1.0
6582 ** @@
6583 ******************************************************************************/
6584
ajStrExchangeSetRestCK(AjPStr * Pstr,const char * txt,char chrnew)6585 AjBool ajStrExchangeSetRestCK(AjPStr* Pstr, const char* txt, char chrnew)
6586 {
6587 char filter[256] = {'\0'}; /* should make all zero */
6588
6589 const char *co;
6590 char* cp;
6591 AjPStr thys;
6592
6593 if(!txt)
6594 return ajFalse;
6595
6596 /*ajDebug("ajStrExchangeSetRestCK '%s' => '%c' for '%S\n",
6597 txt, chrnew, *Pstr);*/
6598 co = txt;
6599
6600 if(!*Pstr)
6601 *Pstr = ajStrNewResLenC("", 1, 0);
6602 else if((*Pstr)->Use > 1)
6603 ajStrGetuniqueStr(Pstr);
6604
6605 thys = *Pstr;
6606
6607 while(*co)
6608 {
6609 filter[(ajint)toupper((int)*co)] = '1';
6610 filter[(ajint)tolower((int)*co++)] = '1';
6611 }
6612
6613 for(cp = thys->Ptr; *cp; cp++)
6614 if(!filter[(ajint)*cp])
6615 *cp = chrnew;
6616
6617 /*ajDebug("ajStrExchangeSetRestCK returns '%S\n",
6618 *Pstr);*/
6619 return ajTrue;
6620 }
6621
6622
6623
6624
6625 /* @func ajStrExchangeSetRestSK ***********************************************
6626 **
6627 ** Replace all occurrences in a string not in one set of characters with
6628 ** a substitute character.
6629 **
6630 ** @param [w] Pstr [AjPStr*] String
6631 ** @param [r] str [const AjPStr] Wanted characters
6632 ** @param [r] chrnew [char] Replacement character
6633 ** @return [AjBool] ajTrue if string was reallocated
6634 **
6635 ** @release 4.1.0
6636 ** @@
6637 ******************************************************************************/
6638
ajStrExchangeSetRestSK(AjPStr * Pstr,const AjPStr str,char chrnew)6639 AjBool ajStrExchangeSetRestSK(AjPStr* Pstr, const AjPStr str,
6640 char chrnew)
6641 {
6642 if(!str)
6643 return ajFalse;
6644
6645 return ajStrExchangeSetRestCK(Pstr, str->Ptr, chrnew);
6646 }
6647
6648
6649
6650
6651 /* @func ajStrRandom **********************************************************
6652 **
6653 ** Randomly rearranges the characters in a string.
6654 **
6655 ** The application code must first call ajRandomSeed().
6656 **
6657 ** @param [u] Pstr [AjPStr *] string
6658 **
6659 ** @return [AjBool] True unless string is empty
6660 **
6661 ** @release 1.0.0
6662 ** @@
6663 ******************************************************************************/
6664
ajStrRandom(AjPStr * Pstr)6665 AjBool ajStrRandom(AjPStr* Pstr)
6666 {
6667 AjPStr copy = NULL;
6668 AjPStr thys;
6669 const char *p;
6670 char *q;
6671
6672 ajuint *rn = NULL;
6673 ajuint *na = NULL;
6674
6675 size_t len;
6676 size_t i;
6677
6678 if(!*Pstr)
6679 *Pstr = ajStrNewResLenC("", 1, 0);
6680 else if((*Pstr)->Use > 1)
6681 ajStrGetuniqueStr(Pstr);
6682
6683 thys = *Pstr;
6684
6685 ajStrAssignS(©, thys);
6686 p=copy->Ptr;
6687 q=thys->Ptr;
6688
6689 len = thys->Len;
6690 AJCNEW(na, len);
6691 AJCNEW(rn, len);
6692
6693 for(i=0;i<len;++i)
6694 {
6695 na[i] = i;
6696 rn[i] = ajRandomNumber();
6697 }
6698
6699 ajSortUintIncI(rn,na,len);
6700
6701 for(i=0;i<len;++i)
6702 q[i] = p[na[i]];
6703
6704 AJFREE(na);
6705 AJFREE(rn);
6706 ajStrDel(©);
6707
6708
6709 if(!thys->Len)
6710 return ajFalse;
6711
6712 return ajTrue;
6713 }
6714
6715
6716
6717
6718 /* @func ajStrReverse *********************************************************
6719 **
6720 ** Reverses the order of characters in a string
6721 **
6722 ** @param [w] Pstr [AjPStr*] Target string
6723 ** @return [AjBool] ajTrue if string was reallocated
6724 **
6725 ** @release 4.0.0
6726 ** @@
6727 ******************************************************************************/
6728
ajStrReverse(AjPStr * Pstr)6729 AjBool ajStrReverse(AjPStr* Pstr)
6730 {
6731 AjBool ret = ajFalse;
6732 char *cp;
6733 char *cq;
6734 char tmp;
6735 AjPStr thys;
6736
6737 if(!*Pstr)
6738 *Pstr = ajStrNewResLenC("", 1, 0);
6739 else if((*Pstr)->Use > 1)
6740 ajStrGetuniqueStr(Pstr);
6741
6742 thys = *Pstr;
6743
6744 cp = thys->Ptr;
6745 cq = cp + thys->Len - 1;
6746
6747 while(cp < cq)
6748 {
6749 tmp = *cp;
6750 *cp = *cq;
6751 *cq = tmp;
6752 cp++;
6753 cq--;
6754 }
6755
6756 return ret;
6757 }
6758
6759
6760
6761
6762 /* @section query *************************************************************
6763 **
6764 ** Functions for querying the properties of strings.
6765 **
6766 ** @fdata [AjPStr]
6767 ** @fnote None.
6768 ** @nam3rule Calc Calculate a value (not in categories above) derived from
6769 ** elements of a string object.
6770 ** @nam4rule CalcCount Counts occurrence of character(s) in string.
6771 ** @nam4rule CalcWhole Tests whether range refers to whole string.
6772 ** @nam3rule Has Check whether string contains certain character(s).
6773 ** @nam4rule HasParentheses Contains parentheses.
6774 ** @nam4rule HasWild Contains wildcard character(s).
6775 ** @nam3rule Is Check whether string value represents a datatype or is
6776 ** of a certain character composition.
6777 ** @nam4rule IsAlnum Alphanumeric characters only.
6778 ** @nam4rule IsAlpha Alphabetic characters only.
6779 ** @nam4rule IsBool Represents Boolean value.
6780 ** @nam4rule IsCharset Specified characters only.
6781 ** @nam5rule IsCharsetCase Specified characters only.
6782 ** @nam4rule IsDouble Represents double value.
6783 ** @nam4rule IsFilter Characters defined in filter only
6784 ** @nam4rule IsFloat Represents float value.
6785 ** @nam4rule IsHex Represents hex value.
6786 ** @nam4rule IsInt Represents integer value.
6787 ** @nam4rule IsLong Represents long value.
6788 ** @nam4rule IsLower No upper case alphabetic characters.
6789 ** @nam4rule IsNum Decimal digits only.
6790 ** @nam4rule IsUpper No lower case alphabetic characters.
6791 ** @nam4rule IsWhite Whitespace characters only.
6792 ** @nam4rule IsWild One or more wildcard characters.
6793 ** @nam4rule IsWord Non-whitespace characters only.
6794 ** @nam3rule Whole Specified range covers whole string.
6795 **
6796 ** @argrule * str [const AjPStr] String
6797 ** @arg2rule S str2 [const AjPStr] String
6798 ** @argrule Whole pos1 [ajlong] Start position, negative values count from end
6799 ** @argrule Whole pos2 [ajlong] End position, negative values count from end
6800 ** @argrule CountC txt [const char*] Text to count
6801 ** @argrule CountK chr [char] Character to count
6802 ** @argrule IsCharsetC txt [const char*] Characters to test
6803 ** @argrule IsCharsetS str2 [const AjPStr] Characters to test
6804 ** @argrule IsCharsetCaseC txt [const char*] Characters to test
6805 ** @argrule IsCharsetCaseS str2 [const AjPStr] Characters to test
6806 ** @argrule IsFilter filter [const char*] Filter non-zero for characters to test
6807 **
6808 ** @valrule * [AjBool] Result of query
6809 ** @valrule *Count [ajulong] Number of occurrences
6810 **
6811 ** @fcategory use
6812 */
6813
6814
6815
6816
6817 /* @func ajStrCalcCountC ******************************************************
6818 **
6819 ** Counts occurrences of set of characters in a string.
6820 **
6821 ** @param [r] str [const AjPStr] String
6822 ** @param [r] txt [const char*] Characters to count
6823 ** @return [ajulong] Number of times characters were found in string
6824 **
6825 ** @release 4.0.0
6826 ******************************************************************************/
6827
ajStrCalcCountC(const AjPStr str,const char * txt)6828 ajulong ajStrCalcCountC(const AjPStr str, const char* txt)
6829 {
6830 ajulong ret = 0;
6831 const char* cp;
6832
6833 cp = txt;
6834
6835 while(*cp)
6836 {
6837 ret += ajStrCalcCountK(str, *cp);
6838 ++cp;
6839 }
6840
6841 return ret;
6842 }
6843
6844
6845
6846
6847 /* @func ajStrCalcCountK ******************************************************
6848 **
6849 ** Counts occurrences of a character in a string.
6850 **
6851 ** @param [r] str [const AjPStr] String
6852 ** @param [r] chr [char] Character to count
6853 ** @return [ajulong] Number of times character was found in string
6854 **
6855 ** @release 4.0.0
6856 ******************************************************************************/
6857
ajStrCalcCountK(const AjPStr str,char chr)6858 ajulong ajStrCalcCountK(const AjPStr str, char chr)
6859 {
6860 ajulong ret = 0;
6861 const char* cp;
6862
6863 cp = str->Ptr;
6864
6865 while(*cp)
6866 {
6867 if(*cp == chr) ret++;
6868 cp++;
6869 }
6870
6871 return ret;
6872 }
6873
6874
6875
6876
6877 /* @func ajStrHasParentheses **************************************************
6878 **
6879 ** Tests whether a string contains (possibly nested) pairs of parentheses.
6880 **
6881 ** Pairs of parentheses are difficult to test for with regular expressions.
6882 **
6883 ** @param [r] str [const AjPStr] String to test
6884 ** @return [AjBool] ajTrue if string has zero or more () pairs
6885 ** with possibly other text
6886 **
6887 ** @release 4.0.0
6888 ** @@
6889 ******************************************************************************/
6890
ajStrHasParentheses(const AjPStr str)6891 AjBool ajStrHasParentheses(const AjPStr str)
6892 {
6893 ajulong left = 0;
6894 const char *cp;
6895
6896 if(!str)
6897 return ajFalse;
6898
6899 cp = str->Ptr;
6900
6901 /* if string was already empty, no need to do anything */
6902
6903 while (*cp)
6904 {
6905 switch (*cp++)
6906 {
6907 case '(':
6908 left++;
6909 break;
6910 case ')':
6911 if (!left) return ajFalse;
6912 left--;
6913 break;
6914 default:
6915 break;
6916 }
6917 }
6918
6919 if (left)
6920 return ajFalse;
6921
6922 return ajTrue;
6923 }
6924
6925
6926
6927
6928 /* @func ajStrIsAlnum *********************************************************
6929 **
6930 ** Test whether a string contains alphanumeric characters only (no white
6931 ** space).
6932 **
6933 ** The test is defined by isalnum in the C RTL plus underscores.
6934 **
6935 ** @param [r] str [const AjPStr] String
6936 ** @return [AjBool] ajTrue if the string is entirely alphanumeric
6937 ** @cre an empty string returns ajFalse
6938 **
6939 ** @release 1.0.0
6940 ** @@
6941 ******************************************************************************/
6942
ajStrIsAlnum(const AjPStr str)6943 AjBool ajStrIsAlnum(const AjPStr str)
6944 {
6945 const char* cp;
6946
6947 if(!str)
6948 return ajFalse;
6949
6950 if(!str->Len)
6951 return ajFalse;
6952
6953 for(cp = str->Ptr;*cp;cp++)
6954 if(*cp != '_' && !isalnum((ajint)*cp))
6955 return ajFalse;
6956
6957 return ajTrue;
6958 }
6959
6960
6961
6962
6963 /* @func ajStrIsAlpha *********************************************************
6964 **
6965 ** Test whether a string contains alphabetic characters only (no white space).
6966 **
6967 ** Test is defined by isalpha in the C RTL.
6968 **
6969 ** @param [r] str [const AjPStr] String
6970 ** @return [AjBool] ajTrue if the string is entirely alphabetic
6971 ** @cre an empty string returns ajFalse
6972 **
6973 ** @release 1.0.0
6974 ** @@
6975 ******************************************************************************/
6976
ajStrIsAlpha(const AjPStr str)6977 AjBool ajStrIsAlpha(const AjPStr str)
6978 {
6979 const char* cp;
6980
6981 if(!str)
6982 return ajFalse;
6983
6984 if(!str->Len)
6985 return ajFalse;
6986
6987 cp = str->Ptr;
6988
6989 while(*cp)
6990 if(!isalpha((ajint)*cp++))
6991 return ajFalse;
6992
6993 return ajTrue;
6994 }
6995
6996
6997
6998
6999 /* @func ajStrIsBool **********************************************************
7000 **
7001 ** Tests whether a string represents a valid Boolean value.
7002 **
7003 ** The string must be a single character boolean value, or one of "yes, "no",
7004 ** "true" or "false".
7005 **
7006 ** @param [r] str [const AjPStr] String
7007 ** @return [AjBool] ajTrue if the string is acceptable as a boolean.
7008 ** @see ajStrToBool
7009 **
7010 ** @release 1.0.0
7011 ** @@
7012 ******************************************************************************/
7013
ajStrIsBool(const AjPStr str)7014 AjBool ajStrIsBool(const AjPStr str)
7015 {
7016 const char* cp;
7017
7018 if(!str)
7019 return ajFalse;
7020
7021 if(!str->Len)
7022 return ajFalse;
7023
7024 cp = str->Ptr;
7025
7026 if(!strchr("YyTt1NnFf0", *cp))
7027 return ajFalse;
7028
7029 if(str->Len == 1) /* one character only */
7030 return ajTrue;
7031
7032 /* longer strings - test they really match */
7033
7034 if(ajStrMatchCaseC(str, "yes"))
7035 return ajTrue;
7036
7037 if(ajStrMatchCaseC(str, "no"))
7038 return ajTrue;
7039
7040 if(ajStrMatchCaseC(str, "true"))
7041 return ajTrue;
7042
7043 if(ajStrMatchCaseC(str, "false"))
7044 return ajTrue;
7045
7046 return ajFalse;
7047 }
7048
7049
7050
7051
7052 /* @func ajStrIsCharsetC ******************************************************
7053 **
7054 ** Test whether a string contains specified characters only.
7055 **
7056 ** @param [r] str [const AjPStr] String
7057 ** @param [r] txt [const char*] Character set to test
7058 ** @return [AjBool] ajTrue if the string is entirely composed of characters
7059 ** in the specified set
7060 ** @cre an empty string returns ajFalse
7061 **
7062 ** @release 4.1.0
7063 ** @@
7064 ******************************************************************************/
7065
ajStrIsCharsetC(const AjPStr str,const char * txt)7066 AjBool ajStrIsCharsetC(const AjPStr str, const char* txt)
7067 {
7068 char filter[256] = {'\0'}; /* should make all zero */
7069 const char* cp;
7070 const char* cq;
7071
7072 if(!str)
7073 return ajFalse;
7074
7075 if(!str->Len)
7076 return ajFalse;
7077
7078 cq = txt;
7079
7080 while (*cq)
7081 filter[(int)*cq++] = 1;
7082
7083 cp = str->Ptr;
7084
7085 while(*cp)
7086 if(!filter[(int)*cp++])
7087 return ajFalse;
7088
7089 return ajTrue;
7090 }
7091
7092
7093
7094
7095 /* @func ajStrIsCharsetS ******************************************************
7096 **
7097 ** Test whether a string contains specified characters only.
7098 **
7099 ** @param [r] str [const AjPStr] String
7100 ** @param [r] str2 [const AjPStr] Character set to test
7101 ** @return [AjBool] ajTrue if the string is entirely composed of characters
7102 ** in the specified set
7103 ** @cre an empty string returns ajFalse
7104 **
7105 ** @release 4.1.0
7106 ** @@
7107 ******************************************************************************/
7108
ajStrIsCharsetS(const AjPStr str,const AjPStr str2)7109 AjBool ajStrIsCharsetS(const AjPStr str, const AjPStr str2)
7110 {
7111
7112 /*
7113 char filter[256] = {'\0'};
7114 const char* cp;
7115 const char* cq;
7116 */
7117 if(!str)
7118 return ajFalse;
7119
7120 if(!str->Len)
7121 return ajFalse;
7122
7123 if(!str2)
7124 return ajFalse;
7125
7126 /*
7127 cq = str2->Ptr;
7128
7129 while (*cq)
7130 filter[(int)*cq++] = 1;
7131
7132 cp = str->Ptr;
7133
7134 while(*cp)
7135 if(!filter[(int)*cp++])
7136 return ajFalse;
7137 */
7138
7139 if(strspn(str->Ptr, str2->Ptr) != str->Len)
7140 return ajFalse;
7141
7142 return ajTrue;
7143 }
7144
7145
7146
7147
7148 /* @func ajStrIsCharsetCaseC **************************************************
7149 **
7150 ** Test whether a string contains specified characters only.
7151 ** The test is case-insensitive
7152 **
7153 ** @param [r] str [const AjPStr] String
7154 ** @param [r] txt [const char*] Character set to test
7155 ** @return [AjBool] ajTrue if the string is entirely composed of characters
7156 ** in the specified set
7157 ** @cre an empty string returns ajFalse
7158 **
7159 ** @release 4.1.0
7160 ** @@
7161 ******************************************************************************/
7162
ajStrIsCharsetCaseC(const AjPStr str,const char * txt)7163 AjBool ajStrIsCharsetCaseC(const AjPStr str, const char* txt)
7164 {
7165 char filter[256] = {'\0'}; /* should make all zero */
7166 const char* cp;
7167 const char* cq = txt;
7168
7169 if(!str)
7170 return ajFalse;
7171
7172 if(!str->Len)
7173 return ajFalse;
7174
7175 while (*cq)
7176 {
7177 filter[tolower((int)*cq)] = 1;
7178 filter[toupper((int)*cq++)] = 1;
7179 }
7180
7181 cp = str->Ptr;
7182
7183 while(*cp)
7184 if(!filter[(int)*cp++])
7185 return ajFalse;
7186
7187 return ajTrue;
7188 }
7189
7190
7191
7192
7193 /* @func ajStrIsCharsetCaseS **************************************************
7194 **
7195 ** Test whether a string contains specified characters only.
7196 ** The test is case-insensitive
7197 **
7198 ** @param [r] str [const AjPStr] String
7199 ** @param [r] str2 [const AjPStr] Character set to test
7200 ** @return [AjBool] ajTrue if the string is entirely composed of characters
7201 ** in the specified set
7202 ** @cre an empty string returns ajFalse
7203 **
7204 ** @release 4.1.0
7205 ** @@
7206 ******************************************************************************/
7207
ajStrIsCharsetCaseS(const AjPStr str,const AjPStr str2)7208 AjBool ajStrIsCharsetCaseS(const AjPStr str, const AjPStr str2)
7209 {
7210 char filter[256] = {'\0'}; /* should make all zero */
7211 const char* cp;
7212 const char* cq;
7213
7214 if(!str)
7215 return ajFalse;
7216
7217 if(!str->Len)
7218 return ajFalse;
7219
7220 if(!str2)
7221 return ajFalse;
7222
7223 cq = str2->Ptr;
7224
7225 while (*cq)
7226 {
7227 filter[tolower((int)*cq)] = 1;
7228 filter[toupper((int)*cq++)] = 1;
7229 }
7230
7231 cp = str->Ptr;
7232
7233 while(*cp)
7234 if(!filter[(int)*cp++])
7235 return ajFalse;
7236
7237 return ajTrue;
7238 }
7239
7240
7241
7242
7243 /* @func ajStrIsDouble ********************************************************
7244 **
7245 ** Tests whether a string represents a valid double precision value,
7246 **
7247 ** Test uses the strtod call in the C RTL.
7248 **
7249 ** @param [r] str [const AjPStr] String
7250 ** @return [AjBool] ajTrue if the string is acceptable as a double
7251 ** precision number.
7252 ** @cre an empty string always returns false.
7253 ** @see ajStrTokIntBool
7254 **
7255 ** @release 1.0.0
7256 ** @@
7257 ******************************************************************************/
7258
ajStrIsDouble(const AjPStr str)7259 AjBool ajStrIsDouble(const AjPStr str)
7260 {
7261 const char* cp;
7262 char* ptr = NULL;
7263 double value;
7264
7265 if(!str)
7266 return ajFalse;
7267
7268 if(!str->Len)
7269 return ajFalse;
7270
7271 cp = str->Ptr;
7272
7273 errno = 0;
7274 value = strtod(cp, &ptr);
7275 (void) value;
7276
7277 if(*ptr || errno == ERANGE)
7278 return ajFalse;
7279
7280 return ajTrue;
7281 }
7282
7283
7284
7285
7286 /* @func ajStrIsFilter ********************************************************
7287 **
7288 ** Test whether a string contains only characters defined by a filter
7289 **
7290 ** @param [r] str [const AjPStr] String
7291 ** @param [r] filter [const char*] Filter non-zero for each allowed value
7292 ** @return [AjBool] ajTrue if the string is entirely composed of characters
7293 ** in the specified set
7294 ** @cre an empty string returns ajFalse
7295 **
7296 ** @release 6.6.0
7297 ** @@
7298 ******************************************************************************/
7299
ajStrIsFilter(const AjPStr str,const char * filter)7300 AjBool ajStrIsFilter(const AjPStr str, const char* filter)
7301 {
7302 const char* cp;
7303
7304 if(!str)
7305 return ajFalse;
7306
7307 if(!str->Len)
7308 return ajFalse;
7309
7310 cp = str->Ptr;
7311
7312 while(*cp)
7313 if(!filter[(int)*cp++])
7314 return ajFalse;
7315
7316 return ajTrue;
7317 }
7318
7319
7320
7321
7322 /* @func ajStrIsFloat *********************************************************
7323 **
7324 ** Tests whether a string represents a valid floating point value.
7325 **
7326 ** Test uses the strtod call in the C RTL.
7327 **
7328 ** @param [r] str [const AjPStr] String
7329 ** @return [AjBool] ajTrue if the string is acceptable as a floating
7330 ** point number.
7331 ** @cre an empty string always returns false.
7332 ** @see ajStrTokIntBool
7333 **
7334 ** @release 1.0.0
7335 ** @@
7336 ******************************************************************************/
7337
ajStrIsFloat(const AjPStr str)7338 AjBool ajStrIsFloat(const AjPStr str)
7339 {
7340 const char* cp;
7341 char* ptr = NULL;
7342 double d;
7343
7344 if(!str)
7345 return ajFalse;
7346
7347 if(!str->Len)
7348 return ajFalse;
7349
7350 cp = str->Ptr;
7351
7352 errno = 0;
7353 d = strtod(cp, &ptr);
7354
7355 if(*ptr || errno == ERANGE)
7356 return ajFalse;
7357
7358 if(d > FLT_MAX)
7359 return ajFalse;
7360
7361 if(d < -FLT_MAX)
7362 return ajFalse;
7363
7364 return ajTrue;
7365 }
7366
7367
7368
7369
7370 /* @func ajStrIsHex ***********************************************************
7371 **
7372 ** Tests whether a string represents a valid hexadecimal value.
7373 **
7374 ** Test uses the strtol call in the C RTL.
7375 **
7376 ** @param [r] str [const AjPStr] String
7377 ** @return [AjBool] ajTrue if the string is acceptable as a hexadecimal value.
7378 ** @cre an empty string always returns false.
7379 **
7380 ** @release 1.13.0
7381 ** @@
7382 ******************************************************************************/
7383
ajStrIsHex(const AjPStr str)7384 AjBool ajStrIsHex(const AjPStr str)
7385 {
7386 const char* cp;
7387 char* ptr = NULL;
7388 ajlong value;
7389
7390 if(!str)
7391 return ajFalse;
7392
7393 if(!str->Len)
7394 return ajFalse;
7395
7396 cp = str->Ptr;
7397
7398 errno = 0;
7399 value = strtol(cp, &ptr, 16);
7400 (void) value;
7401
7402 if(*ptr || errno == ERANGE)
7403 return ajFalse;
7404
7405 return ajTrue;
7406 }
7407
7408
7409
7410
7411 /* @func ajStrIsInt ***********************************************************
7412 **
7413 ** Tests whether a string represents a valid integer value.
7414 **
7415 ** Test uses the strtol call in the C RTL.
7416 **
7417 ** @param [r] str [const AjPStr] String
7418 ** @return [AjBool] ajTrue if the string is acceptable as an integer.
7419 ** @cre an empty string always returns false.
7420 ** @see ajStrTokIntBool
7421 **
7422 ** @release 1.0.0
7423 ** @@
7424 ******************************************************************************/
7425
ajStrIsInt(const AjPStr str)7426 AjBool ajStrIsInt(const AjPStr str)
7427 {
7428 const char* cp;
7429 char* ptr = NULL;
7430 ajlong value;
7431
7432 if(!str)
7433 return ajFalse;
7434
7435 if(!str->Len)
7436 return ajFalse;
7437
7438 cp = str->Ptr;
7439
7440 errno = 0;
7441 value = strtol(cp, &ptr, 10);
7442
7443 if(*ptr || errno == ERANGE)
7444 return ajFalse;
7445
7446 if(value < INT_MIN)
7447 return ajFalse;
7448
7449 if(value > INT_MAX)
7450 return ajFalse;
7451
7452 return ajTrue;
7453 }
7454
7455
7456
7457
7458 /* @func ajStrIsLong **********************************************************
7459 **
7460 ** Tests whether a string represents a valid ajlong integer value.
7461 **
7462 ** Test uses the strtol call in the C RTL.
7463 **
7464 ** @param [r] str [const AjPStr] String
7465 ** @return [AjBool] ajTrue if the string is acceptable as an integer.
7466 ** @cre an empty string always returns false.
7467 ** @see ajStrTokIntBool
7468 **
7469 ** @release 1.0.0
7470 ** @@
7471 ******************************************************************************/
7472
ajStrIsLong(const AjPStr str)7473 AjBool ajStrIsLong(const AjPStr str)
7474 {
7475 const char* cp;
7476 char* ptr = NULL;
7477 ajlong value;
7478
7479 if(!str)
7480 return ajFalse;
7481
7482 if(!str->Len)
7483 return ajFalse;
7484
7485 cp = str->Ptr;
7486
7487 errno = 0;
7488 value = strtol(cp, &ptr, 10);
7489 (void) value;
7490
7491 if(*ptr || errno == ERANGE)
7492 return ajFalse;
7493
7494 return ajTrue;
7495 }
7496
7497
7498
7499
7500 /* @func ajStrIsLower *********************************************************
7501 **
7502 ** Tests whether a string contains no upper case alphabetic characters.
7503 **
7504 ** Test is defined by isupper in the C RTL..
7505 **
7506 ** @param [r] str [const AjPStr] String
7507 ** @return [AjBool] ajTrue if the string is entirely alphabetic
7508 ** @cre an empty string returns ajTrue
7509 **
7510 ** @release 2.7.0
7511 ** @@
7512 ******************************************************************************/
7513
ajStrIsLower(const AjPStr str)7514 AjBool ajStrIsLower(const AjPStr str)
7515 {
7516 const char* cp;
7517
7518 if(!str)
7519 return ajTrue;
7520
7521 if(!str->Len)
7522 return ajTrue;
7523
7524 cp =str->Ptr;
7525
7526 while(*cp)
7527 if(isupper((ajint)*cp++))
7528 return ajFalse;
7529
7530 return ajTrue;
7531 }
7532
7533
7534
7535
7536 /* @func ajStrIsNum ***********************************************************
7537 **
7538 ** Test whether a string contains decimal digits only.
7539 **
7540 ** Test is defined by isdigit in the C RTL..
7541 **
7542 ** @param [r] str [const AjPStr] String
7543 ** @return [AjBool] ajTrue if the string is entirely numeric
7544 ** @cre an empty string returns ajFalse
7545 **
7546 ** @release 3.0.0
7547 ** @@
7548 ******************************************************************************/
7549
ajStrIsNum(const AjPStr str)7550 AjBool ajStrIsNum(const AjPStr str)
7551 {
7552 const char* cp;
7553
7554 if(!str)
7555 return ajFalse;
7556
7557 if(!str->Len)
7558 return ajFalse;
7559
7560 for(cp = str->Ptr;*cp;cp++)
7561 if(!isdigit((ajint)*cp))
7562 return ajFalse;
7563
7564 return ajTrue;
7565 }
7566
7567
7568
7569
7570 /* @func ajStrIsUpper *********************************************************
7571 **
7572 ** Test whether a string contains no lower case alphabetic characters.
7573 **
7574 ** Test is defined by islower in the C RTL..
7575 **
7576 ** @param [r] str [const AjPStr] String
7577 ** @return [AjBool] ajTrue if the string has no lower case characters.
7578 ** @cre an empty string returns ajTrue
7579 **
7580 ** @release 2.7.0
7581 ** @@
7582 ******************************************************************************/
7583
ajStrIsUpper(const AjPStr str)7584 AjBool ajStrIsUpper(const AjPStr str)
7585 {
7586 const char* cp;
7587
7588 if(!str)
7589 return ajFalse;
7590
7591 if(!str->Len)
7592 return ajFalse;
7593
7594 cp = str->Ptr;
7595
7596 while(*cp)
7597 if(islower((ajint)*cp++))
7598 return ajFalse;
7599
7600 return ajTrue;
7601 }
7602
7603
7604
7605
7606 /* @func ajStrIsWhite *********************************************************
7607 **
7608 ** Test whether a string contains whitespace characters only.
7609 **
7610 ** The test is made using the strtod call in the C RTL.
7611 **
7612 ** @param [r] str [const AjPStr] String
7613 ** @return [AjBool] ajTrue if the string is only white space (or empty).
7614 **
7615 ** @release 2.9.0
7616 ** @@
7617 ******************************************************************************/
7618
ajStrIsWhite(const AjPStr str)7619 AjBool ajStrIsWhite(const AjPStr str)
7620 {
7621 const char* cp;
7622
7623 if(!str)
7624 return ajFalse;
7625
7626 if(!str->Len)
7627 return ajTrue;
7628
7629 cp = str->Ptr;
7630
7631 while (*cp)
7632 {
7633 if (!isspace((int)*cp))
7634 return ajFalse;
7635
7636 cp++;
7637 }
7638
7639 return ajTrue;
7640 }
7641
7642
7643
7644
7645 /* @func ajStrIsWild **********************************************************
7646 **
7647 ** Tests whether a string contains the standard wildcard characters * or ?.
7648 **
7649 ** @param [r] str [const AjPStr] String
7650 ** @return [AjBool] ajTrue if string has wildcards.
7651 **
7652 ** @release 1.0.0
7653 ** @@
7654 ******************************************************************************/
7655
ajStrIsWild(const AjPStr str)7656 AjBool ajStrIsWild(const AjPStr str)
7657 {
7658 if(ajStrFindAnyC(str, "*?") >= 0)
7659 return ajTrue;
7660
7661 return ajFalse;
7662 }
7663
7664
7665
7666
7667 /* @func ajStrIsWord **********************************************************
7668 **
7669 ** Test whether a string contains no white space characters.
7670 **
7671 ** Test is defined by isspace in the C RTL.
7672 **
7673 ** @param [r] str [const AjPStr] String
7674 ** @return [AjBool] ajTrue if the string has no white space
7675 ** @cre an empty string returns ajFalse
7676 **
7677 ** @release 1.0.0
7678 ** @@
7679 ******************************************************************************/
7680
ajStrIsWord(const AjPStr str)7681 AjBool ajStrIsWord(const AjPStr str)
7682 {
7683 const char* cp;
7684
7685 if(!str)
7686 return ajFalse;
7687
7688 if(!str->Len)
7689 return ajFalse;
7690
7691 cp = str->Ptr;
7692
7693 while(*cp)
7694 if(isspace((ajint)*cp++))
7695 return ajFalse;
7696
7697 return ajTrue;
7698 }
7699
7700
7701
7702
7703 /* @func ajStrWhole ***********************************************************
7704 **
7705 ** Tests whether a range refers to the whole string
7706 **
7707 ** @param [r] str [const AjPStr] String
7708 ** @param [r] pos1 [ajlong] Begin position (0 start, negative from the end)
7709 ** @param [r] pos2 [ajlong] Begin position (0 start, negative from the end)
7710 ** @return [AjBool] ajTrue is range covers the whole string
7711 **
7712 ** @release 2.5.0
7713 ******************************************************************************/
7714
ajStrWhole(const AjPStr str,ajlong pos1,ajlong pos2)7715 AjBool ajStrWhole(const AjPStr str, ajlong pos1, ajlong pos2)
7716 {
7717 size_t ibeg;
7718 size_t iend;
7719
7720 ibeg = ajCvtSposToPosStart(str->Len, 0, pos1);
7721
7722 if(ibeg)
7723 return ajFalse;
7724
7725 iend = ajCvtSposToPosStart(str->Len, ibeg, pos2);
7726
7727 if(iend != (str->Len - 1))
7728 return ajFalse;
7729
7730 return ajTrue;
7731 }
7732
7733
7734
7735
7736 /* @section filters
7737 **
7738 ** Functions for creating filters from C-type (char*) strings).
7739 **
7740 ** @fdata [AjPStr]
7741 **
7742 ** @nam3rule Getfilter Get a filter array
7743 ** @nam4rule Case Case-insensitive filter
7744 ** @nam4rule Lower Lower case filter.
7745 ** @nam4rule Upper Upper case filter.
7746 **
7747 ** @argrule * str [const AjPStr] String
7748 ** @valrule * [char*] Filter
7749 ** @fcategory use
7750 */
7751
7752
7753
7754
7755 /* @func ajStrGetfilter *******************************************************
7756 **
7757 ** Returns a filter array to test for any character in a string.
7758 **
7759 ** @param [r] str [const AjPStr] Character set to test
7760 ** @return [char*] Filter array set to 1 for each ascii value accepted
7761 ** zero for any character not in the set.
7762 **
7763 ** @release 6.6.0
7764 ** @@
7765 ******************************************************************************/
7766
ajStrGetfilter(const AjPStr str)7767 char* ajStrGetfilter(const AjPStr str)
7768 {
7769 char *ret;
7770 const char* cp;
7771
7772 ret = AJALLOC0(256);
7773
7774 if(!str)
7775 return ret;
7776
7777 if(!str->Len)
7778 return ret;
7779
7780 cp = str->Ptr;
7781
7782 while (*cp)
7783 {
7784 ret[((int)*cp++)] = 1;
7785 }
7786
7787 return ret;
7788 }
7789
7790
7791
7792
7793 /* @func ajStrGetfilterCase ***************************************************
7794 **
7795 ** Returns a filter array to test for any character in a string.
7796 ** The filter is case-insensitive
7797 **
7798 ** @param [r] str [const AjPStr] Character set to test
7799 ** @return [char*] Filter array set to 1 for each ascii value accepted
7800 ** zero for any character not in the set.
7801 **
7802 ** @release 6.6.0
7803 ** @@
7804 ******************************************************************************/
7805
ajStrGetfilterCase(const AjPStr str)7806 char* ajStrGetfilterCase(const AjPStr str)
7807 {
7808 char *ret;
7809 const char* cp;
7810
7811 ret = AJALLOC0(256);
7812
7813 if(!str)
7814 return ret;
7815
7816 if(!str->Len)
7817 return ret;
7818
7819 cp = str->Ptr;
7820
7821 while (*cp)
7822 {
7823 ret[tolower((int)*cp)] = 1;
7824 ret[toupper((int)*cp++)] = 1;
7825 }
7826
7827 return ret;
7828 }
7829
7830
7831
7832
7833 /* @func ajStrGetfilterLower **************************************************
7834 **
7835 ** Returns a filter array to test for any character in a string as lower case.
7836 **
7837 ** @param [r] str [const AjPStr] Character set to test
7838 ** @return [char*] Filter array set to 1 for each ascii value accepted
7839 ** zero for any character not in the set.
7840 **
7841 ** @release 6.6.0
7842 ** @@
7843 ******************************************************************************/
7844
ajStrGetfilterLower(const AjPStr str)7845 char* ajStrGetfilterLower(const AjPStr str)
7846 {
7847 char *ret;
7848 const char* cp;
7849
7850 ret = AJALLOC0(256);
7851
7852 if(!str)
7853 return ret;
7854
7855 if(!str->Len)
7856 return ret;
7857
7858 cp = str->Ptr;
7859
7860 while (*cp)
7861 {
7862 ret[tolower((int)*cp++)] = 1;
7863 }
7864
7865 return ret;
7866 }
7867
7868
7869
7870
7871 /* @func ajStrGetfilterUpper **************************************************
7872 **
7873 ** Returns a filter array to test for any character in a string as upper case.
7874 **
7875 ** @param [r] str [const AjPStr] Character set to test
7876 ** @return [char*] Filter array set to 1 for each ascii value accepted
7877 ** zero for any character not in the set.
7878 **
7879 ** @release 6.6.0
7880 ** @@
7881 ******************************************************************************/
7882
ajStrGetfilterUpper(const AjPStr str)7883 char* ajStrGetfilterUpper(const AjPStr str)
7884 {
7885 char *ret;
7886 const char* cp;
7887
7888 ret = AJALLOC0(256);
7889
7890 if(!str)
7891 return ret;
7892
7893 if(!str->Len)
7894 return ret;
7895
7896 cp = str->Ptr;
7897
7898 while (*cp)
7899 {
7900 ret[toupper((int)*cp++)] = 1;
7901 }
7902
7903 return ret;
7904 }
7905
7906
7907
7908
7909 /* @section element retrieval *************************************************
7910 **
7911 ** Functions for returning elements of a string object.
7912 **
7913 ** @fdata [AjPStr]
7914 ** @fnote The last word of the ajStrGet family of functions is the
7915 ** element variable name.
7916 ** @fnote Each ajXxxGet function should be provided as a macro.
7917 **
7918 ** @nam3rule Get Retrieve an unmodified element of a string object.
7919 ** @nam4rule GetAscii Retrieve ASCII character code
7920 ** @nam5rule GetAsciiLow Retrieve lowest ASCII character code
7921 ** @nam5rule GetAsciiHigh Retrieve highest ASCII character code
7922 ** @nam5rule GetAsciiCommon Retrieve most common ASCII character code
7923 ** @nam4rule GetChar Retrieve first single character
7924 ** @nam5rule GetCharFirst Retrieve first single character
7925 ** @nam5rule GetCharLast Retrieve last single character
7926 ** @nam5rule GetCharPos Retrieve a single character
7927 ** @nam4rule GetLen Retrieve length
7928 ** @nam4rule GetPtr Retrieve char* pointer
7929 ** @nam4rule GetRes Retrieve reserved memory size
7930 ** @nam4rule GetPtr Retrieve additional space available
7931 ** @nam4rule GetRoom Retrieve additional space available
7932 ** @nam4rule GetUse Retrieve use (reference) count
7933 ** @nam4rule GetValid Test string is valid
7934 **
7935 ** @argrule * str [const AjPStr] String
7936 ** @argrule GetCharPos pos [ajlong] Position, negative values count from the end
7937 **
7938 ** @valrule GetChar [char] Single character
7939 ** @valrule GetLen [size_t] String length
7940 ** @valrule GetRes [size_t] Reserved size
7941 ** @valrule GetPtr [const char*] read-only C string pointer to internal string
7942 ** @valrule GetuniquePtr [char*] Modifiable C string pointer to internal string
7943 ** @valrule GetUse [ajuint] Reference (use) count
7944 ** @valrule GetRoom [size_t] Remaining space to extend string
7945 ** without reallocating
7946 ** @valrule GetValid [AjBool] True if string is valid
7947 ** @valrule GetAscii [char] ASCII character
7948 **
7949 ** @fcategory use
7950 */
7951
7952
7953
7954
7955 /* @func ajStrGetAsciiCommon **************************************************
7956 **
7957 ** Returns the most common ASCII character code in a string.
7958 **
7959 ** @param [r] str [const AjPStr] String
7960 ** @return [char] Most common character or null character if empty.
7961 **
7962 ** @release 6.1.0
7963 ** @@
7964 ******************************************************************************/
7965
ajStrGetAsciiCommon(const AjPStr str)7966 char ajStrGetAsciiCommon(const AjPStr str)
7967 {
7968 const char *cp;
7969
7970 ajulong totals[256];
7971 ajulong maxtot = 0;
7972 char maxcode = 0;
7973 int icode;
7974 ajulong i;
7975
7976 if(!str)
7977 return '\0';
7978 if(!str->Len)
7979 return '\0';
7980
7981 for(i=0;i<256;i++)
7982 totals[i] = 0;
7983
7984 cp = str->Ptr;
7985
7986 while (*cp)
7987 {
7988 icode = (int) *cp;
7989 totals[icode]++;
7990 if(totals[icode] > maxtot)
7991 {
7992 maxtot = totals[icode];
7993 maxcode = (char) icode;
7994 }
7995 cp++;
7996 }
7997
7998 return maxcode;
7999 }
8000
8001
8002
8003
8004 /* @func ajStrGetAsciiHigh ****************************************************
8005 **
8006 ** Returns the highest ASCII character code in a string.
8007 **
8008 ** @param [r] str [const AjPStr] String
8009 ** @return [char] Highest character or null character if empty.
8010 **
8011 ** @release 6.1.0
8012 ** @@
8013 ******************************************************************************/
8014
ajStrGetAsciiHigh(const AjPStr str)8015 char ajStrGetAsciiHigh(const AjPStr str)
8016 {
8017 char ret = CHAR_MIN;
8018 const char *cp;
8019
8020 if(!str)
8021 return '\0';
8022 if(!str->Len)
8023 return '\0';
8024
8025 cp = str->Ptr;
8026
8027 while (*cp)
8028 {
8029 if(*cp > ret)
8030 ret = *cp;
8031 cp++;
8032 }
8033
8034 return ret;
8035 }
8036
8037
8038
8039
8040 /* @func ajStrGetAsciiLow *****************************************************
8041 **
8042 ** Returns the lowest ASCII character code in a string.
8043 **
8044 ** @param [r] str [const AjPStr] String
8045 ** @return [char] Lowest character or null character if empty.
8046 **
8047 ** @release 6.1.0
8048 ** @@
8049 ******************************************************************************/
8050
ajStrGetAsciiLow(const AjPStr str)8051 char ajStrGetAsciiLow(const AjPStr str)
8052 {
8053 char ret = CHAR_MAX;
8054 const char *cp;
8055
8056 if(!str)
8057 return '\0';
8058 if(!str->Len)
8059 return '\0';
8060
8061 cp = str->Ptr;
8062
8063 while (*cp)
8064 {
8065 if(*cp < ret)
8066 ret = *cp;
8067 cp++;
8068 }
8069
8070 return ret;
8071 }
8072
8073
8074
8075
8076 /* @func ajStrGetCharFirst ****************************************************
8077 **
8078 ** Returns the first character from a string.
8079 **
8080 ** @param [r] str [const AjPStr] String
8081 ** @return [char] First character or null character if empty.
8082 **
8083 ** @release 4.0.0
8084 ** @@
8085 ******************************************************************************/
8086
ajStrGetCharFirst(const AjPStr str)8087 char ajStrGetCharFirst(const AjPStr str)
8088 {
8089 if(!str)
8090 return '\0';
8091
8092 return str->Ptr[0];
8093 }
8094
8095
8096
8097
8098 /* @func ajStrGetCharLast *****************************************************
8099 **
8100 ** Returns the last character from a string.
8101 **
8102 ** @param [r] str [const AjPStr] String
8103 ** @return [char] Last character or null character if empty.
8104 **
8105 ** @release 4.0.0
8106 ** @@
8107 ******************************************************************************/
8108
ajStrGetCharLast(const AjPStr str)8109 char ajStrGetCharLast(const AjPStr str)
8110 {
8111 if(!str)
8112 return '\0';
8113
8114 if(!str->Len)
8115 return '\0';
8116
8117 return str->Ptr[str->Len - 1];
8118 }
8119
8120
8121
8122
8123 /* @func ajStrGetCharPos ******************************************************
8124 **
8125 ** Returns a single character at a given position from a string.
8126 **
8127 ** @param [r] str [const AjPStr] String
8128 ** @param [r] pos [ajlong] Position in the string, negative values are
8129 ** from the end of the string.
8130 ** @return [char] Character at position pos or null character if out of range.
8131 **
8132 ** @release 4.0.0
8133 ** @@
8134 ******************************************************************************/
8135
ajStrGetCharPos(const AjPStr str,ajlong pos)8136 char ajStrGetCharPos(const AjPStr str, ajlong pos)
8137 {
8138 size_t ipos;
8139
8140 if(!str)
8141 return '\0';
8142
8143 if(pos < 0)
8144 ipos = str->Len + (size_t) pos;
8145 else
8146 ipos = (size_t) pos;
8147
8148 if(ipos > str->Len)
8149 return '\0';
8150
8151 return str->Ptr[ipos];
8152 }
8153
8154
8155
8156
8157 /* @func ajStrGetLen **********************************************************
8158 **
8159 ** Returns the current length of the C (char *) string.
8160 **
8161 ** The length will remain valid unless the string is resized or deleted.
8162 **
8163 ** @param [r] str [const AjPStr] Source string
8164 ** @return [size_t] Current string length
8165 **
8166 ** @release 4.0.0
8167 ** @@
8168 ******************************************************************************/
8169
ajStrGetLen(const AjPStr str)8170 size_t ajStrGetLen(const AjPStr str)
8171 {
8172 if(!str)
8173 return 0;
8174
8175
8176 return str->Len;
8177 }
8178
8179
8180
8181
8182 /* @macro MAJSTRGETLEN ********************************************************
8183 **
8184 ** Returns the current length of the C (char *) string.
8185 **
8186 ** A macro version of {ajStrGetLen} available in case it is needed for speed.
8187 **
8188 ** @param [r] str [const AjPStr] Source string
8189 ** @return [size_t] Current string length
8190 ** @@
8191 ******************************************************************************/
8192
8193
8194
8195
8196 /* @func ajStrGetPtr **********************************************************
8197 **
8198 ** Returns the current pointer to C (char *) string.
8199 **
8200 ** The pointer will remain valid unless the string is resized or deleted.
8201 **
8202 ** @param [r] str [const AjPStr] Source string
8203 ** @return [const char*] Current string pointer, or a null string if undefined.
8204 **
8205 ** @release 4.0.0
8206 ** @@
8207 ******************************************************************************/
8208
ajStrGetPtr(const AjPStr str)8209 const char* ajStrGetPtr(const AjPStr str)
8210 {
8211 if(!str)
8212 return charNULL;
8213
8214 return str->Ptr;
8215 }
8216
8217
8218
8219
8220 /* @macro MAJSTRGETPTR ********************************************************
8221 **
8222 ** Returns the current pointer to C (char *) string.
8223 **
8224 ** A macro version of {ajStrGetPtr} available in case it is needed for speed.
8225 **
8226 ** @param [r] str [const AjPStr] Source string
8227 ** @return [const char*] Current string pointer, or a null string if undefined.
8228 ** @@
8229 ******************************************************************************/
8230
8231
8232
8233
8234 /* @func ajStrGetRes **********************************************************
8235 **
8236 ** Returns the current reserved size of the C (char *) string.
8237 **
8238 ** The reserved size will remain valid unless the string is resized or deleted.
8239 **
8240 ** @param [r] str [const AjPStr] Source string
8241 ** @return [size_t] Current string reserved size
8242 **
8243 ** @release 4.0.0
8244 ** @@
8245 ******************************************************************************/
8246
ajStrGetRes(const AjPStr str)8247 size_t ajStrGetRes(const AjPStr str)
8248 {
8249 if(!str)
8250 return 0;
8251
8252 return str->Res;
8253 }
8254
8255
8256
8257
8258 /* @macro MAJSTRGETRES ********************************************************
8259 **
8260 ** Returns the current reserved size of the C (char *) string.
8261 **
8262 ** A macro version of {ajStrGetRes} available in case it is needed for speed.
8263 **
8264 ** @param [r] str [const AjPStr] Source string
8265 ** @return [size_t] Current string reserved size
8266 ** @@
8267 ******************************************************************************/
8268
8269
8270
8271
8272 /* @func ajStrGetRoom *********************************************************
8273 **
8274 ** Returns the additional space available in a string before it would require
8275 ** reallocating.
8276 **
8277 ** @param [r] str [const AjPStr] String
8278 ** @return [size_t] Space available for additional characters.
8279 **
8280 ** @release 4.0.0
8281 ** @@
8282 ******************************************************************************/
8283
ajStrGetRoom(const AjPStr str)8284 size_t ajStrGetRoom(const AjPStr str)
8285 {
8286 return (str->Res - str->Len - 1);
8287 }
8288
8289
8290
8291
8292 /* @func ajStrGetUse **********************************************************
8293 **
8294 ** Returns the current usage count of the C (char *) string.
8295 **
8296 ** The usage count will remain valid unless the string is resized or deleted.
8297 **
8298 ** @param [r] str [const AjPStr] Source string
8299 ** @return [ajuint] Current string usage count
8300 **
8301 ** @release 4.0.0
8302 ** @@
8303 ******************************************************************************/
8304
ajStrGetUse(const AjPStr str)8305 ajuint ajStrGetUse(const AjPStr str)
8306 {
8307 if(!str)
8308 return 0;
8309
8310 return str->Use;
8311 }
8312
8313
8314
8315
8316 /* @macro MAJSTRGETUSE ********************************************************
8317 **
8318 ** Returns the current usage count of the C (char *) string.
8319 **
8320 ** A macro version of {ajStrGetUse} available in case it is needed for speed.
8321 **
8322 ** @param [r] str [const AjPStr] Source string
8323 ** @return [ajuint] Current string usage count
8324 ** @@
8325 ******************************************************************************/
8326
8327
8328
8329
8330 /* @func ajStrGetValid ********************************************************
8331 **
8332 ** Checks a string object for consistency.
8333 **
8334 ** Intended for debugging and testing of these routines, but made publicly
8335 ** available.
8336 **
8337 ** @param [r] str [const AjPStr] String
8338 ** @return [AjBool] ajTrue if no errors were found.
8339 **
8340 ** @release 4.0.0
8341 ** @@
8342 ******************************************************************************/
8343
ajStrGetValid(const AjPStr str)8344 AjBool ajStrGetValid(const AjPStr str)
8345 {
8346 AjBool ret = ajTrue;
8347
8348 if(!str)
8349 {
8350 ajErr("ajStrGetValid: NULL string pointer");
8351 ret = ajFalse;
8352 }
8353
8354 if(str->Res < 1)
8355 {
8356 ajErr("ajStrGetValid: Bad size value %d", str->Res);
8357 ret = ajFalse;
8358 }
8359
8360 if(str->Len >= str->Res)
8361 {
8362 ajErr("ajStrGetValid: Size %d too small for length %d\n",
8363 str->Res, str->Len);
8364 ret = ajFalse;
8365 }
8366
8367 if(!str->Ptr)
8368 {
8369 ajErr("ajStrGetValid: NULL pointer\n");
8370 ret = ajFalse;
8371 }
8372 else
8373 {
8374 if(str->Len != strlen(str->Ptr))
8375 {
8376 ajErr("ajStrGetValid: Len %d differs from strlen %d\n",
8377 str->Len, strlen(str->Ptr));
8378 ret = ajFalse;
8379 }
8380 }
8381
8382 return ret;
8383 }
8384
8385
8386
8387
8388 /* @section modifiable string retrieval ***************************************
8389 **
8390 ** Functions for returning elements of a string object.
8391 **
8392 ** @fdata [AjPStr]
8393 ** @fnote The last word of the ajStrGet family of functions is the
8394 ** element variable name.
8395 ** @fnote Each ajXxxGet function should be provided as a macro.
8396 **
8397 ** @nam3rule Getunique Single copy strings
8398 ** @nam4rule GetuniquePtr Retrieve char* pointer as single copy
8399 ** @nam4rule GetuniqueStr Retrieve string pointer as single copy
8400 **
8401 ** @argrule * Pstr [AjPStr*] String
8402 **
8403 ** @valrule GetuniqueStr [AjPStr] Modifiable string pointer to internal string
8404 ** @valrule GetuniquePtr [char*] Modifiable C string pointer to internal string
8405 **
8406 ** @fcategory modify
8407 */
8408
8409
8410
8411
8412 /* @func ajStrGetuniquePtr ****************************************************
8413 **
8414 ** Makes the string value unique by copying any string with a reference count
8415 ** of more than 1, and returns the current C (char *) pointer.
8416 **
8417 ** As the input string is not const, the calling program must be able
8418 ** to modify it in order to call this function.
8419 **
8420 ** If the length of the string is changed, it is the responsibility of
8421 ** the caller to reset it with ajStrSetValid
8422 **
8423 ** @param [u] Pstr [AjPStr*] Source string
8424 ** @return [char*] Current string pointer, or a null string if undefined.
8425 **
8426 ** @release 4.0.0
8427 ** @@
8428 ******************************************************************************/
8429
ajStrGetuniquePtr(AjPStr * Pstr)8430 char* ajStrGetuniquePtr(AjPStr *Pstr)
8431 {
8432 AjPStr thys;
8433
8434 if(!*Pstr)
8435 *Pstr = ajStrNewResLenC("", 1, 0);
8436 else if((*Pstr)->Use > 1)
8437 ajStrGetuniqueStr(Pstr);
8438
8439 thys = *Pstr;
8440
8441 return thys->Ptr;
8442 }
8443
8444
8445
8446
8447 /* @macro MAJSTRGETUNIQUESTR **************************************************
8448 **
8449 ** Make certain a string is modifiable by checking it has no other references,
8450 ** or by making a new real copy of the string.
8451 **
8452 ** Uses strCloneL to copy without copying the reference count.
8453 **
8454 ** The target string is guaranteed to have a reference count of exactly 1.
8455 **
8456 ** A macro version of {ajStrGetuniqueStr} in case it is needed for speed
8457 **
8458 ** @param [u] Pstr [AjPStr*] String
8459 ** @return [AjPStr] The new string pointer, or NULL for failure
8460 ** @@
8461 ******************************************************************************/
8462
8463
8464
8465
8466 /* @func ajStrGetuniqueStr ****************************************************
8467 **
8468 ** Make certain a string is modifiable by checking it has no other references,
8469 ** or by making a new real copy of the string.
8470 **
8471 ** Uses strCloneL to copy without copying the reference count.
8472 **
8473 ** The target string is guaranteed to have a reference count of exactly 1.
8474 **
8475 ** @param [u] Pstr [AjPStr*] String
8476 ** @return [AjPStr] The new string pointer, or NULL for failure
8477 **
8478 ** @release 4.0.0
8479 ** @@
8480 ******************************************************************************/
8481
ajStrGetuniqueStr(AjPStr * Pstr)8482 AjPStr ajStrGetuniqueStr(AjPStr* Pstr)
8483 {
8484 AjPStr thys;
8485
8486 if(!*Pstr)
8487 {
8488 *Pstr = ajStrNew();
8489
8490 return *Pstr;
8491 }
8492
8493 thys = *Pstr;
8494
8495 if(thys->Use > 1)
8496 strClone(Pstr);
8497
8498 return *Pstr;
8499 }
8500
8501
8502
8503
8504 /* @section element assignment ************************************************
8505 **
8506 ** Functions for assigning elements of a string object.
8507 **
8508 ** @fdata [AjPStr]
8509 ** @fnote The last word of the ajStrGet family of functions is the
8510 ** element variable name.
8511 ** @fnote Each ajXXXSet function should be provided as a macro.
8512 ** @nam3rule Set Set elements (attributes)
8513 ** @nam4rule SetClear Clear all elements (empty string, length zero)
8514 ** @nam4rule SetLen
8515 ** @nam4rule SetRes Set (increase) reserved memory
8516 ** @nam5rule SetResRound Maximum rounded up by a standard amount (32)
8517 ** @nam4rule SetUnique Set reference count to 1, making a copy if needed
8518 ** @nam4rule SetValid Sets the string elements to be valid,
8519 ** for example adjusting the string length after editing.
8520 **
8521 ** @argrule * Pstr [AjPStr*] String
8522 ** @argrule Res size [size_t] Reserved size
8523 ** @argrule Len len [size_t] Correct string length
8524 **
8525 ** @valrule * [AjBool] True on success
8526 **
8527 ** @fcategory modify
8528 */
8529
8530
8531
8532
8533 /* @func ajStrSetClear ********************************************************
8534 **
8535 ** Clears all elements in a string object.
8536 **
8537 ** If the string is already empty nothing happens. If the string has data,
8538 ** it makes sure the string is modifiable and sets it to empty.
8539 **
8540 ** @param [w] Pstr [AjPStr*] Pointer to the string to be deleted.
8541 ** The pointer is always deleted.
8542 ** @return [AjBool] ajTrue if string was reallocated
8543 **
8544 ** @release 4.0.0
8545 ** @@
8546 ******************************************************************************/
8547
ajStrSetClear(AjPStr * Pstr)8548 AjBool ajStrSetClear(AjPStr* Pstr)
8549 {
8550 AjPStr thys;
8551
8552 if(!*Pstr)
8553 return ajTrue;
8554
8555 thys = *Pstr;
8556
8557 if(thys->Use > 1)
8558 {
8559 thys->Use--;
8560 *Pstr = ajStrNew();
8561 return ajTrue;
8562 }
8563
8564 thys->Ptr[0] = '\0';
8565 thys->Len = 0;
8566
8567 return ajTrue;
8568 }
8569
8570
8571
8572
8573 /* @func ajStrSetRes **********************************************************
8574 **
8575 ** Ensures a string is modifiable and big enough for its intended purpose.
8576 **
8577 ** The target string is guaranteed to have a reference count of 1 and a
8578 ** minimum reserved size.
8579 **
8580 ** @param [u] Pstr [AjPStr*] String
8581 ** @param [r] size [size_t] Minimum reserved size.
8582 ** @return [AjBool] ajTrue if the string was reallocated
8583 **
8584 ** @release 4.0.0
8585 ** @@
8586 ******************************************************************************/
8587
ajStrSetRes(AjPStr * Pstr,size_t size)8588 AjBool ajStrSetRes(AjPStr* Pstr, size_t size)
8589 {
8590 AjPStr thys;
8591 size_t savesize;
8592
8593 savesize = size; /* often part of *Pstr, about to vanish */
8594
8595 if(!*Pstr)
8596 {
8597 *Pstr = ajStrNewRes(savesize);
8598
8599 return ajTrue;
8600 }
8601
8602 thys = *Pstr;
8603
8604 if(thys->Use > 1)
8605 {
8606 strCloneL(Pstr, savesize);
8607
8608 return ajTrue;
8609 }
8610
8611 if(thys->Res < savesize)
8612 {
8613 #ifdef AJ_SAVESTATS
8614 strExtra += savesize - thys->Res;
8615 #endif
8616 AJRESIZE0(thys->Ptr, thys->Res, savesize);
8617 thys->Res = savesize;
8618
8619 return ajTrue;
8620 }
8621
8622 return ajFalse;
8623 }
8624
8625
8626
8627
8628 /* @func ajStrSetResRound *****************************************************
8629 **
8630 ** Ensures a string is modifiable and big enough for its intended purpose.
8631 **
8632 ** The target string is guaranteed to have a reference count of 1,
8633 ** and a minimum reserved size. The string size is rounded up.
8634 **
8635 ** @param [w] Pstr [AjPStr*] String
8636 ** @param [r] size [size_t] Minimum reserved size.
8637 ** @return [AjBool] ajTrue if the string was reallocated
8638 **
8639 ** @release 4.0.0
8640 ** @@
8641 ******************************************************************************/
8642
ajStrSetResRound(AjPStr * Pstr,size_t size)8643 AjBool ajStrSetResRound(AjPStr* Pstr, size_t size)
8644 {
8645 AjPStr thys;
8646 size_t trysize;
8647 size_t roundsize;
8648
8649 if(!*Pstr)
8650 {
8651 roundsize = ajRound(size, STRSIZE);
8652 *Pstr = ajStrNewRes(roundsize);
8653
8654 return ajTrue;
8655 }
8656
8657 thys = *Pstr;
8658
8659 if(thys->Use > 1)
8660 {
8661 strCloneL(Pstr, size);
8662
8663 return ajTrue;
8664 }
8665
8666 if(thys->Res < size)
8667 {
8668 if(size >= LONGSTR)
8669 {
8670 trysize = thys->Res;
8671
8672 while(trysize<size)
8673 trysize+=trysize;
8674
8675 roundsize = ajRound(trysize, LONGSTR);
8676 }
8677 else
8678 roundsize = ajRound(size, STRSIZE);
8679
8680 #ifdef AJ_SAVESTATS
8681 strExtra += roundsize - thys->Res;
8682 #endif
8683 AJRESIZE0(thys->Ptr, thys->Res, roundsize);
8684
8685
8686 thys->Res = roundsize;
8687
8688 return ajTrue;
8689 }
8690
8691 return ajFalse;
8692 }
8693
8694
8695
8696
8697 /* @func ajStrSetValid ********************************************************
8698 **
8699 ** Reset string length when some nasty caller may have edited it
8700 **
8701 ** @param [u] Pstr [AjPStr*] String.
8702 ** @return [AjBool] True on success.
8703 **
8704 ** @release 4.0.0
8705 ** @@
8706 ******************************************************************************/
8707
ajStrSetValid(AjPStr * Pstr)8708 AjBool ajStrSetValid(AjPStr *Pstr)
8709 {
8710 AjBool ret = ajTrue;
8711 AjPStr thys = *Pstr;
8712
8713 if(thys->Use > 1)
8714 {
8715 ajWarn("ajStrSetValid called for string in use %d times\n", thys->Use);
8716 ret = ajFalse;
8717 }
8718
8719 thys->Len = strlen(thys->Ptr);
8720
8721 if(thys->Len > (thys->Res - 1)) /* ouch someone went off the end */
8722 {
8723 ajWarn("ajStrSetValid found string with length %d in size %d",
8724 thys->Len, thys->Res);
8725 ret = ajFalse;
8726 ajStrSetResRound(Pstr, thys->Len+1);
8727 }
8728
8729 return ret;
8730 }
8731
8732
8733
8734
8735 /* @func ajStrSetValidLen *****************************************************
8736 **
8737 ** Reset string length when some nasty caller may have edited it
8738 **
8739 ** @param [u] Pstr [AjPStr*] String
8740 ** @param [r] len [size_t] Length expected.
8741 ** @return [AjBool] True on success
8742 **
8743 ** @release 4.0.0
8744 ** @@
8745 ******************************************************************************/
8746
ajStrSetValidLen(AjPStr * Pstr,size_t len)8747 AjBool ajStrSetValidLen(AjPStr* Pstr, size_t len)
8748 {
8749 AjBool ret = ajTrue;
8750 AjPStr thys = *Pstr;
8751
8752 /* check 2 error conditions */
8753
8754 if(thys->Use > 1)
8755 {
8756 ajWarn("ajStrSetValidLen called for string in use %d times\n",
8757 thys->Use);
8758 ret = ajFalse;
8759 }
8760
8761 if(len >= thys->Res)
8762 {
8763 ajWarn("ajStrSetValidLen called with length %d for string size %d\n",
8764 len, thys->Res);
8765 thys->Ptr[thys->Res-1] = '\0';
8766 len = strlen(thys->Ptr);
8767 ret = ajFalse;
8768 }
8769
8770 thys->Ptr[len] = '\0';
8771
8772 thys->Len = len;
8773
8774 return ret;
8775 }
8776
8777
8778
8779
8780 /* @section string to datatype conversion functions ***************************
8781 **
8782 ** Functions for converting strings to other datatypes.
8783 **
8784 ** @fdata [AjPStr]
8785 ** @fnote None.
8786 **
8787 ** @nam3rule To Convert string value to a different datatype.
8788 ** @nam4rule ToBool Convert to boolean
8789 ** @nam4rule ToDouble Convert to double
8790 ** @nam4rule ToFloat Convert to float
8791 ** @nam4rule ToHex Convert to hexadecimal
8792 ** @nam4rule ToInt Convert to integer
8793 ** @nam4rule ToLong Convert to long
8794 ** @nam4rule ToUint Convert to unsigned integer
8795 ** @nam4rule ToUlong Convert to unsigned long integer
8796 **
8797 ** @argrule * str [const AjPStr] String
8798 ** @argrule ToBool Pval [AjBool*] Boolean return value
8799 ** @argrule ToDouble Pval [double*] Double return value
8800 ** @argrule ToFloat Pval [float*] Float return value
8801 ** @argrule ToHex Pval [ajint*] Integer return value
8802 ** @argrule ToInt Pval [ajint*] Integer return value
8803 ** @argrule ToLong Pval [ajlong*] Long integer return value
8804 ** @argrule ToUint Pval [ajuint*] Unsigned integer return value
8805 ** @argrule ToUlong Pval [ajulong*] Unsigned long integer return value
8806 **
8807 ** @valrule * [AjBool] True on success
8808 **
8809 ** @fcategory cast
8810 */
8811
8812
8813
8814
8815 /* @func ajStrToBool **********************************************************
8816 **
8817 ** Converts a string into a Boolean value.
8818 **
8819 ** @param [r] str [const AjPStr] String
8820 ** @param [w] Pval [AjBool*] ajTrue if the string is "true" as a boolean.
8821 ** @return [AjBool] ajTrue if the string had a valid boolean value.
8822 ** @cre an empty string returns ajFalse.
8823 ** @see ajStrIsBool
8824 **
8825 ** @release 1.0.0
8826 ** @@
8827 ******************************************************************************/
8828
ajStrToBool(const AjPStr str,AjBool * Pval)8829 AjBool ajStrToBool(const AjPStr str, AjBool* Pval)
8830 {
8831 const char* cp;
8832 size_t i;
8833
8834 *Pval = ajFalse;
8835
8836 if(!str)
8837 return ajFalse;
8838
8839 if(str->Len < 1)
8840 return ajFalse;
8841
8842 cp = str->Ptr;
8843
8844 if(strchr("YyTt1", *cp))
8845 {
8846 *Pval = ajTrue;
8847
8848 if(str->Len == 1)
8849 return ajTrue;
8850
8851 if(ajStrMatchCaseC(str, "yes"))
8852 return ajTrue;
8853
8854 if(ajStrMatchCaseC(str, "true"))
8855 return ajTrue;
8856
8857 return ajFalse;
8858 }
8859 else if(strchr("NnFf", *cp))
8860 {
8861 *Pval = ajFalse;
8862
8863 if(!ajStrGetCharPos(str, 1))
8864 return ajTrue;
8865
8866 if(ajStrMatchCaseC(str, "no"))
8867 return ajTrue;
8868
8869 if(ajStrMatchCaseC(str, "false"))
8870 return ajTrue;
8871
8872 return ajFalse;
8873 }
8874 else if(strchr("123456789", *cp))
8875 {
8876 *Pval = ajTrue;
8877
8878 if(ajStrIsFloat(str))
8879 return ajTrue;
8880
8881 return ajFalse;
8882 }
8883 else if(strchr("0+-", *cp))
8884 {
8885 i = strcspn(cp, "123456789"); /* e.g. 0.1, 0007 */
8886
8887 if(cp[i])
8888 *Pval = ajTrue;
8889 else
8890 *Pval = ajFalse;
8891
8892 if(ajStrIsFloat(str))
8893 return ajTrue;
8894
8895 return ajFalse;
8896 }
8897
8898 return ajFalse;
8899 }
8900
8901
8902
8903
8904 /* @func ajStrToDouble ********************************************************
8905 **
8906 ** Converts a string into a double precision value.
8907 **
8908 ** Uses the strtod call in the C RTL.
8909 **
8910 ** @param [r] str [const AjPStr] String
8911 ** @param [w] Pval [double*] String represented as a double precision number.
8912 ** @return [AjBool] ajTrue if the string had a valid double precision value.
8913 ** @cre an empty string returns ajFalse.
8914 ** @see ajStrIsInt
8915 **
8916 ** @release 1.0.0
8917 ** @@
8918 ******************************************************************************/
8919
ajStrToDouble(const AjPStr str,double * Pval)8920 AjBool ajStrToDouble(const AjPStr str, double* Pval)
8921 {
8922 AjBool ret = ajFalse;
8923 const char* cp;
8924 double d;
8925 char* ptr = NULL;
8926
8927 *Pval = 0.0;
8928
8929 if(!str)
8930 return ret;
8931
8932 if(!str->Len)
8933 return ret;
8934
8935 cp = str->Ptr;
8936
8937 errno = 0;
8938
8939 #ifdef WIN32
8940 if(ajStrMatchC(str, "NaN") || ajStrMatchC(str, "NAN"))
8941 {
8942 *Pval = 0.0;
8943 return ajTrue;
8944 }
8945 #endif
8946
8947 d = strtod(cp, &ptr);
8948
8949 if(!*ptr && errno != ERANGE)
8950 {
8951 *Pval = d;
8952 ret = ajTrue;
8953 }
8954
8955 return ret;
8956 }
8957
8958
8959
8960
8961 /* @func ajStrToFloat *********************************************************
8962 **
8963 ** Converts a string into a floating point value.
8964 **
8965 ** Uses the strtod call in the C RTL.
8966 **
8967 ** @param [r] str [const AjPStr] String
8968 ** @param [w] Pval [float*] String represented as a floating point number.
8969 ** @return [AjBool] ajTrue if the string had a valid floating point value.
8970 ** @cre an empty string returns ajFalse.
8971 ** @see ajStrIsInt
8972 **
8973 ** @release 1.0.0
8974 ** @@
8975 ******************************************************************************/
8976
ajStrToFloat(const AjPStr str,float * Pval)8977 AjBool ajStrToFloat(const AjPStr str, float* Pval)
8978 {
8979 AjBool ret = ajFalse;
8980 const char* cp;
8981 double d;
8982 char* ptr = NULL;
8983
8984 *Pval = 0.0;
8985
8986 if(!str)
8987 return ret;
8988
8989 if(!str->Len)
8990 return ret;
8991
8992 cp = str->Ptr;
8993
8994 errno = 0;
8995 #ifdef WIN32
8996 if(ajStrMatchC(str, "NaN") || ajStrMatchC(str, "NAN"))
8997 {
8998 *Pval = 0.0;
8999 return ajTrue;
9000 }
9001 #endif
9002
9003 d = strtod(cp, &ptr);
9004
9005 if(!*ptr && errno != ERANGE)
9006 {
9007 if(d > FLT_MAX)
9008 return ajFalse;
9009
9010 if(d < -FLT_MAX)
9011 return ajFalse;
9012
9013 *Pval = (float) d;
9014 ret = ajTrue;
9015 }
9016
9017 return ret;
9018 }
9019
9020
9021
9022
9023 /* @func ajStrToHex ***********************************************************
9024 **
9025 ** Converts a string from hexadecimal into an integer value.
9026 **
9027 ** Uses the strtol call in the C RTL.
9028 **
9029 ** @param [r] str [const AjPStr] String
9030 ** @param [w] Pval [ajint*] String represented as an integer.
9031 ** @return [AjBool] ajTrue if the string had a valid hexadecimal value.
9032 ** @cre an empty string returns ajFalse.
9033 ** @see ajStrIsHex
9034 **
9035 ** @release 1.13.0
9036 ** @@
9037 ******************************************************************************/
9038
ajStrToHex(const AjPStr str,ajint * Pval)9039 AjBool ajStrToHex(const AjPStr str, ajint* Pval)
9040 {
9041 AjBool ret = ajFalse;
9042 const char* cp;
9043 ajlong l;
9044 char* ptr;
9045
9046 *Pval = 0;
9047
9048 if(!str)
9049 return ret;
9050
9051 if(!str->Len)
9052 return ret;
9053
9054 cp = str->Ptr;
9055 errno = 0;
9056 l = strtol(cp, &ptr, 16);
9057
9058 if(!*ptr && errno != ERANGE)
9059 {
9060 l = AJMAX(INT_MIN, l);
9061 l = AJMIN(INT_MAX, l);
9062 *Pval =(ajint) l;
9063 ret = ajTrue;
9064 }
9065
9066 return ret;
9067 }
9068
9069
9070
9071
9072 /* @func ajStrToInt ***********************************************************
9073 **
9074 ** Converts a string into an integer value.
9075 **
9076 ** Uses the strtol call in the C RTL.
9077 **
9078 ** @param [r] str [const AjPStr] String
9079 ** @param [w] Pval [ajint*] String represented as an integer.
9080 ** @return [AjBool] ajTrue if the string had a valid integer value.
9081 ** @cre an empty string returns ajFalse.
9082 ** @see ajStrIsInt
9083 **
9084 ** @release 1.0.0
9085 ** @@
9086 ******************************************************************************/
9087
ajStrToInt(const AjPStr str,ajint * Pval)9088 AjBool ajStrToInt(const AjPStr str, ajint* Pval)
9089 {
9090 AjBool ret = ajFalse;
9091 const char* cp;
9092 ajlong l;
9093 char* ptr;
9094
9095 *Pval = 0;
9096
9097 if(!str)
9098 return ret;
9099
9100 if(!str->Len)
9101 return ret;
9102
9103 cp = str->Ptr;
9104
9105 errno = 0;
9106 l = strtol(cp, &ptr, 10);
9107 if(!*ptr && errno != ERANGE)
9108 {
9109 l = AJMAX(INT_MIN, l);
9110 l = AJMIN(INT_MAX, l);
9111 *Pval =(ajint) l;
9112 ret = ajTrue;
9113 }
9114
9115 return ret;
9116 }
9117
9118
9119
9120
9121 /* @func ajStrToLong **********************************************************
9122 **
9123 ** Converts a string into an integer value.
9124 **
9125 ** Uses the strtol call in the C RTL.
9126 **
9127 ** @param [r] str [const AjPStr] String
9128 ** @param [w] Pval [ajlong*] String represented as an integer.
9129 ** @return [AjBool] ajTrue if the string had a valid integer value.
9130 ** @cre an empty string returns ajFalse.
9131 ** @see ajStrIsInt
9132 **
9133 ** @release 1.0.0
9134 ** @@
9135 ******************************************************************************/
9136
ajStrToLong(const AjPStr str,ajlong * Pval)9137 AjBool ajStrToLong(const AjPStr str, ajlong* Pval)
9138 {
9139 AjBool ret = ajFalse;
9140 const char* cp;
9141 ajlong l;
9142 char* ptr;
9143
9144 *Pval = 0;
9145
9146 if(!str)
9147 return ret;
9148
9149 if(!str->Len)
9150 return ret;
9151
9152 cp = str->Ptr;
9153
9154 errno = 0;
9155 l = strtol(cp, &ptr, 10);
9156
9157 if(!*ptr && errno != ERANGE)
9158 {
9159 *Pval = l;
9160 ret = ajTrue;
9161 }
9162
9163 return ret;
9164 }
9165
9166
9167
9168
9169 /* @func ajStrToUint **********************************************************
9170 **
9171 ** Converts a string into an unsigned integer value.
9172 **
9173 ** Uses the strtoul call in the C RTL from C89 onwards.
9174 **
9175 ** @param [r] str [const AjPStr] String
9176 ** @param [w] Pval [ajuint*] String represented as an unsigned integer.
9177 ** @return [AjBool] ajTrue if the string had a valid unsigned integer value.
9178 ** @cre an empty string returns ajFalse.
9179 ** @see ajStrIsInt
9180 **
9181 ** @release 4.1.0
9182 ** @@
9183 ******************************************************************************/
9184
ajStrToUint(const AjPStr str,ajuint * Pval)9185 AjBool ajStrToUint(const AjPStr str, ajuint* Pval)
9186 {
9187 AjBool ret = ajFalse;
9188 const char* cp;
9189 ajulong l;
9190 char* ptr;
9191
9192 *Pval = 0;
9193
9194 if(!str)
9195 return ret;
9196
9197 if(!str->Len)
9198 return ret;
9199
9200 cp = str->Ptr;
9201
9202 errno = 0;
9203 l = strtoul(cp, &ptr, 10);
9204
9205 if(!*ptr && errno != ERANGE)
9206 {
9207 *Pval =(ajuint) l;
9208 ret = ajTrue;
9209 }
9210
9211 return ret;
9212 }
9213
9214
9215
9216
9217 /* @func ajStrToUlong *********************************************************
9218 **
9219 ** Converts a string into an unsigned long integer value.
9220 **
9221 ** Uses the strtoul call in the C RTL.
9222 **
9223 ** @param [r] str [const AjPStr] String
9224 ** @param [w] Pval [ajulong*] String represented as an integer.
9225 ** @return [AjBool] ajTrue if the string had a valid integer value.
9226 ** @cre an empty string returns ajFalse.
9227 ** @see ajStrIsInt
9228 **
9229 ** @release 6.3.0
9230 ** @@
9231 ******************************************************************************/
9232
ajStrToUlong(const AjPStr str,ajulong * Pval)9233 AjBool ajStrToUlong(const AjPStr str, ajulong* Pval)
9234 {
9235 AjBool ret = ajFalse;
9236 const char* cp;
9237 ajulong l;
9238 char* ptr;
9239
9240 *Pval = 0;
9241
9242 if(!str)
9243 return ret;
9244
9245 if(!str->Len)
9246 return ret;
9247
9248 cp = str->Ptr;
9249
9250 errno = 0;
9251 l = strtoul(cp, &ptr, 10);
9252
9253 if(!*ptr && errno != ERANGE)
9254 {
9255 *Pval = l;
9256 ret = ajTrue;
9257 }
9258
9259 return ret;
9260 }
9261
9262
9263
9264
9265 /* @section datatype to string conversion functions ***************************
9266 **
9267 ** Functions for converting datatypes to strings.
9268 **
9269 ** @fdata [AjPStr]
9270 ** @fnote See also "String to datatype conversion functions: C-type (char*)
9271 ** strings"
9272 ** @nam3rule From Convert a datatype value to a string.
9273 ** @nam4rule FromBool Convert from boolean
9274 ** @nam4rule FromDouble Convert from double
9275 ** @nam5rule FromDoubleExp Convert from double in exponential form
9276 ** @nam4rule FromFloat Convert from float
9277 ** @nam4rule FromInt Convert from integer
9278 ** @nam4rule FromLong Convert from long
9279 ** @nam4rule FromUint Convert from unsigned integer
9280 ** @nam4rule FromVoid Convert from void pointer if it appears to be
9281 ** a string
9282 **
9283 ** @argrule * Pstr [AjPStr*] String result
9284 ** @argrule FromBool val [AjBool] boolean value
9285 ** @argrule FromDouble val [double] Double value
9286 ** @argrule FromFloat val [float] Float value
9287 ** @argrule FromInt val [ajint] Integer value
9288 ** @argrule FromLong val [ajlong] Long integer value
9289 ** @argrule FromDouble precision [ajint] Floating point precision
9290 ** @argrule FromFloat precision [ajint] Floating point precision
9291 ** @argrule FromUint val [ajuint] Unsigned integer value
9292 ** @argrule FromVoid vval [const void*] Void pointer value
9293 **
9294 ** @valrule * [AjBool] True on success
9295 **
9296 ** @fcategory derive
9297 */
9298
9299
9300
9301
9302 /* @func ajStrFromBool ********************************************************
9303 **
9304 ** Converts a Boolean value into a 1-letter string.
9305 **
9306 ** Can be used to print boolean values, but the ajFmt library has better ways.
9307 **
9308 ** @param [w] Pstr [AjPStr*] String to hold the result.
9309 ** @param [r] val [AjBool] Boolean value
9310 ** @return [AjBool] ajTrue if string was reallocated
9311 **
9312 ** @release 1.0.0
9313 ** @@
9314 ******************************************************************************/
9315
ajStrFromBool(AjPStr * Pstr,AjBool val)9316 AjBool ajStrFromBool(AjPStr* Pstr, AjBool val)
9317 {
9318 AjBool ret = ajFalse;
9319 static char bool_y[] = "Y";
9320 static char bool_n[] = "N";
9321
9322 if(val)
9323 ret = ajStrAssignC(Pstr, bool_y);
9324 else
9325 ret = ajStrAssignC(Pstr, bool_n);
9326
9327 return ret;
9328 }
9329
9330
9331
9332
9333 /* @func ajStrFromDouble ******************************************************
9334 **
9335 ** Converts a double precision value into a string.
9336 **
9337 ** The string size is set to be just large enough to hold the value.
9338 **
9339 ** @param [w] Pstr [AjPStr*] Target string
9340 ** @param [r] val [double] Double precision value
9341 ** @param [r] precision [ajint] Precision (number of decimal places) to use.
9342 ** @return [AjBool] ajTrue if string was reallocated
9343 **
9344 ** @release 1.0.0
9345 ** @@
9346 ******************************************************************************/
9347
ajStrFromDouble(AjPStr * Pstr,double val,ajint precision)9348 AjBool ajStrFromDouble(AjPStr* Pstr, double val, ajint precision)
9349 {
9350 AjBool ret = ajFalse;
9351 long long i;
9352 char fmt[12];
9353
9354 if(val)
9355 i = precision + ajNumLengthDouble(val) + 3;
9356 else
9357 i = precision + 4;
9358
9359 ret = ajStrSetResRound(Pstr, (ajuint)i);
9360
9361 sprintf(fmt, "%%.%df", precision);
9362 ajFmtPrintS(Pstr, fmt, val);
9363
9364 return ret ;
9365 }
9366
9367
9368
9369
9370 /* @func ajStrFromDoubleExp ***************************************************
9371 **
9372 ** Converts a double precision value into a string.
9373 **
9374 ** The string size is set to be just large enough to hold the value. Uses
9375 ** exponential form.
9376 **
9377 ** @param [w] Pstr [AjPStr*] Target string
9378 ** @param [r] val [double] Double precision value
9379 ** @param [r] precision [ajint] Precision (number of decimal places) to use.
9380 ** @return [AjBool] ajTrue if string was reallocated
9381 **
9382 ** @release 4.0.0
9383 ** @@
9384 ******************************************************************************/
9385
ajStrFromDoubleExp(AjPStr * Pstr,double val,ajint precision)9386 AjBool ajStrFromDoubleExp(AjPStr* Pstr, double val, ajint precision)
9387 {
9388 AjBool ret = ajFalse;
9389 long long i;
9390 char fmt[12];
9391
9392 if(val)
9393 i = precision + ajNumLengthDouble(val) + 8;
9394 else
9395 i = precision + 8;
9396
9397 ret = ajStrSetResRound(Pstr, (ajuint)i);
9398
9399 sprintf(fmt, "%%.%de", precision);
9400 ajFmtPrintS(Pstr, fmt, val);
9401
9402 return ret ;
9403 }
9404
9405
9406
9407
9408 /* @func ajStrFromFloat *******************************************************
9409 **
9410 ** Converts a floating point value into a string.
9411 **
9412 ** The string size is set to be just large enough to hold the value.
9413 **
9414 ** @param [w] Pstr [AjPStr*] Target string
9415 ** @param [r] val [float] Floating point value
9416 ** @param [r] precision [ajint] Precision (number of decimal places) to use.
9417 ** @return [AjBool] ajTrue if string was reallocated
9418 **
9419 ** @release 1.0.0
9420 ** @@
9421 ******************************************************************************/
9422
ajStrFromFloat(AjPStr * Pstr,float val,ajint precision)9423 AjBool ajStrFromFloat(AjPStr* Pstr, float val, ajint precision)
9424 {
9425 AjBool ret = ajFalse;
9426 ajuint i;
9427 char fmt[12];
9428
9429 if(val)
9430 i = precision + ajNumLengthFloat(val) + 4;
9431 else
9432 i = precision + 4;
9433
9434 ret = ajStrSetResRound(Pstr, i);
9435
9436 sprintf(fmt, "%%.%df", precision);
9437 ajFmtPrintS(Pstr, fmt, val);
9438
9439 return ret;
9440 }
9441
9442
9443
9444
9445 /* @func ajStrFromInt *********************************************************
9446 **
9447 ** Converts an integer value into a string.
9448 **
9449 ** The string size is set to be just large enough to hold the value.
9450 **
9451 ** @param [w] Pstr [AjPStr*] Target string
9452 ** @param [r] val [ajint] Integer value
9453 ** @return [AjBool] ajTrue if string was reallocated
9454 **
9455 ** @release 1.0.0
9456 ** @@
9457 ******************************************************************************/
9458
ajStrFromInt(AjPStr * Pstr,ajint val)9459 AjBool ajStrFromInt(AjPStr* Pstr, ajint val)
9460 {
9461 AjBool ret = ajFalse;
9462 ajuint i;
9463
9464 if(val)
9465 i = ajNumLengthInt(val) + 2;
9466 else
9467 i = 2;
9468
9469 if(val < 0)
9470 i++;
9471
9472 ret = ajStrSetResRound(Pstr, i);
9473
9474 ajFmtPrintS(Pstr, "%d", val);
9475
9476 return ret ;
9477 }
9478
9479
9480
9481
9482 /* @func ajStrFromLong ********************************************************
9483 **
9484 ** Converts an ajlong integer value into a string.
9485 **
9486 ** The string size is set to be just large enough to hold the value.
9487 **
9488 ** @param [w] Pstr [AjPStr*] Target string
9489 ** @param [r] val [ajlong] Long integer value
9490 ** @return [AjBool] ajTrue if string was reallocated
9491 **
9492 ** @release 1.0.0
9493 ** @@
9494 ******************************************************************************/
9495
ajStrFromLong(AjPStr * Pstr,ajlong val)9496 AjBool ajStrFromLong(AjPStr* Pstr, ajlong val)
9497 {
9498 AjBool ret = ajFalse;
9499 ajlong i;
9500
9501 if(val)
9502 i = ajNumLengthUint(val) + 2;
9503 else
9504 i = 2;
9505
9506 if(val < 0)
9507 i++;
9508
9509 ret = ajStrSetResRound(Pstr, (size_t) i);
9510
9511 ajFmtPrintS(Pstr, "%ld", (long)val);
9512
9513 return ret;
9514 }
9515
9516
9517
9518
9519 /* @func ajStrFromUint ********************************************************
9520 **
9521 ** Converts an unsigned integer value into a string.
9522 **
9523 ** The string size is set to be just large enough to hold the value.
9524 **
9525 ** @param [w] Pstr [AjPStr*] Target string
9526 ** @param [r] val [ajuint] Integer value
9527 ** @return [AjBool] ajTrue if string was reallocated
9528 **
9529 ** @release 4.1.0
9530 ** @@
9531 ******************************************************************************/
9532
ajStrFromUint(AjPStr * Pstr,ajuint val)9533 AjBool ajStrFromUint(AjPStr* Pstr, ajuint val)
9534 {
9535 AjBool ret = ajFalse;
9536 ajuint i;
9537 AjPStr thys;
9538
9539 if(val)
9540 i = ajNumLengthUint(val) + 1;
9541 else
9542 i = 2;
9543
9544 ret = ajStrSetResRound(Pstr, i);
9545 thys = *Pstr;
9546
9547 thys->Len = sprintf(thys->Ptr, "%u", val);
9548 ajFmtPrintS(Pstr, "%u", val);
9549
9550 return ret ;
9551 }
9552
9553
9554
9555
9556 /* @func ajStrFromVoid ********************************************************
9557 **
9558 ** Tests a void pointer and if it is potentially an ASCII string
9559 ** saves it as the output string.
9560 **
9561 ** The string size is set to be just large enough to hold the value.
9562 **
9563 ** Intended to allow possible strings to be reported in tables and lists
9564 ** where they must be held as void* pointers
9565 **
9566 ** @param [w] Pstr [AjPStr*] Target string
9567 ** @param [r] vval [const void*] Integer value
9568 ** @return [AjBool] ajTrue if string was found
9569 **
9570 ** @release 6.4.0
9571 ** @@
9572 ******************************************************************************/
9573
ajStrFromVoid(AjPStr * Pstr,const void * vval)9574 AjBool ajStrFromVoid(AjPStr* Pstr, const void* vval)
9575 {
9576 const AjPStr str = (const AjPStr) vval;
9577
9578 size_t ires;
9579 size_t ilen;
9580
9581 ajStrAssignC(Pstr, "<not a string>");
9582
9583 ires = str->Res;
9584 ilen = str->Len;
9585
9586 if((ilen+1) > ires)
9587 return ajFalse;
9588
9589 if(ires > 4096)
9590 return ajFalse;
9591
9592 if(str->Ptr[ilen])
9593 return ajFalse;
9594
9595 ajStrAssignS(Pstr, str);
9596
9597 return ajTrue;
9598 }
9599
9600
9601
9602
9603 /* @section formatting ********************************************************
9604 **
9605 ** Functions for formatting strings.
9606 **
9607 ** @fdata [AjPStr]
9608 ** @fnote Same namrule as "String formatting functions: C-type (char*)
9609 ** strings".
9610 ** @nam3rule Fmt Change the format of a string.
9611 ** @nam4rule FmtBlock Format in blocks
9612 ** @nam4rule FmtCapital Convert to captal for start of each word
9613 ** @nam4rule FmtLower Convert to lower case.
9614 ** @nam5rule FmtLowerSub Convert sub-string.
9615 ** @nam4rule FmtPercent URL percent-encoding
9616 ** @nam5rule FmtPercentDecode Decode URL percent-encoding
9617 ** @nam5rule FmtPercentEncode Encode using URL percent-encoding
9618 ** @nam4rule FmtQuery Convert to a standard EMBOSS query in lower case
9619 ** with white space replaced by an underscore
9620 ** @nam4rule FmtQuote Enclose in double quotes
9621 ** @nam4rule FmtTitle Convert first character of string to upper case.
9622 ** @nam4rule FmtUpper Convert to upper case.
9623 ** @nam5rule FmtUpperSub Substring only
9624 ** @nam4rule FmtWord Make into a word by replacing whitespace
9625 ** @nam4rule FmtWrap Wrap with newlines
9626 ** @nam5rule FmtWrapAt Wrap with newlines at a preferred character
9627 ** @nam5rule FmtWrapLeft Wrap with newlines and left margin of spaces
9628 ** @suffix C C string
9629 ** @suffix S String object
9630 **
9631 ** @argrule * Pstr [AjPStr*] String
9632 ** @argrule FmtBlock len [ajulong] Block length
9633 ** @argrule Sub pos1 [ajlong] Start position, negative value counts from end
9634 ** @argrule Sub pos2 [ajlong] End position, negative value counts from end
9635 ** @argrule Wrap width [ajuint] Line length
9636 ** @argrule WrapAt ch [char] Preferred last character on line
9637 ** @argrule WrapLeft margin [ajuint] Left margin
9638 ** @argrule WrapLeft indent [ajuint] Indentation on later lines
9639 ** @argrule EncodeC txt [const char*] Characters to encode
9640 ** @argrule EncodeS str [const AjPStr] Characters to encode
9641 **
9642 ** @valrule * [AjBool] True on success
9643 **
9644 ** @fcategory modify
9645 */
9646
9647
9648
9649
9650 /* @func ajStrFmtBlock ********************************************************
9651 **
9652 ** Splits a string into words (blocks) of a given size by inserting spaces.
9653 **
9654 ** Mainly intended for sequence output formats
9655 **
9656 ** @param [u] Pstr [AjPStr*] String.
9657 ** @param [r] len [ajulong] Block size
9658 ** @return [AjBool] ajTrue on success
9659 **
9660 ** @release 4.0.0
9661 ** @@
9662 ******************************************************************************/
9663
ajStrFmtBlock(AjPStr * Pstr,ajulong len)9664 AjBool ajStrFmtBlock(AjPStr* Pstr, ajulong len)
9665 {
9666 size_t i;
9667 char* cp;
9668 char* cq;
9669 AjPStr thys;
9670 ajuint j;
9671
9672 i = (size_t) ((*Pstr)->Len + ((*Pstr)->Len-1)/len);
9673 ajStrSetResRound(Pstr, i+1);
9674 thys = *Pstr;
9675
9676 /*
9677 ajDebug("ajStrBlock len: %d blksize: %d i: %d\n", thys->Len, blksize, i);
9678 */
9679
9680 cp = &thys->Ptr[thys->Len];
9681 cq = &thys->Ptr[i];
9682
9683 for(j=thys->Len-1; j; j--)
9684 {
9685 *(--cq) = *(--cp);
9686
9687 if(!(j%len))
9688 *(--cq) = ' ';
9689 }
9690
9691 thys->Ptr[i]='\0';
9692 thys->Len = i;
9693
9694 ajStrTrace(thys);
9695
9696 /*
9697 ajDebug("result '%S'\n", thys);
9698 */
9699
9700 return ajTrue;
9701 }
9702
9703
9704
9705
9706 /* @func ajStrFmtCapital ******************************************************
9707 **
9708 ** Converts the first character of each word in a string to upper case.
9709 **
9710 ** @param [u] Pstr [AjPStr*] String
9711 ** @return [AjBool] ajTrue if string was reallocated
9712 **
9713 ** @release 6.6.0
9714 ** @@
9715 ******************************************************************************/
9716
ajStrFmtCapital(AjPStr * Pstr)9717 AjBool ajStrFmtCapital(AjPStr* Pstr)
9718 {
9719 AjPStr thys;
9720 char* cp;
9721 AjBool wasspace = ajTrue;
9722
9723 ajStrFmtLower(Pstr);
9724
9725 if(!*Pstr)
9726 *Pstr = ajStrNewResLenC("", 1, 0);
9727 else if((*Pstr)->Use > 1)
9728 ajStrGetuniqueStr(Pstr);
9729
9730 thys = *Pstr;
9731
9732 cp = thys->Ptr;
9733
9734 while(*cp)
9735 {
9736 if(wasspace && isalpha((int)*cp))
9737 {
9738 *cp = (char) toupper((int)*cp);
9739 wasspace = ajFalse;
9740
9741 }
9742
9743 if(isspace((int)*cp))
9744 wasspace = ajTrue;
9745
9746 cp++;
9747 }
9748
9749 return ajFalse;
9750 }
9751
9752
9753
9754
9755 /* @func ajStrFmtLower ********************************************************
9756 **
9757 ** Converts a string to lower case.
9758 **
9759 ** If the string has multiple references, a new string is made first.
9760 **
9761 ** @param [u] Pstr [AjPStr*] String
9762 ** @return [AjBool] ajTrue if string was reallocated
9763 **
9764 ** @release 4.0.0
9765 ** @@
9766 ******************************************************************************/
9767
ajStrFmtLower(AjPStr * Pstr)9768 AjBool ajStrFmtLower(AjPStr* Pstr)
9769 {
9770 AjPStr thys;
9771
9772 if(!*Pstr)
9773 *Pstr = ajStrNewResLenC("", 1, 0);
9774 else if((*Pstr)->Use > 1)
9775 ajStrGetuniqueStr(Pstr);
9776 thys = *Pstr;
9777
9778 ajCharFmtLower(thys->Ptr);
9779
9780 return ajTrue;
9781 }
9782
9783
9784
9785
9786 /* @func ajStrFmtLowerSub *****************************************************
9787 **
9788 ** Converts a substring of a string to lower case.
9789 **
9790 ** @param [u] Pstr [AjPStr*] String
9791 ** @param [r] pos1 [ajlong] start position for conversion
9792 ** @param [r] pos2 [ajlong] end position for conversion
9793 ** @return [AjBool] ajTrue if string was reallocated
9794 **
9795 ** @release 4.0.0
9796 ** @@
9797 ******************************************************************************/
9798
ajStrFmtLowerSub(AjPStr * Pstr,ajlong pos1,ajlong pos2)9799 AjBool ajStrFmtLowerSub(AjPStr* Pstr, ajlong pos1, ajlong pos2)
9800 {
9801 AjPStr thys;
9802 size_t ibegin;
9803 size_t iend;
9804 size_t i;
9805
9806 if(!*Pstr)
9807 *Pstr = ajStrNewResLenC("", 1, 0);
9808 else if((*Pstr)->Use > 1)
9809 ajStrGetuniqueStr(Pstr);
9810
9811 thys = *Pstr;
9812
9813 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos1);
9814 iend = ajCvtSposToPosStart(thys->Len, ibegin, pos2);
9815
9816 for (i=ibegin; i<=iend;i++)
9817 thys->Ptr[i] = (char)tolower((int) thys->Ptr[i]);
9818
9819 return ajTrue;
9820 }
9821
9822
9823
9824
9825 /* @func ajStrFmtPercentDecode ************************************************
9826 **
9827 ** Converts percent-encoded characters
9828 **
9829 ** @param [u] Pstr [AjPStr *] string
9830 **
9831 ** @return [AjBool] True if string is not empty.
9832 **
9833 ** @release 6.4.0
9834 ** @@
9835 ******************************************************************************/
9836
ajStrFmtPercentDecode(AjPStr * Pstr)9837 AjBool ajStrFmtPercentDecode(AjPStr* Pstr)
9838 {
9839 AjPStr thys;
9840
9841 char *cp;
9842 char *cq;
9843 int ia;
9844
9845 if(!*Pstr)
9846 *Pstr = ajStrNewResLenC("", 1, 0);
9847 else if((*Pstr)->Use > 1)
9848 ajStrGetuniqueStr(Pstr);
9849
9850 thys = *Pstr;
9851 cp = thys->Ptr;
9852 cq = thys->Ptr;
9853
9854 while(*cp)
9855 {
9856 if(*cp != '%')
9857 {
9858 *cq++ = *cp++;
9859 }
9860 else
9861 {
9862 ia = 0;
9863 cp++;
9864 if(!*cp) break;
9865 if(*cp >= '0' && *cp <= '9')
9866 ia += 16 * (*cp - '0');
9867 else if(*cp >= 'A' && *cp <= 'F')
9868 ia += 16 * (10 + (*cp - 'A'));
9869 else if(*cp >= 'a' && *cp <= 'f')
9870 ia += 16 * (10 + (*cp - 'a'));
9871 cp++;
9872 if(!*cp) break;
9873 if(*cp >= '0' && *cp <= '9')
9874 ia += (*cp - '0');
9875 else if(*cp >= 'A' && *cp <= 'F')
9876 ia += (10 + (*cp - 'A'));
9877 else if(*cp >= 'a' && *cp <= 'f')
9878 ia += (10 + (*cp - 'a'));
9879 *cq++ = (char) ia;
9880 cp++;
9881 }
9882 }
9883
9884 *cq = '\0';
9885 thys->Len = cq - thys->Ptr;
9886
9887 return ajTrue;
9888 }
9889
9890
9891
9892
9893 /* @func ajStrFmtPercentEncodeC ***********************************************
9894 **
9895 ** Percent-encoded specified characters
9896 **
9897 ** @param [u] Pstr [AjPStr *] string
9898 ** @param [r] txt [const char*] Characters to encode
9899 **
9900 ** @return [AjBool] True if string is not empty.
9901 **
9902 ** @release 6.4.0
9903 ** @@
9904 ******************************************************************************/
9905
ajStrFmtPercentEncodeC(AjPStr * Pstr,const char * txt)9906 AjBool ajStrFmtPercentEncodeC(AjPStr* Pstr, const char* txt)
9907 {
9908 AjPStr thys;
9909 AjPStr copy;
9910
9911 char *cp;
9912 char *cq;
9913 int ia;
9914 int ip;
9915 int iq;
9916 size_t ir;
9917 ajuint i;
9918 ajuint npct;
9919
9920 AjBool changed = ajFalse;
9921
9922 if(!*Pstr)
9923 *Pstr = ajStrNewResLenC("", 1, 0);
9924 else if((*Pstr)->Use > 1)
9925 ajStrGetuniqueStr(Pstr);
9926
9927 thys = *Pstr;
9928 npct = (ajuint) ajStrCalcCountC(thys, txt);
9929 if(!npct)
9930 return ajTrue;
9931
9932 copy = ajStrNewS(thys);
9933 ajStrSetRes(Pstr, thys->Len + 3*npct);
9934 thys = *Pstr;
9935
9936 cp = copy->Ptr;
9937 cq = thys->Ptr;
9938
9939 while(*cp)
9940 {
9941 ir = strcspn(cp, txt);
9942
9943 for(i=0; i < ir; i++)
9944 *cq++ = *cp++;
9945
9946 if(*cp)
9947 {
9948 changed = ajTrue;
9949 ia = (int) *cp;
9950 ip = ia / 16;
9951 iq = ia % 16;
9952
9953 *cq++ = '%';
9954
9955 if(ip < 10)
9956 *cq++ = '0' + ip;
9957 else
9958 *cq++ = 'A' - 10 + ip;
9959
9960 if(iq < 10)
9961 *cq++ = '0' + iq;
9962 else
9963 *cq++ = 'A' - 10 + iq;
9964
9965 cp++;
9966 }
9967 }
9968
9969 *cq = '\0';
9970 thys->Len = cq - thys->Ptr;
9971
9972 if(changed)
9973 ajDebug("ajStrFmtPercentEncodeC changed '%s' '%S' => '%S'\n",
9974 txt, copy, thys);
9975
9976 ajStrDel(©);
9977
9978 return ajTrue;
9979 }
9980
9981
9982
9983
9984 /* @func ajStrFmtPercentEncodeS ***********************************************
9985 **
9986 ** Percent-encoded specified characters
9987 **
9988 ** @param [u] Pstr [AjPStr *] string
9989 ** @param [r] str [const AjPStr] Characters to encode
9990 **
9991 ** @return [AjBool] True if string is not empty.
9992 **
9993 ** @release 6.4.0
9994 ** @@
9995 ******************************************************************************/
9996
ajStrFmtPercentEncodeS(AjPStr * Pstr,const AjPStr str)9997 AjBool ajStrFmtPercentEncodeS(AjPStr* Pstr, const AjPStr str)
9998 {
9999 return ajStrFmtPercentEncodeC(Pstr, MAJSTRGETPTR(str));
10000 }
10001
10002
10003
10004
10005 /* @func ajStrFmtQuery ********************************************************
10006 **
10007 ** Ensures a string is a standard EMBOSS query term with all
10008 ** alphabetic characters in lower case, and any non alphanumeric characters
10009 ** replaced by an underscore
10010 **
10011 ** @param [u] Pstr [AjPStr *] string
10012 **
10013 ** @return [AjBool] True if string is not empty.
10014 **
10015 ** @release 6.4.0
10016 ** @@
10017 ******************************************************************************/
10018
ajStrFmtQuery(AjPStr * Pstr)10019 AjBool ajStrFmtQuery(AjPStr* Pstr)
10020 {
10021 AjPStr thys;
10022
10023 static char filter[256];
10024 static int spaces[256];
10025 static AjBool called = AJFALSE;
10026
10027 char *cp;
10028 char *cq;
10029
10030 int c;
10031 int ispace = 0;
10032 int iextra = 0;
10033
10034 if(!called)
10035 {
10036 for(c=0; c<256; c++)
10037 {
10038 if(isalnum(c) || strchr("*?.", c))
10039 {
10040 spaces[c] = 0;
10041 if(isupper(c))
10042 filter[c] = tolower(c);
10043 else
10044 filter[c] = c;
10045 }
10046 else
10047 {
10048 spaces[c] = 1;
10049 filter[c] = '_';
10050 }
10051 }
10052
10053 spaces[0] = 0;
10054
10055 called = ajTrue;
10056 }
10057
10058 if(!*Pstr)
10059 *Pstr = ajStrNewResLenC("", 1, 0);
10060 else if((*Pstr)->Use > 1)
10061 ajStrGetuniqueStr(Pstr);
10062
10063 thys = *Pstr;
10064 cp = thys->Ptr;
10065 cq = thys->Ptr;
10066
10067 while(*cp)
10068 {
10069 while(spaces[(int)*cp])
10070 {
10071 ispace++;
10072 cp++;
10073 }
10074 if(ispace)
10075 {
10076 iextra += ispace-1;
10077 *cq++ = '_';
10078 ispace = 0;
10079 }
10080
10081 while(*cp && !spaces[(int)*cp])
10082 *cq++ = filter[(int)*cp++];
10083 }
10084
10085 *cq = '\0';
10086 thys->Len -= iextra;
10087
10088 return ajTrue;
10089 }
10090
10091
10092
10093
10094 /* @func ajStrFmtQuote ********************************************************
10095 **
10096 ** Ensures a string is quoted with double quotes.
10097 **
10098 ** @param [u] Pstr [AjPStr *] string
10099 **
10100 ** @return [AjBool] True if string is not empty.
10101 ** As it is at least quoted, it will always return true.
10102 **
10103 ** @release 4.0.0
10104 ** @@
10105 ******************************************************************************/
10106
ajStrFmtQuote(AjPStr * Pstr)10107 AjBool ajStrFmtQuote(AjPStr* Pstr)
10108 {
10109 if(ajStrGetCharFirst(*Pstr) != '"')
10110 ajStrInsertC(Pstr, 0, "\"");
10111
10112 /* careful: could be an empty string that is now '"' */
10113 /* this is the only way to have a length of 1 */
10114
10115 if((*Pstr)->Len == 1 || ajStrGetCharLast(*Pstr) != '"')
10116 ajStrAppendK(Pstr, '"');
10117
10118 if(!(*Pstr)->Len)
10119 return ajFalse;
10120
10121 return ajTrue;
10122 }
10123
10124
10125
10126
10127 /* @func ajStrFmtTitle ********************************************************
10128 **
10129 ** Converts the first character of a string to upper case.
10130 **
10131 ** @param [u] Pstr [AjPStr*] String
10132 ** @return [AjBool] ajTrue if string was reallocated
10133 **
10134 ** @release 4.0.0
10135 ** @@
10136 ******************************************************************************/
10137
ajStrFmtTitle(AjPStr * Pstr)10138 AjBool ajStrFmtTitle(AjPStr* Pstr)
10139 {
10140 AjPStr thys;
10141 char* cp;
10142
10143 ajStrFmtLower(Pstr);
10144
10145 if(!*Pstr)
10146 *Pstr = ajStrNewResLenC("", 1, 0);
10147 else if((*Pstr)->Use > 1)
10148 ajStrGetuniqueStr(Pstr);
10149
10150 thys = *Pstr;
10151
10152 cp = thys->Ptr;
10153
10154 while(*cp)
10155 {
10156 if(isalpha((int)*cp))
10157 {
10158 *cp = (char) toupper((int)*cp);
10159
10160 return ajTrue;
10161 }
10162
10163 cp++;
10164 }
10165
10166 return ajFalse;
10167 }
10168
10169
10170
10171
10172 /* @func ajStrFmtUpper ********************************************************
10173 **
10174 ** Converts a string to upper case.
10175 **
10176 ** If the string has multiple references, a new string is made first.
10177 **
10178 ** @param [u] Pstr [AjPStr*] String
10179 ** @return [AjBool] ajTrue if string was reallocated
10180 **
10181 ** @release 4.0.0
10182 ** @@
10183 ******************************************************************************/
10184
ajStrFmtUpper(AjPStr * Pstr)10185 AjBool ajStrFmtUpper(AjPStr* Pstr)
10186 {
10187 AjPStr thys;
10188
10189 if(!*Pstr)
10190 *Pstr = ajStrNewResLenC("", 1, 0);
10191 else if((*Pstr)->Use > 1)
10192 ajStrGetuniqueStr(Pstr);
10193
10194 thys = *Pstr;
10195
10196 ajCharFmtUpper(thys->Ptr);
10197
10198 return ajTrue;
10199 }
10200
10201
10202
10203
10204 /* @func ajStrFmtUpperSub *****************************************************
10205 **
10206 ** Converts a substring of a string to upper case.
10207 **
10208 ** @param [u] Pstr [AjPStr*] String
10209 ** @param [r] pos1 [ajlong] start position for conversion
10210 ** @param [r] pos2 [ajlong] end position for conversion
10211 ** @return [AjBool] ajTrue if string was reallocated
10212 **
10213 ** @release 4.0.0
10214 ** @@
10215 ******************************************************************************/
10216
ajStrFmtUpperSub(AjPStr * Pstr,ajlong pos1,ajlong pos2)10217 AjBool ajStrFmtUpperSub(AjPStr* Pstr, ajlong pos1, ajlong pos2)
10218 {
10219 AjPStr thys;
10220 size_t ibegin;
10221 size_t iend;
10222 size_t i;
10223
10224 if(!*Pstr)
10225 *Pstr = ajStrNewResLenC("", 1, 0);
10226 else if((*Pstr)->Use > 1)
10227 ajStrGetuniqueStr(Pstr);
10228
10229 thys = *Pstr;
10230
10231 ibegin = ajCvtSposToPosStart(thys->Len, 0, pos1);
10232 iend = ajCvtSposToPosStart(thys->Len, ibegin, pos2);
10233
10234 for (i=ibegin; i<=iend;i++)
10235 thys->Ptr[i] = (char)toupper((int) thys->Ptr[i]);
10236
10237 return ajTrue;
10238 }
10239
10240
10241
10242
10243 /* @func ajStrFmtWord *********************************************************
10244 **
10245 ** Converts a string to a single word. Spaces are converted to underscores.
10246 ** Leading substrings ending in a colon are removed.
10247 **
10248 ** @param [u] Pstr [AjPStr*] String
10249 ** @return [AjBool] ajTrue on success
10250 **
10251 ** @release 6.4.0
10252 ** @@
10253 ******************************************************************************/
10254
ajStrFmtWord(AjPStr * Pstr)10255 AjBool ajStrFmtWord(AjPStr* Pstr)
10256 {
10257 ajlong colpos;
10258
10259 if(!*Pstr)
10260 *Pstr = ajStrNewResLenC("", 1, 0);
10261 else if((*Pstr)->Use > 1)
10262 ajStrGetuniqueStr(Pstr);
10263
10264 if(!ajStrIsWord(*Pstr))
10265 {
10266 /* ajDebug("ajStrFmtWord non-word '%S'\n", *Pstr); */
10267 ajStrRemoveWhiteExcess(Pstr);
10268 ajStrExchangeKK(Pstr, ' ', '_');
10269 /* ajDebug("ajStrFmtWord cleaned '%S'\n", *Pstr); */
10270 }
10271
10272 /* ajDebug("ajStrFmtWord word '%S'\n", *Pstr); */
10273 if(ajStrGetCharLast(*Pstr) == ':')
10274 ajStrTrimEndC(Pstr, ":");
10275
10276 colpos = 1 + ajStrFindlastK(*Pstr, ':');
10277
10278 if(colpos)
10279 ajStrKeepRange(Pstr, colpos, -1);
10280
10281 return ajTrue;
10282 }
10283
10284
10285
10286
10287 /* @func ajStrFmtWrap *********************************************************
10288 **
10289 ** Formats a string so that it wraps when printed.
10290 **
10291 ** Newline characters are inserted, at white space if possible,
10292 ** with a break at whitespace following the preferred character
10293 ** if found, or at the last whitespace, or just at the line width if there
10294 ** is no whitespace found (it does happen with long hyphenated enzyme names)
10295 **
10296 ** @param [u] Pstr [AjPStr*] Target string
10297 ** @param [r] width [ajuint] Line width
10298 ** @return [AjBool] ajTrue on successful completion else ajFalse;
10299 **
10300 ** @release 4.0.0
10301 ** @@
10302 ******************************************************************************/
10303
ajStrFmtWrap(AjPStr * Pstr,ajuint width)10304 AjBool ajStrFmtWrap(AjPStr* Pstr, ajuint width)
10305 {
10306 AjPStr thys;
10307 char* cq;
10308 size_t i;
10309 size_t j;
10310 size_t k;
10311 size_t imax;
10312
10313 if(!*Pstr)
10314 *Pstr = ajStrNewResLenC("", 1, 0);
10315 else if((*Pstr)->Use > 1)
10316 ajStrGetuniqueStr(Pstr);
10317
10318 thys = *Pstr;
10319
10320 if(width > (*Pstr)->Len) /* already fits on one line */
10321 return ajTrue;
10322
10323 cq = thys->Ptr;
10324 i=0;
10325 imax = thys->Len - width;
10326
10327 ajDebug("ajStrFmtWrap imax:%u len:%u '%S'\n",
10328 imax, MAJSTRGETLEN(thys), *Pstr);
10329
10330 while(i < imax)
10331 {
10332 j = i+width+1;
10333
10334 if(j > thys->Len)
10335 j = thys->Len;
10336
10337 k = j;
10338
10339 while(i < j)
10340 {
10341 if(isspace((ajint)*cq))
10342 {
10343 k = i;
10344
10345 if(*cq == '\n')
10346 break;
10347 }
10348
10349 cq++;
10350 i++;
10351 }
10352
10353 if(*cq != '\n')
10354 {
10355 if(k == j)
10356 {
10357 ajStrInsertC(Pstr, k, "\n");
10358 imax++;
10359 }
10360 else
10361 thys->Ptr[k] = '\n';
10362 }
10363
10364 i=k+1;
10365 cq=&thys->Ptr[i];
10366 ajDebug("k:%u len:%u i:%u imax:%u '%s'\n",
10367 k, MAJSTRGETLEN(thys)-k-1, i, imax, &thys->Ptr[k+1]);
10368 }
10369
10370 ajDebug("Done i:%u\n", i);
10371
10372 return ajTrue;
10373 }
10374
10375
10376
10377
10378 /* @func ajStrFmtWrapAt *******************************************************
10379 **
10380 ** Formats a string so that it wraps when printed.
10381 ** Breaks are at a preferred character (for example ',' for author lists)
10382 **
10383 ** Newline characters are inserted, at white space if possible,
10384 ** with a break at whitespace following the preferred character
10385 ** if found, or at the last whitespace, or just at the line width if there
10386 ** is no whitespace found (it does happen with long hyphenated enzyme names)
10387 **
10388 ** @param [u] Pstr [AjPStr*] Target string
10389 ** @param [r] width [ajuint] Line width
10390 ** @param [r] ch [char] Preferred last character on line
10391 ** @return [AjBool] ajTrue on successful completion else ajFalse;
10392 **
10393 ** @release 5.0.0
10394 ** @@
10395 ******************************************************************************/
10396
ajStrFmtWrapAt(AjPStr * Pstr,ajuint width,char ch)10397 AjBool ajStrFmtWrapAt(AjPStr* Pstr, ajuint width, char ch)
10398 {
10399 AjPStr thys;
10400 char* cq;
10401 size_t i;
10402 size_t j;
10403 size_t k;
10404 size_t kk;
10405 size_t imax;
10406
10407 if(!*Pstr)
10408 *Pstr = ajStrNewResLenC("", 1, 0);
10409 else if((*Pstr)->Use > 1)
10410 ajStrGetuniqueStr(Pstr);
10411
10412 thys = *Pstr;
10413
10414 if(width > (*Pstr)->Len) /* already fits on one line */
10415 return ajTrue;
10416
10417 cq = thys->Ptr;
10418 i=0;
10419 imax = thys->Len - width;
10420
10421 ajDebug("ajStrFmtWrapPref '%c' imax:%u len:%u '%S'\n",
10422 ch, imax, MAJSTRGETLEN(thys), *Pstr);
10423
10424 while(i < imax)
10425 {
10426 j = i+width+1;
10427
10428 if(j > thys->Len)
10429 j = thys->Len;
10430
10431 k = j;
10432 kk = j;
10433
10434 while(i < j)
10435 {
10436 if(isspace((ajint)*cq))
10437 {
10438 k = i;
10439
10440 if(*cq == '\n')
10441 break;
10442
10443 if(i && thys->Ptr[i-1] == ch)
10444 kk = i;
10445 }
10446
10447 cq++;
10448 i++;
10449 }
10450
10451 if(*cq != '\n')
10452 {
10453 if(kk < j)
10454 {
10455 thys->Ptr[kk] = '\n';
10456 k = kk;
10457 }
10458 else if(k == j)
10459 {
10460 ajStrInsertC(Pstr, k, "\n");
10461 imax++;
10462 }
10463 else
10464 thys->Ptr[k] = '\n';
10465 }
10466
10467 i=k+1;
10468 cq=&thys->Ptr[i];
10469 ajDebug("k:%u len:%u i:%u imax:%u '%s'\n",
10470 k, MAJSTRGETLEN(thys)-k-1, i, imax, &thys->Ptr[k+1]);
10471 }
10472
10473 ajDebug("Done i:%u\n", i);
10474
10475 return ajTrue;
10476 }
10477
10478
10479
10480
10481 /* @func ajStrFmtWrapLeft *****************************************************
10482 **
10483 ** Formats a string so that it wraps and has a margin of space characters
10484 ** and an additional indent when printed.
10485 **
10486 ** Newline characters are inserted, at white space if possible,
10487 **
10488 ** @param [u] Pstr [AjPStr*] Target string
10489 ** @param [r] width [ajuint] Line width
10490 ** @param [r] margin [ajuint] Left margin
10491 ** @param [r] indent [ajuint] Left indentation on later lines
10492 ** @return [AjBool] ajTrue on successful completion else ajFalse;
10493 **
10494 ** @release 4.0.0
10495 ** @@
10496 ******************************************************************************/
10497
ajStrFmtWrapLeft(AjPStr * Pstr,ajuint width,ajuint margin,ajuint indent)10498 AjBool ajStrFmtWrapLeft(AjPStr* Pstr, ajuint width,
10499 ajuint margin, ajuint indent)
10500 {
10501 AjPStr newstr = NULL;
10502 char* cp;
10503 size_t len;
10504 size_t i = 0;
10505 size_t j;
10506 size_t isp = 0;
10507 size_t leftmargin = margin;
10508 size_t maxwidth = width + indent;
10509
10510 /* ajDebug("ajStrFmtWrapLeft %d %d %d\n'%S'\n",
10511 width, margin, indent, *Pstr); */
10512
10513 len = 1 + (*Pstr)->Len + (indent + margin + 1) * (*Pstr)->Len / width;
10514 ajStrAssignS(&newstr, *Pstr);
10515 ajStrAssignResC(Pstr, len, "");
10516 ajStrAppendCountK(Pstr, ' ', margin);
10517
10518 for(cp = newstr->Ptr; *cp; cp++)
10519 {
10520 switch(*cp)
10521 {
10522 case '\n':
10523 ajStrAppendK(Pstr, '\n');
10524
10525 for(j=0; j<leftmargin; j++)
10526 ajStrAppendK(Pstr, ' ');
10527 i = indent;
10528 isp = 0;
10529 leftmargin = margin + indent;
10530 break;
10531 case ' ':
10532 case '\t':
10533 isp = (*Pstr)->Len;
10534 /* ajDebug("can split at %d\n", isp); */
10535 default:
10536 if(++i >= maxwidth)
10537 { /* too wide, time to split */
10538 /* ajDebug("split at i: %d isp: %d\n'%S'\n",
10539 i, isp, *Pstr); */
10540 if(isp)
10541 {
10542 if(isp == (*Pstr)->Len)
10543 ajStrAppendK(Pstr, '\n');
10544 else
10545 (*Pstr)->Ptr[isp] = '\n';
10546 leftmargin = margin + indent;
10547 }
10548 else
10549 {
10550 ajStrAppendK(Pstr, *cp); /* keep going */
10551 break;
10552 }
10553
10554 for(j=0; j<leftmargin; j++)
10555 { /* follow newline with left margin spaces */
10556 isp++;
10557 ajStrInsertK(Pstr, isp, ' ');
10558 }
10559
10560 i = (*Pstr)->Len - isp + indent;
10561 isp = 0;
10562
10563 if(!isspace((ajint)*cp))
10564 ajStrAppendK(Pstr, *cp);
10565 }
10566 else
10567 ajStrAppendK(Pstr, *cp);
10568
10569 break;
10570 }
10571 }
10572
10573 ajStrDel(&newstr);
10574
10575 return ajTrue;
10576 }
10577
10578
10579
10580
10581 /* @section comparison ********************************************************
10582 **
10583 ** Functions for comparing strings
10584 **
10585 ** @fdata [AjPStr]
10586 **
10587 ** @nam3rule Match Compare two complete strings.
10588 ** @nam4rule MatchCase Case-insensitive comparison.
10589 ** @nam4rule MatchWild Comparison using wildcard characters.
10590 ** @nam5rule MatchWildCase Case-insensitive comparison
10591 ** using wildcard characters.
10592 ** @nam5rule MatchWildWord Case-sensitive wildcard comparison of
10593 ** first words within two strings.
10594 ** @nam6rule MatchWildWordCase Case-insensitive wildcard comparison of
10595 ** first words within two strings.
10596 ** @nam4rule MatchWord Comparison using whole words.
10597 ** @nam5rule MatchWordOne Comparison using whole words matching any one.
10598 ** @nam5rule MatchWordAll Comparison using whole words matching every one.
10599
10600 ** @nam3rule Prefix Compare start of string to given prefix.
10601 ** @nam4rule PrefixCase Case-insensitive comparison.
10602 ** @nam3rule Suffix Compare end of string to given suffix.
10603 ** @nam4rule SuffixCase Case-insensitive comparison.
10604 **
10605 ** @argrule * str [const AjPStr] String
10606 ** @argrule C txt2 [const char*] String
10607 ** @argrule S str2 [const AjPStr] String
10608 **
10609 ** @valrule * [AjBool] True on success
10610 **
10611 ** @fcategory use
10612 */
10613
10614
10615
10616
10617 /* @func ajStrMatchC **********************************************************
10618 **
10619 ** Simple test for matching a string and a text string.
10620 **
10621 ** @param [r] str [const AjPStr] String
10622 ** @param [r] txt2 [const char*] Text
10623 ** @return [AjBool] ajTrue if two complete strings are the same
10624 **
10625 ** @release 1.0.0
10626 ** @@
10627 ******************************************************************************/
10628
ajStrMatchC(const AjPStr str,const char * txt2)10629 AjBool ajStrMatchC(const AjPStr str, const char* txt2)
10630 {
10631 if(!str || !txt2)
10632 return ajFalse;
10633
10634 if(!strcmp(str->Ptr, txt2))
10635 return ajTrue;
10636
10637 return ajFalse;
10638 }
10639
10640
10641
10642
10643 /* @func ajStrMatchS **********************************************************
10644 **
10645 ** Simple test for matching two strings.
10646 **
10647 ** @param [r] str [const AjPStr] String
10648 ** @param [r] str2 [const AjPStr] Second String
10649 ** @return [AjBool] ajTrue if two complete strings are the same
10650 **
10651 ** @release 4.0.0
10652 ** @@
10653 ******************************************************************************/
10654
ajStrMatchS(const AjPStr str,const AjPStr str2)10655 AjBool ajStrMatchS(const AjPStr str, const AjPStr str2)
10656 {
10657 if(!str || !str2)
10658 return ajFalse;
10659
10660 if(!strcmp(str->Ptr, str2->Ptr))
10661 return ajTrue;
10662
10663 return ajFalse;
10664 }
10665
10666
10667
10668
10669 /* @func ajStrMatchCaseC ******************************************************
10670 **
10671 ** Simple case-insensitive test for matching a string and a text string.
10672 **
10673 ** @param [r] str [const AjPStr] String
10674 ** @param [r] txt2 [const char*] Text
10675 ** @return [AjBool] ajTrue if two strings are exactly the same excluding case
10676 **
10677 ** @release 1.0.0
10678 ** @@
10679 ******************************************************************************/
10680
ajStrMatchCaseC(const AjPStr str,const char * txt2)10681 AjBool ajStrMatchCaseC(const AjPStr str, const char* txt2)
10682 {
10683 if(!str || !txt2)
10684 return ajFalse;
10685
10686 return ajCharMatchCaseC(str->Ptr, txt2);
10687 }
10688
10689
10690
10691
10692 /* @func ajStrMatchCaseS ******************************************************
10693 **
10694 ** Simple case-insensitive test for matching two strings.
10695 **
10696 ** @param [r] str [const AjPStr] String
10697 ** @param [r] str2 [const AjPStr] Second String
10698 ** @return [AjBool] ajTrue if two strings are exactly the same excluding case
10699 **
10700 ** @release 4.0.0
10701 ** @@
10702 ******************************************************************************/
10703
ajStrMatchCaseS(const AjPStr str,const AjPStr str2)10704 AjBool ajStrMatchCaseS(const AjPStr str, const AjPStr str2)
10705 {
10706 if(!str || !str2)
10707 return ajFalse;
10708
10709 return ajCharMatchCaseC(str->Ptr, str2->Ptr);
10710 }
10711
10712
10713
10714
10715 /* @func ajStrMatchWildC ******************************************************
10716 **
10717 ** Simple case-sensitive test for matching a string and a text string using
10718 ** wildcard characters.
10719 **
10720 ** @param [r] str [const AjPStr] String
10721 ** @param [r] txt2 [const char*] Wildcard text
10722 ** @return [AjBool] ajTrue if the strings match
10723 **
10724 ** @release 1.0.0
10725 ** @@
10726 ******************************************************************************/
10727
ajStrMatchWildC(const AjPStr str,const char * txt2)10728 AjBool ajStrMatchWildC(const AjPStr str, const char* txt2)
10729 {
10730 return ajCharMatchWildC(MAJSTRGETPTR(str), txt2);
10731 }
10732
10733
10734
10735
10736 /* @func ajStrMatchWildS ******************************************************
10737 **
10738 ** Simple case-sensitive test for matching two strings using wildcard
10739 ** characters.
10740 **
10741 ** @param [r] str [const AjPStr] String
10742 ** @param [r] str2 [const AjPStr] Wildcard string
10743 ** @return [AjBool] ajTrue if two strings match
10744 **
10745 ** @release 4.0.0
10746 ** @@
10747 ******************************************************************************/
10748
ajStrMatchWildS(const AjPStr str,const AjPStr str2)10749 AjBool ajStrMatchWildS(const AjPStr str, const AjPStr str2)
10750 {
10751 return ajCharMatchWildC(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
10752 }
10753
10754
10755
10756
10757 /* @func ajStrMatchWildCaseC **************************************************
10758 **
10759 ** Simple case-insensitive test for matching a string and a text string using
10760 ** wildcard characters.
10761 **
10762 ** @param [r] str [const AjPStr] String
10763 ** @param [r] txt2 [const char*] Wildcard text
10764 ** @return [AjBool] ajTrue if the strings match
10765 **
10766 ** @release 4.1.0
10767 ** @@
10768 ******************************************************************************/
10769
ajStrMatchWildCaseC(const AjPStr str,const char * txt2)10770 AjBool ajStrMatchWildCaseC(const AjPStr str, const char* txt2)
10771 {
10772 return ajCharMatchWildCaseC(MAJSTRGETPTR(str), txt2);
10773 }
10774
10775
10776
10777
10778 /* @func ajStrMatchWildCaseS **************************************************
10779 **
10780 ** Simple case-insensitive test for matching two strings using wildcard
10781 ** characters.
10782 **
10783 ** @param [r] str [const AjPStr] String
10784 ** @param [r] str2 [const AjPStr] Wildcard string
10785 ** @return [AjBool] ajTrue if two strings match
10786 **
10787 ** @release 4.1.0
10788 ** @@
10789 ******************************************************************************/
10790
ajStrMatchWildCaseS(const AjPStr str,const AjPStr str2)10791 AjBool ajStrMatchWildCaseS(const AjPStr str, const AjPStr str2)
10792 {
10793 return ajCharMatchWildCaseC(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
10794 }
10795
10796
10797
10798
10799 /* @func ajStrMatchWildWordC **************************************************
10800 **
10801 ** Case-sensitive test for matching a text string "word" against a string
10802 ** using wildcard characters.
10803 **
10804 ** 'Word' is defined as starting and ending with an alphanumeric character
10805 ** (A-Z a-z 0-9) with no white space.
10806 **
10807 ** The query text can use '*' or '?' as a wildcard.
10808 **
10809 ** @param [r] str [const AjPStr] String
10810 ** @param [r] txt2 [const char*] Text
10811 ** @return [AjBool] ajTrue if found
10812 **
10813 ** @release 4.0.0
10814 ** @@
10815 ******************************************************************************/
10816
ajStrMatchWildWordC(const AjPStr str,const char * txt2)10817 AjBool ajStrMatchWildWordC(const AjPStr str, const char* txt2)
10818 {
10819 return ajCharMatchWildWordC(MAJSTRGETPTR(str), txt2);
10820 }
10821
10822
10823
10824
10825 /* @func ajStrMatchWildWordS **************************************************
10826 **
10827 ** Case-sensitive test for matching a string "word" against a string
10828 ** using wildcard characters.
10829 **
10830 ** 'Word' is defined as starting and ending with an alphanumeric character
10831 ** (A-Z a-z 0-9) with no white space.
10832 **
10833 ** The query text can use '*' or '?' as a wildcard.
10834 **
10835 ** @param [r] str [const AjPStr] String
10836 ** @param [r] str2 [const AjPStr] Text
10837 ** @return [AjBool] ajTrue if found
10838 **
10839 ** @release 4.0.0
10840 ** @@
10841 ******************************************************************************/
10842
ajStrMatchWildWordS(const AjPStr str,const AjPStr str2)10843 AjBool ajStrMatchWildWordS(const AjPStr str, const AjPStr str2)
10844 {
10845 return ajCharMatchWildWordC(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
10846 }
10847
10848
10849
10850
10851 /* @func ajStrMatchWildWordCaseC **********************************************
10852 **
10853 ** Case-insensitive test for matching a text string "word" against a string
10854 ** using wildcard characters.
10855 **
10856 ** 'Word' is defined as starting and ending with an alphanumeric character
10857 ** (A-Z a-z 0-9) with no white space.
10858 **
10859 ** The query text can use '*' or '?' as a wildcard.
10860 **
10861 ** @param [r] str [const AjPStr] String
10862 ** @param [r] txt2 [const char*] Text
10863 ** @return [AjBool] ajTrue if found
10864 **
10865 ** @release 4.1.0
10866 ** @@
10867 ******************************************************************************/
10868
ajStrMatchWildWordCaseC(const AjPStr str,const char * txt2)10869 AjBool ajStrMatchWildWordCaseC(const AjPStr str, const char* txt2)
10870 {
10871 return ajCharMatchWildWordCaseC(MAJSTRGETPTR(str), txt2);
10872 }
10873
10874
10875
10876
10877 /* @func ajStrMatchWildWordCaseS **********************************************
10878 **
10879 ** Case-insensitive test for matching a string "word" against a string
10880 ** using wildcard characters.
10881 **
10882 ** 'Word' is defined as starting and ending with an alphanumeric character
10883 ** (A-Z a-z 0-9) with no white space.
10884 **
10885 ** The query text can use '*' or '?' as a wildcard.
10886 **
10887 ** @param [r] str [const AjPStr] String
10888 ** @param [r] str2 [const AjPStr] Text
10889 ** @return [AjBool] ajTrue if found
10890 **
10891 ** @release 4.1.0
10892 ** @@
10893 ******************************************************************************/
10894
ajStrMatchWildWordCaseS(const AjPStr str,const AjPStr str2)10895 AjBool ajStrMatchWildWordCaseS(const AjPStr str, const AjPStr str2)
10896 {
10897 return ajCharMatchWildWordCaseC(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
10898 }
10899
10900
10901
10902
10903 /* @func ajStrMatchWordAllS ***************************************************
10904 **
10905 ** Test for matching all words within a string.
10906 ** Matches can be to parts of words in the original string.
10907 **
10908 ** 'Word' is defined as no white space.
10909 **
10910 ** @param [r] str [const AjPStr] String
10911 ** @param [r] str2 [const AjPStr] Text
10912 ** @return [AjBool] ajTrue if found
10913 **
10914 ** @release 4.0.0
10915 ** @@
10916 ******************************************************************************/
10917
ajStrMatchWordAllS(const AjPStr str,const AjPStr str2)10918 AjBool ajStrMatchWordAllS(const AjPStr str, const AjPStr str2)
10919 {
10920 AjBool ret = ajTrue;
10921 const AjPStr teststr = NULL;
10922
10923 teststr = ajStrParseWhite(str2);
10924
10925 if(!teststr)
10926 return ajFalse;
10927
10928 while (teststr)
10929 {
10930 if(ajStrFindS(str, teststr) == -1)
10931 ret = ajFalse;
10932
10933 teststr = ajStrParseWhite(NULL);
10934 }
10935
10936 return ret;
10937 }
10938
10939
10940
10941
10942 /* @func ajStrMatchWordOneS ***************************************************
10943 **
10944 ** Test for matching a word within a string.
10945 ** Matches can be to parts of words in the original string.
10946 **
10947 ** 'Word' is defined as no white space.
10948 **
10949 ** @param [r] str [const AjPStr] String
10950 ** @param [r] str2 [const AjPStr] Text
10951 ** @return [AjBool] ajTrue if found
10952 **
10953 ** @release 4.0.0
10954 ** @@
10955 ******************************************************************************/
10956
ajStrMatchWordOneS(const AjPStr str,const AjPStr str2)10957 AjBool ajStrMatchWordOneS(const AjPStr str, const AjPStr str2)
10958 {
10959 AjBool ret = ajFalse;
10960 const AjPStr teststr = NULL;
10961
10962 teststr = ajStrParseWhite(str2);
10963
10964 if(!teststr)
10965 return ajFalse;
10966
10967 while (teststr)
10968 {
10969 if(ajStrFindS(str, teststr) != -1)
10970 ret = ajTrue;
10971
10972 teststr = ajStrParseWhite(NULL);
10973 }
10974
10975 return ret;
10976 }
10977
10978
10979
10980
10981 /* @func ajStrPrefixC *********************************************************
10982 **
10983 ** Test for matching the start of a string against a given prefix text string.
10984 **
10985 ** @param [r] str [const AjPStr] String
10986 ** @param [r] txt2 [const char*] Prefix as text
10987 ** @return [AjBool] ajTrue if the string begins with the prefix
10988 **
10989 ** @release 1.0.0
10990 ** @@
10991 ******************************************************************************/
10992
ajStrPrefixC(const AjPStr str,const char * txt2)10993 AjBool ajStrPrefixC(const AjPStr str, const char* txt2)
10994 {
10995 size_t ilen;
10996
10997 if(!str)
10998 return ajFalse;
10999
11000 ilen = strlen(txt2);
11001
11002 if(!ilen) /* no prefix */
11003 return ajFalse;
11004
11005 if(ilen > MAJSTRGETLEN(str)) /* prefix longer */
11006 return ajFalse;
11007
11008 if(strncmp(MAJSTRGETPTR(str), txt2, ilen)) /* +1 or -1 for a failed match */
11009 return ajFalse;
11010
11011 return ajTrue;
11012 }
11013
11014
11015
11016
11017 /* @func ajStrPrefixS *********************************************************
11018 **
11019 ** Test for matching the start of a string against a given prefix string.
11020 **
11021 ** @param [r] str [const AjPStr] String
11022 ** @param [r] str2 [const AjPStr] Prefix
11023 ** @return [AjBool] ajTrue if the string begins with the prefix
11024 **
11025 ** @release 4.0.0
11026 ** @@
11027 ******************************************************************************/
11028
ajStrPrefixS(const AjPStr str,const AjPStr str2)11029 AjBool ajStrPrefixS(const AjPStr str, const AjPStr str2)
11030 {
11031 if(!str)
11032 return ajFalse;
11033
11034 if(!str2)
11035 return ajFalse;
11036
11037 if(!str2->Len) /* no prefix */
11038 return ajFalse;
11039
11040 if(str2->Len > MAJSTRGETLEN(str)) /* prefix longer */
11041 return ajFalse;
11042
11043 if(strncmp(MAJSTRGETPTR(str),
11044 MAJSTRGETPTR(str2), MAJSTRGETLEN(str2))) /* +1 or -1 for a
11045 failed match */
11046 return ajFalse;
11047
11048 return ajTrue;
11049 }
11050
11051
11052
11053
11054 /* @func ajStrPrefixCaseC *****************************************************
11055 **
11056 ** Case-insensitive test for matching the start of a string against a
11057 ** given prefix text string.
11058 **
11059 ** @param [r] str [const AjPStr] String
11060 ** @param [r] txt2 [const char*] Prefix
11061 ** @return [AjBool] ajTrue if the string begins with the prefix
11062 **
11063 ** @release 1.0.0
11064 ** @@
11065 ******************************************************************************/
11066
ajStrPrefixCaseC(const AjPStr str,const char * txt2)11067 AjBool ajStrPrefixCaseC(const AjPStr str, const char* txt2)
11068 {
11069 return ajCharPrefixCaseC(MAJSTRGETPTR(str), txt2);
11070 }
11071
11072
11073
11074
11075 /* @func ajStrPrefixCaseS *****************************************************
11076 **
11077 ** Case-insensitive test for matching the start of a string against a
11078 ** given prefix string.
11079 **
11080 ** @param [r] str [const AjPStr] String
11081 ** @param [r] str2 [const AjPStr] Prefix
11082 ** @return [AjBool] ajTrue if the string begins with the prefix
11083 **
11084 ** @release 4.0.0
11085 ** @@
11086 ******************************************************************************/
11087
ajStrPrefixCaseS(const AjPStr str,const AjPStr str2)11088 AjBool ajStrPrefixCaseS(const AjPStr str, const AjPStr str2)
11089 {
11090 return ajCharPrefixCaseC(MAJSTRGETPTR(str),
11091 MAJSTRGETPTR(str2));
11092 }
11093
11094
11095
11096
11097 /* @func ajStrSuffixC *********************************************************
11098 **
11099 ** Test for matching the end of a string against a given suffix text string.
11100 **
11101 ** @param [r] str [const AjPStr] String
11102 ** @param [r] txt2 [const char*] Suffix as text
11103 ** @return [AjBool] ajTrue if the string ends with the suffix
11104 **
11105 ** @release 1.0.0
11106 ** @@
11107 ******************************************************************************/
11108
ajStrSuffixC(const AjPStr str,const char * txt2)11109 AjBool ajStrSuffixC(const AjPStr str, const char* txt2)
11110 {
11111 size_t ilen;
11112 size_t istart;
11113
11114 if(!str)
11115 return ajFalse;
11116
11117 ilen = strlen(txt2);
11118 istart = str->Len - ilen;
11119
11120 if(ilen > MAJSTRGETLEN(str)) /* suffix longer */
11121 return ajFalse;
11122
11123 if(strncmp(&str->Ptr[istart], txt2, ilen)) /* +1 or -1 for a
11124 failed match */
11125 return ajFalse;
11126
11127 return ajTrue;
11128 }
11129
11130
11131
11132
11133 /* @func ajStrSuffixS *********************************************************
11134 **
11135 ** Test for matching the end of a string against a given suffix string.
11136 **
11137 ** @param [r] str [const AjPStr] String
11138 ** @param [r] str2 [const AjPStr] Suffix
11139 ** @return [AjBool] ajTrue if the string ends with the suffix
11140 **
11141 ** @release 4.0.0
11142 ** @@
11143 ******************************************************************************/
11144
ajStrSuffixS(const AjPStr str,const AjPStr str2)11145 AjBool ajStrSuffixS(const AjPStr str, const AjPStr str2)
11146 {
11147 size_t ilen;
11148 size_t istart;
11149
11150 if(!str)
11151 return ajFalse;
11152
11153 ilen = MAJSTRGETLEN(str2);
11154 istart = str->Len - ilen;
11155
11156 if(ilen > MAJSTRGETLEN(str)) /* suffix longer */
11157 return ajFalse;
11158
11159 if(strncmp(&str->Ptr[istart], str2->Ptr, ilen)) /* +1 or -1 for a
11160 failed match */
11161 return ajFalse;
11162
11163 return ajTrue;
11164 }
11165
11166
11167
11168
11169 /* @func ajStrSuffixCaseC *****************************************************
11170 **
11171 ** Case-insensitive test for matching the end of a string against a
11172 ** given suffix text string.
11173 **
11174 ** @param [r] str [const AjPStr] String
11175 ** @param [r] txt2 [const char*] Prefix
11176 ** @return [AjBool] ajTrue if the string ends with the suffix
11177 **
11178 ** @release 4.0.0
11179 ** @@
11180 ******************************************************************************/
11181
ajStrSuffixCaseC(const AjPStr str,const char * txt2)11182 AjBool ajStrSuffixCaseC(const AjPStr str, const char* txt2)
11183 {
11184 return ajCharSuffixCaseC(MAJSTRGETPTR(str), txt2);
11185 }
11186
11187
11188
11189
11190 /* @func ajStrSuffixCaseS *****************************************************
11191 **
11192 ** Case-insensitive test for matching the end of a string against a
11193 ** given suffix string.
11194 **
11195 ** @param [r] str [const AjPStr] String
11196 ** @param [r] str2 [const AjPStr] Prefix
11197 ** @return [AjBool] ajTrue if the string ends with the suffix
11198 **
11199 ** @release 4.0.0
11200 ** @@
11201 ******************************************************************************/
11202
ajStrSuffixCaseS(const AjPStr str,const AjPStr str2)11203 AjBool ajStrSuffixCaseS(const AjPStr str, const AjPStr str2)
11204 {
11205 return ajCharSuffixCaseC(MAJSTRGETPTR(str),
11206 MAJSTRGETPTR(str2));
11207 }
11208
11209
11210
11211
11212 /* @section comparison (sorting) **********************************************
11213 **
11214 ** Functions for sorting strings.
11215 **
11216 ** @fdata [AjPStr]
11217 ** @fnote namrule same as "String comparison (sorting) functions (C-type
11218 ** char* strings)".
11219 ** @nam3rule Cmp Compare two complete strings & return sort order.
11220 ** @nam4rule CmpCase Case-insensitive comparison.
11221 ** @nam4rule CmpWild Comparison using wildcard characters.
11222 ** @nam5rule CmpWildCase Case-insensitive comparison
11223 ** using wildcard characters.
11224 ** @nam3rule Vcmp Compare string using void arguments.
11225 **
11226 ** @argrule Cmp str [const AjPStr] String to compare
11227 ** @argrule C txt2 [const char*] String to compare
11228 ** @argrule S str2 [const AjPStr] String to compare
11229 ** @argrule Len len [size_t] Number of characters to compare
11230 ** @argrule Vcmp str [const void*] String
11231 ** @argrule Vcmp str2 [const void*] String to compare
11232 **
11233 ** @valrule * [int] -1 if first string should sort before second, +1 if the
11234 ** second string should sort first. 0 if they are identical
11235 ** in length and content.
11236 **
11237 ** @fcategory use
11238 */
11239
11240
11241
11242
11243 /* @macro MAJSTRCMPC **********************************************************
11244 **
11245 ** Finds the sort order of a string and a text string.
11246 **
11247 ** A macro version of {ajStrCmpC} in case it is needed for speed
11248 **
11249 ** @param [r] str [const AjPStr] String object
11250 ** @param [r] txt2 [const char*] Text string
11251 ** @return [int] -1 if first string should sort before second, +1 if the
11252 ** second string should sort first. 0 if they are identical
11253 ** in length and content.
11254 ** @@
11255 ******************************************************************************/
11256
11257
11258
11259
11260 /* @func ajStrCmpC ************************************************************
11261 **
11262 ** Finds the sort order of a string and a text string.
11263 **
11264 ** @param [r] str [const AjPStr] String object
11265 ** @param [r] txt2 [const char*] Text string
11266 ** @return [int] -1 if first string should sort before second, +1 if the
11267 ** second string should sort first. 0 if they are identical
11268 ** in length and content.
11269 **
11270 ** @release 1.0.0
11271 ** @@
11272 ******************************************************************************/
11273
ajStrCmpC(const AjPStr str,const char * txt2)11274 int ajStrCmpC(const AjPStr str, const char* txt2)
11275 {
11276 return strcmp(MAJSTRGETPTR(str), txt2);
11277 }
11278
11279
11280
11281
11282 /* @func ajStrCmpLenC *********************************************************
11283 **
11284 ** Finds the sort order of a string and a text string comparing the first
11285 ** n characters only.
11286 **
11287 ** @param [r] str [const AjPStr] String object
11288 ** @param [r] txt2 [const char*] Text string
11289 ** @param [r] len [size_t] Length to compare
11290 ** @return [int] -1 if first string should sort before second, +1 if the
11291 ** second string should sort first. 0 if they are identical
11292 ** in length and content.
11293 **
11294 ** @release 4.0.0
11295 ** @@
11296 ******************************************************************************/
11297
ajStrCmpLenC(const AjPStr str,const char * txt2,size_t len)11298 int ajStrCmpLenC(const AjPStr str, const char* txt2, size_t len)
11299 {
11300 return strncmp(MAJSTRGETPTR(str), txt2, len);
11301 }
11302
11303
11304
11305
11306 /* @macro MAJSTRCMPS **********************************************************
11307 **
11308 ** Finds the sort order of two strings.
11309 **
11310 ** A macro version of {ajStrCmpS} in case it is needed for speed
11311 **
11312 ** @param [r] str [const AjPStr] First string
11313 ** @param [r] str2 [const AjPStr] Second string
11314 ** @return [int] -1 if first string should sort before second, +1 if the
11315 ** second string should sort first. 0 if they are identical
11316 ** in length and content.
11317 ** @@
11318 ******************************************************************************/
11319
11320
11321
11322
11323 /* @func ajStrCmpS ************************************************************
11324 **
11325 ** Finds the sort order of two strings.
11326 **
11327 ** @param [r] str [const AjPStr] First string
11328 ** @param [r] str2 [const AjPStr] Second string
11329 ** @return [int] -1 if first string should sort before second, +1 if the
11330 ** second string should sort first. 0 if they are identical
11331 ** in length and content.
11332 **
11333 ** @release 4.0.0
11334 ** @@
11335 ******************************************************************************/
11336
ajStrCmpS(const AjPStr str,const AjPStr str2)11337 int ajStrCmpS(const AjPStr str, const AjPStr str2)
11338 {
11339 return strcmp(MAJSTRGETPTR(str),
11340 MAJSTRGETPTR(str2));
11341 }
11342
11343
11344
11345
11346 /* @func ajStrCmpCaseS ********************************************************
11347 **
11348 ** Finds the sort order of two strings using a case-insensitive comparison.
11349 **
11350 ** @param [r] str [const AjPStr] text string
11351 ** @param [r] str2 [const AjPStr] Text string
11352 ** @return [int] -1 if first string should sort before second, +1 if the
11353 ** second string should sort first. 0 if they are identical
11354 ** in length and content.
11355 **
11356 ** @release 4.0.0
11357 ** @@
11358 ******************************************************************************/
11359
ajStrCmpCaseS(const AjPStr str,const AjPStr str2)11360 int ajStrCmpCaseS(const AjPStr str, const AjPStr str2)
11361 {
11362 const char* cp;
11363 const char* cq;
11364
11365 if(!str)
11366 {
11367 if(!str2) return 0;
11368 else return -1;
11369 }
11370 if(!str2) return 1;
11371
11372 for(cp = MAJSTRGETPTR(str), cq = MAJSTRGETPTR(str2);
11373 *cp && *cq; cp++, cq++)
11374 if(toupper((int) *cp) != toupper((int) *cq))
11375 {
11376 if(toupper((int) *cp) > toupper((int) *cq))
11377 return 1;
11378 else
11379 return -1;
11380 }
11381
11382 if(*cp)
11383 return 1;
11384
11385 if(*cq)
11386 return -1;
11387
11388 return 0;
11389 }
11390
11391
11392
11393
11394 /* @func ajStrCmpLenS *********************************************************
11395 **
11396 ** Finds the sort order of two strings comparing the first
11397 ** n characters only.
11398
11399 ** Compares the first n characters of two strings
11400 **
11401 ** @param [r] str [const AjPStr] String object
11402 ** @param [r] str2 [const AjPStr] Second string object
11403 ** @param [r] len [size_t] Length to compare
11404 ** @return [int] -1 if first string should sort before second, +1 if the
11405 ** second string should sort first. 0 if they are identical
11406 ** in length and content.
11407 **
11408 ** @release 4.0.0
11409 ** @@
11410 ******************************************************************************/
11411
ajStrCmpLenS(const AjPStr str,const AjPStr str2,size_t len)11412 int ajStrCmpLenS(const AjPStr str, const AjPStr str2, size_t len)
11413 {
11414 if(!str)
11415 {
11416 if(!str2) return 0;
11417 else return -1;
11418 }
11419 if(!str2) return 1;
11420
11421 return strncmp(MAJSTRGETPTR(str), MAJSTRGETPTR(str2), len);
11422 }
11423
11424
11425
11426
11427 /* @func ajStrCmpWildC ********************************************************
11428 **
11429 ** Finds the sort-order (case insensitive) of string and a text string using
11430 ** wildcard characters.
11431 **
11432 ** @param [r] str [const AjPStr] String
11433 ** @param [r] txt2 [const char*] Wildcard text
11434 ** @return [int] -1 if first string should sort before second, +1 if the
11435 ** second string should sort first. 0 if they are identical
11436 ** in length and content.
11437 **
11438 ** @release 1.0.0
11439 ** @@
11440 ******************************************************************************/
11441
ajStrCmpWildC(const AjPStr str,const char * txt2)11442 int ajStrCmpWildC(const AjPStr str, const char* txt2)
11443 {
11444 if(!str)
11445 {
11446 if(!txt2) return 0;
11447 else return -1;
11448 }
11449 if(!txt2) return 1;
11450
11451 return ajCharCmpWild(MAJSTRGETPTR(str), txt2);
11452 }
11453
11454
11455
11456
11457 /* @func ajStrCmpWildS ********************************************************
11458 **
11459 ** Finds the sort-order (case insensitive) of two strings using wildcard
11460 ** characters.
11461 **
11462 ** @param [r] str [const AjPStr] String
11463 ** @param [r] str2 [const AjPStr] Wildcard string
11464 ** @return [int] -1 if first string should sort before second, +1 if the
11465 ** second string should sort first. 0 if they are identical
11466 ** in length and content.
11467 **
11468 ** @release 4.0.0
11469 ** @@
11470 ******************************************************************************/
11471
ajStrCmpWildS(const AjPStr str,const AjPStr str2)11472 int ajStrCmpWildS(const AjPStr str, const AjPStr str2)
11473 {
11474 if(!str)
11475 {
11476 if(!str2) return 0;
11477 else return -1;
11478 }
11479 if(!str2) return 1;
11480
11481 return ajCharCmpWild(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
11482 }
11483
11484
11485
11486
11487 /* @func ajStrCmpWildCaseC ****************************************************
11488 **
11489 ** Finds the sort-order (case sensitive) of string and a text string using
11490 ** wildcard characters.
11491 **
11492 ** @param [r] str [const AjPStr] String
11493 ** @param [r] txt2 [const char*] Wildcard text
11494 ** @return [int] -1 if first string should sort before second, +1 if the
11495 ** second string should sort first. 0 if they are identical
11496 ** in length and content.
11497 **
11498 ** @release 4.1.0
11499 ** @@
11500 ******************************************************************************/
11501
ajStrCmpWildCaseC(const AjPStr str,const char * txt2)11502 int ajStrCmpWildCaseC(const AjPStr str, const char* txt2)
11503 {
11504 if(!str)
11505 {
11506 if(!txt2) return 0;
11507 else return -1;
11508 }
11509 if(!txt2) return 1;
11510
11511 return ajCharCmpWildCase(MAJSTRGETPTR(str), txt2);
11512 }
11513
11514
11515
11516
11517 /* @func ajStrCmpWildCaseS ****************************************************
11518 **
11519 ** Finds the sort-order (case sensitive) of two strings using wildcard
11520 ** characters.
11521 **
11522 ** @param [r] str [const AjPStr] String
11523 ** @param [r] str2 [const AjPStr] Wildcard string
11524 ** @return [int] -1 if first string should sort before second, +1 if the
11525 ** second string should sort first. 0 if they are identical
11526 ** in length and content.
11527 **
11528 ** @release 4.1.0
11529 ** @@
11530 ******************************************************************************/
11531
ajStrCmpWildCaseS(const AjPStr str,const AjPStr str2)11532 int ajStrCmpWildCaseS(const AjPStr str, const AjPStr str2)
11533 {
11534 if(!str)
11535 {
11536 if(!str2) return 0;
11537 else return -1;
11538 }
11539 if(!str2) return 1;
11540
11541 return ajCharCmpWildCase(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
11542 }
11543
11544
11545
11546
11547 /* @func ajStrVcmp ************************************************************
11548 **
11549 ** Finds the sort order of two strings cast as void.
11550 **
11551 ** For use with {ajListSort}, {ajListUnique} and other functions which
11552 ** require a general function with void arguments.
11553 **
11554 ** @param [r] str [const void*] First string
11555 ** @param [r] str2 [const void*] Second string
11556 ** @return [int] -1 if first string should sort before second, +1 if the
11557 ** second string should sort first. 0 if they are identical
11558 ** in length and content.
11559 **
11560 ** @release 4.0.0
11561 ** @@
11562 ******************************************************************************/
11563
ajStrVcmp(const void * str,const void * str2)11564 int ajStrVcmp(const void* str, const void* str2)
11565 {
11566 if(!str)
11567 {
11568 if(!str2) return 0;
11569 else return -1;
11570 }
11571 if(!str2) return 1;
11572
11573 return strcmp((*(AjPStr const *)str)->Ptr, (*(AjPStr const *)str2)->Ptr);
11574 }
11575
11576
11577
11578
11579 /* @section comparison (search) functions *************************************
11580 **
11581 ** Functions for finding substrings or characters in strings.
11582 **
11583 ** @fdata [AjPStr]
11584 ** @fnote None.
11585 **
11586 ** @nam3rule Find Locate first occurrence of a string
11587 ** within another string.
11588 ** @nam4rule FindAny Any in a set of characters from the start
11589 ** @nam4rule FindCase Case insensitive
11590 ** @nam4rule FindNext Next in a set of characters from a given position
11591 ** @nam4rule FindRest Any not in a set of characters
11592 ** @nam5rule FindRestCase Any not in a set of characters, case insensitive
11593 ** @nam3rule Findlast Locate last occurrence of a string
11594 **
11595 ** @argrule * str [const AjPStr] String
11596 ** @argrule FindNext pos1 [ajlong] String position to search from
11597 ** @argrule C txt2 [const char*] Text to find
11598 ** @argrule K chr [char] Character
11599 ** @argrule S str2 [const AjPStr] Text to find
11600 **
11601 ** @valrule * [ajlong] Position of the start of text in string if found.
11602 ** Or -1 for text not found.
11603 **
11604 ** @fcategory use
11605 */
11606
11607
11608
11609
11610 /* @func ajStrFindC ***********************************************************
11611 **
11612 ** Finds the first occurrence in a string of a second (text) string.
11613 **
11614 ** @param [r] str [const AjPStr] String
11615 ** @param [r] txt2 [const char*] text to find
11616 ** @return [ajlong] Position of the start of text in string if found.
11617 ** Or -1 for text not found.
11618 **
11619 ** @release 1.0.0
11620 ** @@
11621 ******************************************************************************/
11622
ajStrFindC(const AjPStr str,const char * txt2)11623 ajlong ajStrFindC(const AjPStr str, const char* txt2)
11624 {
11625 const char* cp;
11626
11627 cp = strstr(MAJSTRGETPTR(str), txt2);
11628
11629 if(!cp)
11630 return -1;
11631
11632 return(cp - str->Ptr);
11633 }
11634
11635
11636
11637
11638 /* @func ajStrFindK ***********************************************************
11639 **
11640 ** Finds the first occurrence in a string of a single character.
11641 **
11642 ** @param [r] str [const AjPStr] String
11643 ** @param [r] chr [char] Character to find
11644 ** @return [ajlong] Position of the start of text in string if found.
11645 ** Or -1 for text not found.
11646 **
11647 ** @release 1.0.0
11648 ** @@
11649 ******************************************************************************/
11650
ajStrFindK(const AjPStr str,char chr)11651 ajlong ajStrFindK(const AjPStr str, char chr)
11652 {
11653 const char* cp;
11654
11655 cp = strchr(MAJSTRGETPTR(str), chr);
11656
11657 if(!cp)
11658 return -1;
11659
11660 return(cp - str->Ptr);
11661 }
11662
11663
11664
11665
11666 /* @func ajStrFindS ***********************************************************
11667 **
11668 ** Finds the first occurrence in a string of a second string.
11669 **
11670 ** @param [r] str [const AjPStr] String
11671 ** @param [r] str2 [const AjPStr] text to find
11672 ** @return [ajlong] Position of the start of text in string if found.
11673 ** Or -1 for text not found.
11674 **
11675 ** @release 4.0.0
11676 ** @@
11677 ******************************************************************************/
11678
ajStrFindS(const AjPStr str,const AjPStr str2)11679 ajlong ajStrFindS(const AjPStr str, const AjPStr str2)
11680 {
11681 const char* cp;
11682
11683 cp = strstr(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
11684
11685 if(!cp)
11686 return -1;
11687
11688 return (cp - str->Ptr);
11689 }
11690
11691
11692
11693
11694 /* @func ajStrFindAnyC ********************************************************
11695 **
11696 ** Finds the first occurrence in a string of any character in a second
11697 ** (text) string.
11698 **
11699 ** @param [r] str [const AjPStr] String
11700 ** @param [r] txt2 [const char*] text to find
11701 ** @return [ajlong] Position of the start of text in string if found.
11702 ** Or -1 for text not found.
11703 **
11704 ** @release 3.0.0
11705 ** @@
11706 ******************************************************************************/
11707
ajStrFindAnyC(const AjPStr str,const char * txt2)11708 ajlong ajStrFindAnyC(const AjPStr str, const char* txt2)
11709 {
11710 size_t i;
11711
11712 i = strcspn(MAJSTRGETPTR(str), txt2);
11713
11714 if(i == str->Len)
11715 return -1;
11716
11717 return i;
11718 }
11719
11720
11721
11722
11723 /* @func ajStrFindAnyK ********************************************************
11724 **
11725 ** Finds the first occurrence in a string of a specified character.
11726 **
11727 ** @param [r] str [const AjPStr] String
11728 ** @param [r] chr [char] character to find
11729 ** @return [ajlong] Position of the start of text in string if found.
11730 ** Or -1 for text not found.
11731 **
11732 ** @release 4.0.0
11733 ** @@
11734 ******************************************************************************/
11735
ajStrFindAnyK(const AjPStr str,char chr)11736 ajlong ajStrFindAnyK(const AjPStr str, char chr)
11737 {
11738 const char* cp;
11739
11740 cp = strchr(MAJSTRGETPTR(str), (ajint) chr);
11741
11742 if(!cp)
11743 return -1;
11744
11745 return(cp - str->Ptr);
11746 }
11747
11748
11749
11750
11751 /* @func ajStrFindAnyS ********************************************************
11752 **
11753 ** Finds the first occurrence in a string of any character in a second
11754 ** string.
11755 **
11756 ** @param [r] str [const AjPStr] String
11757 ** @param [r] str2 [const AjPStr] text to find
11758 ** @return [ajlong] Position of the start of text in string if found.
11759 ** Or -1 for text not found.
11760 **
11761 ** @release 4.0.0
11762 ** @@
11763 ******************************************************************************/
11764
ajStrFindAnyS(const AjPStr str,const AjPStr str2)11765 ajlong ajStrFindAnyS(const AjPStr str, const AjPStr str2)
11766 {
11767 size_t i;
11768
11769 i = strcspn(MAJSTRGETPTR(str), MAJSTRGETPTR(str2));
11770
11771 if(i == str->Len)
11772 return -1;
11773
11774 return i;
11775 }
11776
11777
11778
11779
11780 /* @func ajStrFindCaseC *******************************************************
11781 **
11782 ** Finds the first occurrence in a string of a second (text) string using a
11783 ** case-insensitive search.
11784 **
11785 ** @param [r] str [const AjPStr] String
11786 ** @param [r] txt2 [const char*] text to find
11787 ** @return [ajlong] Position of the start of text in string if found.
11788 ** @error -1 Text not found.
11789 **
11790 ** @release 1.7.0
11791 ** @@
11792 ******************************************************************************/
11793
ajStrFindCaseC(const AjPStr str,const char * txt2)11794 ajlong ajStrFindCaseC(const AjPStr str, const char *txt2)
11795 {
11796 AjPStr t1;
11797 AjPStr t2;
11798 ajlong v;
11799
11800 t1 = ajStrNewC(MAJSTRGETPTR(str));
11801 t2 = ajStrNewC(txt2);
11802 ajStrFmtUpper(&t1);
11803 ajStrFmtUpper(&t2);
11804
11805 v = ajStrFindS(t1,t2);
11806 ajStrDel(&t1);
11807 ajStrDel(&t2);
11808
11809 return v;
11810 }
11811
11812
11813
11814
11815 /* @func ajStrFindCaseS *******************************************************
11816 **
11817 ** Finds the first occurrence in a string of a second string using a
11818 ** case-insensitive search.
11819 **
11820 ** @param [r] str [const AjPStr] String
11821 ** @param [r] str2 [const AjPStr] text to find
11822 ** @return [ajlong] Position of the start of text in string if found.
11823 ** -1 if not found.
11824 **
11825 ** @release 4.0.0
11826 ** @@
11827 ******************************************************************************/
11828
ajStrFindCaseS(const AjPStr str,const AjPStr str2)11829 ajlong ajStrFindCaseS(const AjPStr str, const AjPStr str2)
11830 {
11831 return ajStrFindCaseC(str,MAJSTRGETPTR(str2));
11832 }
11833
11834
11835
11836
11837 /* @func ajStrFindNextC *******************************************************
11838 **
11839 ** Finds the next occurrence in a string of a second
11840 ** (text) string.
11841 **
11842 ** @param [r] str [const AjPStr] String
11843 ** @param [r] pos1 [ajlong] Start position in string
11844 ** @param [r] txt2 [const char*] text to find
11845 ** @return [ajlong] Position of the start of text in string if found.
11846 ** Or -1 for text not found.
11847 **
11848 ** @release 6.0.0
11849 ** @@
11850 ******************************************************************************/
11851
ajStrFindNextC(const AjPStr str,ajlong pos1,const char * txt2)11852 ajlong ajStrFindNextC(const AjPStr str, ajlong pos1, const char* txt2)
11853 {
11854 size_t i;
11855 size_t jpos;
11856 char *cp;
11857
11858 jpos = ajCvtSposToPosStart(str->Len, 0, pos1);
11859 cp = strstr(&str->Ptr[jpos], txt2);
11860 if(!cp)
11861 return -1;
11862
11863 i = cp - str->Ptr;
11864
11865 return i;
11866 }
11867
11868
11869
11870
11871 /* @func ajStrFindNextK *******************************************************
11872 **
11873 ** Finds the next occurrence in a string of a specified character.
11874 **
11875 ** @param [r] str [const AjPStr] String
11876 ** @param [r] pos1 [ajlong] Start position in string
11877 ** @param [r] chr [char] character to find
11878 ** @return [ajlong] Position of the start of text in string if found.
11879 ** Or -1 for text not found.
11880 **
11881 ** @release 6.0.0
11882 ** @@
11883 ******************************************************************************/
11884
ajStrFindNextK(const AjPStr str,ajlong pos1,char chr)11885 ajlong ajStrFindNextK(const AjPStr str, ajlong pos1, char chr)
11886 {
11887 const char* cp;
11888 size_t jpos;
11889
11890 jpos = ajCvtSposToPosStart(str->Len, 0, pos1);
11891
11892 cp = strchr(&str->Ptr[jpos], (ajint) chr);
11893
11894 if(!cp)
11895 return -1;
11896
11897 return(cp - str->Ptr);
11898 }
11899
11900
11901
11902
11903 /* @func ajStrFindNextS *******************************************************
11904 **
11905 ** Finds the next occurrence in a string of any character in a second
11906 ** string.
11907 **
11908 ** @param [r] str [const AjPStr] String
11909 ** @param [r] pos1 [ajlong] Start position in string
11910 ** @param [r] str2 [const AjPStr] text to find
11911 ** @return [ajlong] Position of the start of text in string if found.
11912 ** Or -1 for text not found.
11913 **
11914 ** @release 6.0.0
11915 ** @@
11916 ******************************************************************************/
11917
ajStrFindNextS(const AjPStr str,ajlong pos1,const AjPStr str2)11918 ajlong ajStrFindNextS(const AjPStr str, ajlong pos1, const AjPStr str2)
11919 {
11920 size_t i;
11921 size_t jpos;
11922 char *cp;
11923
11924 jpos = ajCvtSposToPosStart(str->Len, 0, pos1);
11925
11926 cp = strstr(&str->Ptr[jpos], str2->Ptr);
11927
11928 if(!cp)
11929 return -1;
11930
11931 i = cp - str->Ptr;
11932
11933 return i;
11934 }
11935
11936
11937
11938
11939 /* @func ajStrFindRestC *******************************************************
11940 **
11941 ** Finds the first occurrence in a string of any character not in a second
11942 ** (text) string.
11943 **
11944 ** @param [r] str [const AjPStr] String
11945 ** @param [r] txt2 [const char*] text to find
11946 ** @return [ajlong] Position of the start of text in string if found.
11947 ** Or -1 for text not found.
11948 **
11949 ** @release 4.1.0
11950 ** @@
11951 ******************************************************************************/
11952
ajStrFindRestC(const AjPStr str,const char * txt2)11953 ajlong ajStrFindRestC(const AjPStr str, const char* txt2)
11954 {
11955 size_t i;
11956
11957 i = strspn(MAJSTRGETPTR(str), txt2);
11958
11959 if(i == MAJSTRGETLEN(str))
11960 return -1;
11961
11962 return i;
11963 }
11964
11965
11966
11967
11968 /* @func ajStrFindRestS *******************************************************
11969 **
11970 ** Finds the first occurrence in a string of any character not in a second
11971 ** (text) string.
11972 **
11973 ** @param [r] str [const AjPStr] String
11974 ** @param [r] str2 [const AjPStr] text to find
11975 ** @return [ajlong] Position of the start of text in string if found.
11976 ** Or -1 for text not found.
11977 **
11978 ** @release 4.1.0
11979 ** @@
11980 ******************************************************************************/
11981
ajStrFindRestS(const AjPStr str,const AjPStr str2)11982 ajlong ajStrFindRestS(const AjPStr str, const AjPStr str2)
11983 {
11984 return ajStrFindRestC(str, MAJSTRGETPTR(str2));
11985 }
11986
11987
11988
11989
11990 /* @func ajStrFindRestCaseC ***************************************************
11991 **
11992 ** Finds the first occurrence in a string of any character not in a second
11993 ** (text) string (case-insensitive).
11994 **
11995 ** @param [r] str [const AjPStr] String
11996 ** @param [r] txt2 [const char*] text to find
11997 ** @return [ajlong] Position of the start of text in string if found.
11998 ** Or -1 for text not found.
11999 **
12000 ** @release 4.1.0
12001 ** @@
12002 ******************************************************************************/
12003
ajStrFindRestCaseC(const AjPStr str,const char * txt2)12004 ajlong ajStrFindRestCaseC(const AjPStr str, const char* txt2)
12005 {
12006 size_t i;
12007 AjPStr tmpstr;
12008 AjPStr tmptxt;
12009
12010 tmpstr = ajStrNewS(str);
12011 tmptxt = ajStrNewC(txt2);
12012
12013 ajStrFmtUpper(&tmptxt);
12014 ajStrFmtUpper(&tmpstr);
12015
12016 i = strspn(tmpstr->Ptr, tmptxt->Ptr);
12017 ajStrDel(&tmpstr);
12018 ajStrDel(&tmptxt);
12019
12020 if(i == str->Len)
12021 return -1;
12022
12023 return i;
12024 }
12025
12026
12027
12028
12029 /* @func ajStrFindRestCaseS ***************************************************
12030 **
12031 ** Finds the first occurrence in a string of any character not in a second
12032 ** (text) string (case-insensitive).
12033 **
12034 ** @param [r] str [const AjPStr] String
12035 ** @param [r] str2 [const AjPStr] text to find
12036 ** @return [ajlong] Position of the start of text in string if found.
12037 ** Or -1 for text not found.
12038 **
12039 ** @release 4.1.0
12040 ** @@
12041 ******************************************************************************/
12042
ajStrFindRestCaseS(const AjPStr str,const AjPStr str2)12043 ajlong ajStrFindRestCaseS(const AjPStr str, const AjPStr str2)
12044 {
12045 return ajStrFindRestCaseC(str, MAJSTRGETPTR(str2));
12046 }
12047
12048
12049
12050
12051 /* @func ajStrFindlastC *******************************************************
12052 **
12053 ** Finds the last occurrence in a string of a second (text) string.
12054 **
12055 ** @param [r] str [const AjPStr] String to search
12056 ** @param [r] txt2 [const char*] text to look for
12057 ** @return [ajlong] Position of the text string if found.
12058 ** @error -1 Text not found.
12059 **
12060 ** @release 4.0.0
12061 ** @@
12062 ******************************************************************************/
12063
ajStrFindlastC(const AjPStr str,const char * txt2)12064 ajlong ajStrFindlastC(const AjPStr str, const char* txt2)
12065 {
12066 ajlong i = 0;
12067 size_t j = 0;
12068 size_t len = 0;
12069 const char* ptr1 = 0;
12070 const char* ptr2 = 0;
12071 AjBool found = ajTrue;
12072
12073 len = strlen(txt2);
12074
12075 for(i=str->Len-len;i>=0;i--)
12076 {
12077 ptr1 = &str->Ptr[i];
12078 ptr2 = txt2;
12079 found = ajTrue;
12080
12081 for(j=0;j<len;j++)
12082 {
12083 if(*ptr1 != *ptr2)
12084 {
12085 found = ajFalse;
12086 break;
12087 }
12088
12089 ptr2++;
12090 ptr1++;
12091 }
12092
12093 if(found)
12094 return i;
12095 }
12096
12097 return -1;
12098 }
12099
12100
12101
12102
12103 /* @func ajStrFindlastK *******************************************************
12104 **
12105 ** Finds the last occurrence in a string of a character.
12106 **
12107 ** @param [r] str [const AjPStr] String to search
12108 ** @param [r] chr [char] Character to look for
12109 ** @return [ajlong] Position of the character if found.
12110 ** @error -1 Text not found.
12111 **
12112 ** @release 6.1.0
12113 ** @@
12114 ******************************************************************************/
12115
ajStrFindlastK(const AjPStr str,char chr)12116 ajlong ajStrFindlastK(const AjPStr str, char chr)
12117 {
12118 const char* cp;
12119
12120 cp = strrchr(MAJSTRGETPTR(str), (ajint) chr);
12121
12122 if(!cp)
12123 return -1;
12124
12125 return(cp - str->Ptr);
12126 }
12127
12128
12129
12130
12131 /* @func ajStrFindlastS *******************************************************
12132 **
12133 ** Finds the last occurrence in a string of a second (text) string.
12134 **
12135 ** @param [r] str [const AjPStr] String to search
12136 ** @param [r] str2 [const AjPStr] text to look for
12137 ** @return [ajlong] Position of the text string if found.
12138 ** @error -1 Text not found.
12139 **
12140 ** @release 4.0.0
12141 ** @@
12142 ******************************************************************************/
12143
ajStrFindlastS(const AjPStr str,const AjPStr str2)12144 ajlong ajStrFindlastS(const AjPStr str, const AjPStr str2)
12145 {
12146 ajlong i = 0;
12147 size_t j = 0;
12148 const char* ptr1 = 0;
12149 const char* ptr2 = 0;
12150 AjBool found = ajTrue;
12151
12152 for(i=str->Len-str2->Len; i >= 0; --i)
12153 {
12154 ptr1 = &str->Ptr[i];
12155 ptr2 = &str2->Ptr[i];
12156 found = ajTrue;
12157
12158 for(j=0; j < str2->Len; ++j)
12159 {
12160 if(*ptr1 != *ptr2)
12161 {
12162 found = ajFalse;
12163 break;
12164 }
12165
12166 ptr2++;
12167 ptr1++;
12168 }
12169
12170 if(found)
12171 return i;
12172 }
12173
12174 return -1;
12175 }
12176
12177
12178
12179
12180 /* @section parsing functions *************************************************
12181 **
12182 ** Functions for parsing tokens from strings.
12183 **
12184 ** @fdata [AjPStr]
12185 ** @fnote None.
12186 **
12187 ** @nam3rule Extract Return token(s) from a string and return
12188 ** the remainder
12189 ** @nam4rule ExtractFirst Remove first word from a string, no leading spaces
12190 ** @nam4rule ExtractToken Remove first token from a string, skipping spaces
12191 ** and punctuation (commas, colons)
12192 ** @nam4rule ExtractWord Remove first word from a string, skipping spaces
12193 ** @nam3rule Parse Parse tokens using strtok
12194 ** @nam4rule ParseCount Count tokens using string token functions
12195 ** @nam5rule ParseCountMulti Multiple (reentrant) version (obsolete?)
12196 ** @nam4rule ParseSplit Parse into array of strings
12197 ** @nam4rule ParseWhite Count tokens using string token functions
12198 **
12199 ** @argrule * str [const AjPStr] String
12200 ** @argrule C txtdelim [const char*] Text to find
12201 ** @argrule K chr [char] Character
12202 ** @argrule S strdelim [const AjPStr] Text to find
12203 ** @argrule Split PPstr [AjPStr**] String array of results
12204 ** @argrule Extract Prest [AjPStr*] Remainder of string
12205 ** @argrule First Pword [AjPStr*] First word of string
12206 ** @argrule Token Pword [AjPStr*] First word of string
12207 ** @argrule Word Pword [AjPStr*] First word of string
12208 **
12209 ** @valrule * [const AjPStr] Latest string parsed.
12210 ** @valrule *Count [ajuint] Number of string matches.
12211 ** @valrule *Split [ajuint] Number of string matches.
12212 ** @valrule *Extract [AjBool] True if a match was found
12213 **
12214 ** @fcategory use
12215 */
12216
12217
12218
12219
12220 /* @func ajStrExtractFirst ****************************************************
12221 **
12222 ** Returns a word from the start of a string, and the remainder of the string
12223 **
12224 ** @param [r] str [const AjPStr] String to be parsed
12225 ** @param [w] Prest [AjPStr*] Remainder of string
12226 ** @param [w] Pword [AjPStr*] First word of string
12227 ** @return [AjBool] True if parsing succeeded
12228 **
12229 ** @release 4.0.0
12230 ** @@
12231 ******************************************************************************/
12232
ajStrExtractFirst(const AjPStr str,AjPStr * Prest,AjPStr * Pword)12233 AjBool ajStrExtractFirst(const AjPStr str, AjPStr* Prest, AjPStr* Pword)
12234 {
12235 size_t i=0;
12236 size_t j=0;
12237 const char* cp;
12238
12239 if(!str)
12240 return ajFalse;
12241
12242 if(!str->Len)
12243 return ajFalse;
12244
12245 cp = str->Ptr;
12246
12247 if(isspace((int)*cp++))
12248 return ajFalse;
12249
12250 while(*cp && !isspace((int)*cp)) /* look for end of first word */
12251 {
12252 cp++;
12253 i++;
12254 }
12255
12256 j = i+1;
12257
12258 while(*cp && isspace((int)*cp))
12259 {
12260 cp++;
12261 j++;
12262 }
12263
12264 ajStrAssignSubS(Pword, str, 0, i);
12265
12266 if(*cp)
12267 ajStrAssignSubS(Prest, str, j, str->Len);
12268 else
12269 ajStrAssignClear(Prest);
12270
12271 /*ajDebug("ajStrExtractFirst i:%d j:%d len:%d word '%S'\n",
12272 i, j, str->Len, *Pword);*/
12273
12274 return ajTrue;
12275 }
12276
12277
12278
12279
12280 /* @func ajStrExtractToken ****************************************************
12281 **
12282 ** Returns a word from the start of a string, and the remainder of the string.
12283 ** Leading spaces and punctuation (commas, semicolons) are ignored
12284 **
12285 ** @param [r] str [const AjPStr] String to be parsed
12286 ** @param [w] Prest [AjPStr*] Remainder of string
12287 ** @param [w] Pword [AjPStr*] First token of string
12288 ** @return [AjBool] True if parsing succeeded
12289 **
12290 ** @release 6.4.0
12291 ** @@
12292 ******************************************************************************/
12293
ajStrExtractToken(const AjPStr str,AjPStr * Prest,AjPStr * Pword)12294 AjBool ajStrExtractToken(const AjPStr str, AjPStr* Prest, AjPStr* Pword)
12295 {
12296 size_t i=0;
12297 size_t istart=0;
12298 size_t j=0;
12299 const char* cp;
12300
12301 if(!str)
12302 return ajFalse;
12303
12304 if(!str->Len)
12305 return ajFalse;
12306
12307 cp = str->Ptr;
12308
12309 while(isspace((int)*cp))
12310 {
12311 cp++;
12312 istart++;
12313 }
12314
12315 if(!*cp)
12316 return ajFalse;
12317
12318 i = istart-1;
12319
12320 while(*cp && !isspace((int)*cp) &&
12321 !(strchr(",;", *cp))) /* look for token end */
12322 {
12323 cp++;
12324 i++;
12325 }
12326
12327 j = i+1;
12328
12329 while(*cp && isspace((int)*cp) && !(strchr(",;", *cp)))
12330 {
12331 cp++;
12332 j++;
12333 }
12334
12335 ajStrAssignSubS(Pword, str, istart, i);
12336
12337 if(*cp)
12338 ajStrAssignSubS(Prest, str, j, str->Len);
12339 else
12340 ajStrAssignClear(Prest);
12341
12342 /*ajDebug("ajStrExtractWord i:%d j:%d len:%d word '%S'\n",
12343 i, j, str->Len, *Pword);*/
12344
12345 return ajTrue;
12346 }
12347
12348
12349
12350
12351 /* @func ajStrExtractWord *****************************************************
12352 **
12353 ** Returns a word from the start of a string, and the remainder of the string.
12354 ** Leading spaces are skipped.
12355 **
12356 ** @param [r] str [const AjPStr] String to be parsed
12357 ** @param [w] Prest [AjPStr*] Remainder of string
12358 ** @param [w] Pword [AjPStr*] First word of string
12359 ** @return [AjBool] True if parsing succeeded
12360 **
12361 ** @release 4.0.0
12362 ** @@
12363 ******************************************************************************/
12364
ajStrExtractWord(const AjPStr str,AjPStr * Prest,AjPStr * Pword)12365 AjBool ajStrExtractWord(const AjPStr str, AjPStr* Prest, AjPStr* Pword)
12366 {
12367 size_t i=0;
12368 size_t istart=0;
12369 size_t j=0;
12370 const char* cp;
12371
12372 if(!str)
12373 return ajFalse;
12374
12375 if(!str->Len)
12376 return ajFalse;
12377
12378 cp = str->Ptr;
12379
12380 while(isspace((int)*cp))
12381 {
12382 cp++;
12383 istart++;
12384 }
12385
12386 if(!*cp)
12387 return ajFalse;
12388
12389 i = istart-1;
12390
12391 while(*cp && !isspace((int)*cp)) /* look for end of first word */
12392 {
12393 cp++;
12394 i++;
12395 }
12396
12397 j = i+1;
12398
12399 while(*cp && isspace((int)*cp))
12400 {
12401 cp++;
12402 j++;
12403 }
12404
12405 ajStrAssignSubS(Pword, str, istart, i);
12406
12407 if(*cp)
12408 ajStrAssignSubS(Prest, str, j, str->Len);
12409 else
12410 ajStrAssignClear(Prest);
12411
12412 /*ajDebug("ajStrExtractWord i:%d j:%d len:%d word '%S'\n",
12413 i, j, str->Len, *Pword);*/
12414
12415 return ajTrue;
12416 }
12417
12418
12419
12420
12421 /* @func ajStrParseC **********************************************************
12422 **
12423 ** Tokenise a string using a specified set of delimiters and return tokens
12424 ** from the string.
12425 **
12426 ** This function uses the C run time library strtok function. This makes it
12427 ** necessary to only call it from one string at a time as strtok and this
12428 ** function have internal memories of the last position.
12429 **
12430 ** @param [r] str [const AjPStr] String to be parsed (first call) or
12431 ** NULL for follow-up calls using the same string, as for the
12432 ** C RTL function strtok which is eventually called.
12433 ** @param [r] txtdelim [const char*] Delimiter(s) to be used between tokens.
12434 ** @return [const AjPStr] Token returned, when all tokens are parsed
12435 ** a NULL is returned.
12436 **
12437 ** @release 4.0.0
12438 ** @@
12439 ******************************************************************************/
12440
ajStrParseC(const AjPStr str,const char * txtdelim)12441 const AjPStr ajStrParseC(const AjPStr str, const char* txtdelim)
12442 {
12443 static AjOStr strParseStr = { 1, 0, NULL, 0, 0};
12444 static AjPStr strp = &strParseStr;
12445
12446 if(!strp->Ptr)
12447 if(!str)
12448 {
12449 ajWarn("Error in ajStrParseC: NULL argument and not initialised");
12450
12451 return NULL;
12452 }
12453
12454 if(str)
12455 {
12456 if(strParseCp) ajCharDel(&strParseCp);
12457 strParseCp = ajCharNewC(str->Ptr);
12458 strp->Ptr = ajSysFuncStrtok(strParseCp, txtdelim);
12459 }
12460 else
12461 strp->Ptr = ajSysFuncStrtok(NULL, txtdelim);
12462
12463 if(strp->Ptr)
12464 {
12465 strp->Len = strlen(strp->Ptr);
12466 strp->Res = strp->Len + 1;
12467
12468 return strp;
12469 }
12470 else
12471 {
12472 strp->Len=0;
12473 strp->Res=1;
12474 ajCharDel(&strParseCp);
12475 }
12476
12477 return NULL;
12478 }
12479
12480
12481
12482
12483 /* @func ajStrParseCount ******************************************************
12484 **
12485 ** Returns the number of tokens in a string, delimited by whitespace
12486 **
12487 ** @param [r] str [const AjPStr] String to examine.
12488 ** @return [ajuint] The number of tokens
12489 **
12490 ** @release 4.0.0
12491 ** @@
12492 ******************************************************************************/
12493
ajStrParseCount(const AjPStr str)12494 ajuint ajStrParseCount(const AjPStr str)
12495 {
12496 AjPStrTok t = NULL;
12497
12498 ajuint count;
12499
12500 if(!str)
12501 return 0;
12502
12503 if(!ajStrGetLen(str))
12504 return 0;
12505
12506 count = 0;
12507 ajStrTokenAssignC(&t, str, " \t\n\r");
12508
12509 while(ajStrTokenStep(t))
12510 ++count;
12511
12512 ajStrTokenDel(&t);
12513
12514 return count;
12515 }
12516
12517
12518
12519
12520 /* @func ajStrParseCountC *****************************************************
12521 **
12522 ** Returns the number of tokens in a string using a specified set of
12523 ** delimiters held in a text string.
12524 **
12525 ** @param [r] str [const AjPStr] String to examine.
12526 ** @param [r] txtdelim [const char *] String of delimiter characters.
12527 ** @return [ajuint] The number of tokens
12528 **
12529 ** @release 4.0.0
12530 ** @@
12531 ******************************************************************************/
12532
ajStrParseCountC(const AjPStr str,const char * txtdelim)12533 ajuint ajStrParseCountC(const AjPStr str, const char *txtdelim)
12534 {
12535 AjPStrTok t = NULL;
12536
12537 ajuint count;
12538
12539 if(!str)
12540 return 0;
12541
12542 if(!ajStrGetLen(str))
12543 return 0;
12544
12545 count = 0;
12546 ajStrTokenAssignC(&t, str, txtdelim);
12547
12548 while(ajStrTokenStep(t))
12549 ++count;
12550
12551 ajStrTokenDel(&t);
12552
12553 return count;
12554 }
12555
12556
12557
12558
12559 /* @func ajStrParseCountS *****************************************************
12560 **
12561 ** Returns the number of tokens in a string using a specified set of
12562 ** delimiters held in a string.
12563 **
12564 ** @param [r] str [const AjPStr] String to examine.
12565 ** @param [r] strdelim [const AjPStr] String of delimiter characters.
12566 ** @return [ajuint] The number of tokens
12567 **
12568 ** @release 4.0.0
12569 ** @@
12570 ******************************************************************************/
12571
ajStrParseCountS(const AjPStr str,const AjPStr strdelim)12572 ajuint ajStrParseCountS(const AjPStr str, const AjPStr strdelim)
12573 {
12574 AjPStrTok t = NULL;
12575
12576 ajuint count;
12577
12578 if(!str)
12579 return 0;
12580
12581 if(!ajStrGetLen(str))
12582 return 0;
12583
12584 count = 0;
12585 ajStrTokenAssignS(&t, str, strdelim);
12586
12587 while(ajStrTokenStep(t))
12588 ++count;
12589
12590 ajStrTokenDel(&t);
12591
12592 return count;
12593 }
12594
12595
12596
12597
12598 /* @func ajStrParseCountMultiC ************************************************
12599 **
12600 ** Returns the number of tokens in a string.
12601 **
12602 ** Uses reentrant {ajSysStrtokR} in place of the C RTL strtok function.
12603 **
12604 ** @param [r] str [const AjPStr] String to examine.
12605 ** @param [r] txtdelim [const char *] String of delimiter characters.
12606 ** @return [ajuint] The number of tokens
12607 **
12608 ** @release 4.0.0
12609 ** @@
12610 ******************************************************************************/
12611
ajStrParseCountMultiC(const AjPStr str,const char * txtdelim)12612 ajuint ajStrParseCountMultiC(const AjPStr str, const char *txtdelim)
12613 {
12614 AjPStr buf = NULL;
12615 ajuint count;
12616 char *p;
12617 const char *save = NULL;
12618 AjPStr mystr = NULL;
12619
12620 if(!str)
12621 return 0;
12622
12623 buf = ajStrNew();
12624 mystr = ajStrNewS(str);
12625
12626 p = ajSysFuncStrtokR(ajStrGetuniquePtr(&mystr),txtdelim,&save,&buf);
12627
12628 if(!p)
12629 {
12630 ajStrDel(&buf);
12631
12632 return 0;
12633 }
12634
12635 count = 1;
12636
12637 while(ajSysFuncStrtokR(NULL,txtdelim,&save,&buf))
12638 ++count;
12639
12640 ajStrDel(&buf);
12641 ajStrDel(&mystr);
12642
12643 return count;
12644 }
12645
12646
12647
12648
12649 /* @func ajStrParseSplit ******************************************************
12650 **
12651 ** Splits a newline-separated multi-line string into an array of strings.
12652 **
12653 ** @param [r] str [const AjPStr] String
12654 ** @param [w] PPstr [AjPStr**] pointer to array of AjPStrs
12655 **
12656 ** @return [ajuint] Number of array elements created
12657 **
12658 ** @release 4.0.0
12659 ** @@
12660 ******************************************************************************/
12661
12662
ajStrParseSplit(const AjPStr str,AjPStr ** PPstr)12663 ajuint ajStrParseSplit(const AjPStr str, AjPStr **PPstr)
12664 {
12665 ajuint c;
12666 size_t len;
12667 size_t i;
12668 size_t n;
12669 const char *p = NULL;
12670 const char *q = NULL;
12671
12672 if(!str)
12673 return 0;
12674
12675 if(!str->Len)
12676 return 0;
12677
12678 p = q = str->Ptr;
12679
12680 len = str->Len;
12681 c=0;
12682 n=0;
12683
12684 for(i=0;i<len;++i)
12685 if(*(p++)=='\n')
12686 ++c;
12687 p=q;
12688
12689 if(ajStrGetCharLast(str) != '\n')
12690 ++c;
12691
12692 AJCNEW0(*PPstr,c);
12693
12694
12695 for(i=0;i<c;++i)
12696 {
12697 while(*q!='\n') /* safe - we already counted c as # of newlines */
12698 ++q;
12699
12700 (*PPstr)[n] = ajStrNew();
12701 ajStrAssignSubC(&(*PPstr)[n++],p,0,q-p);
12702 p = ++q;
12703 }
12704
12705 if(ajStrGetCharLast(str) != '\n')
12706 ajStrAssignC(&(*PPstr)[n++],q);
12707
12708 return c;
12709 }
12710
12711
12712
12713
12714 /* @func ajStrParseWhite ******************************************************
12715 **
12716 ** Tokenise a string using whitespace and return tokens from the string.
12717 **
12718 ** @param [r] str [const AjPStr] String to be parsed (first call) or
12719 ** NULL for follow-up calls using the same string, as for the
12720 ** C RTL function strtok which is eventually called.
12721 ** @return [const AjPStr] Token
12722 ** @error NULL if no further token is found.
12723 **
12724 ** @release 4.0.0
12725 ** @@
12726 ******************************************************************************/
12727
ajStrParseWhite(const AjPStr str)12728 const AjPStr ajStrParseWhite(const AjPStr str)
12729 {
12730 return ajStrParseC(str, " \t\n\r");
12731 }
12732
12733
12734
12735
12736 /* @section debugging *********************************************************
12737 **
12738 ** Functions for reporting of a string object.
12739 **
12740 ** @fdata [AjPStr]
12741 ** @nam3rule Probe Test string memory is valid
12742 ** @nam3rule Stat Report string statistics to debug file
12743 ** @nam3rule Trace Report string elements to debug file
12744 ** @nam4rule TraceFull All characters in detail
12745 ** @nam4rule TraceTitle With title text
12746 **
12747 ** @argrule Probe Pstr [AjPStr const*] String
12748 ** @argrule Stat title [const char*] Report title
12749 ** @argrule Trace str [const AjPStr] String
12750 ** @argrule TraceTitle title [const char*] Report title
12751 **
12752 ** @valrule * [void]
12753 **
12754 ** @fcategory misc
12755 */
12756
12757
12758
12759
12760 /* @func ajStrProbe ***********************************************************
12761 **
12762 ** Default string memory probe which checks the string object and the
12763 ** string it contains are valid memory
12764 **
12765 ** If the given string is NULL, or a NULL pointer, simply returns.
12766 **
12767 ** @param [r] Pstr [AjPStr const *] Pointer to the string to be probed.
12768 ** @return [void]
12769 **
12770 ** @release 6.0.0
12771 ** @@
12772 ******************************************************************************/
12773
ajStrProbe(AjPStr const * Pstr)12774 void ajStrProbe(AjPStr const * Pstr)
12775 {
12776 AjPStr thys;
12777
12778 if(!Pstr)
12779 return;
12780
12781 if(!*Pstr)
12782 return;
12783
12784 thys = *Pstr;
12785
12786 if(thys != strPNULL) /* ignore the constant null string */
12787 {
12788 AJMPROBE(thys->Ptr);
12789 AJMPROBE(*Pstr);
12790 }
12791
12792 return;
12793 }
12794
12795
12796
12797
12798 /* @func ajStrStat ************************************************************
12799 **
12800 ** Prints a summary of string usage with debug calls.
12801 **
12802 ** @param [r] title [const char*] Title for this summary
12803 ** @return [void]
12804 **
12805 ** @release 1.0.0
12806 ** @@
12807 ******************************************************************************/
12808
ajStrStat(const char * title)12809 void ajStrStat(const char* title)
12810 {
12811 #ifdef AJ_SAVESTATS
12812 static ajlong statAlloc = 0;
12813 static ajlong statExtra = 0;
12814 static ajlong statCount = 0;
12815 static ajlong statFree = 0;
12816 static ajlong statFreeCount = 0;
12817 static ajlong statTotal = 0;
12818
12819 ajDebug("String usage statistics since last call %s:\n", title);
12820 ajDebug("String usage (bytes): %Ld allocated, %Ld resize, %Ld freed\n",
12821 strAlloc - statAlloc, strExtra - statExtra,
12822 strFree - statFree);
12823 ajDebug("String usage (number): %Ld allocated, %Ld freed, %Ld in use\n",
12824 strTotal - statTotal, strFreeCount - statFreeCount,
12825 strCount - statCount);
12826
12827 statAlloc = strAlloc;
12828 statExtra = strExtra;
12829 statCount = strCount;
12830 statFree = strFree;
12831 statFreeCount = strFreeCount;
12832 statTotal = strTotal;
12833 #else
12834 (void) title;
12835 #endif
12836
12837 return;
12838 }
12839
12840
12841
12842
12843 /* @func ajStrTrace ***********************************************************
12844 **
12845 ** Checks a string object for consistency and reports its contents.
12846 **
12847 ** @param [r] str [const AjPStr] String
12848 ** @return [void]
12849 **
12850 ** @release 1.0.0
12851 ** @@
12852 ******************************************************************************/
12853
ajStrTrace(const AjPStr str)12854 void ajStrTrace(const AjPStr str)
12855 {
12856 if(!str)
12857 {
12858 ajDebug("String trace NULL\n");
12859
12860 return;
12861 }
12862
12863 if(!ajStrGetValid(str))
12864 ajDebug("ajStrGetValid problems: see warning messages\n");
12865
12866 ajDebug("String trace use: %d size: %d len: %d string: ",
12867 str->Use, str->Res, str->Len);
12868
12869 if(str->Ptr)
12870 {
12871 if(str->Len <= 20)
12872 ajDebug("<%s>\n", str->Ptr);
12873 else
12874 ajDebug("<%10.10s>..<%s>\n",
12875 str->Ptr, str->Ptr + str->Len-10);
12876 }
12877 else
12878 ajDebug("<NULL>\n");
12879
12880 ajDebug(" ptr: %x charptr: %x\n",
12881 str, str->Ptr);
12882
12883 return;
12884 }
12885
12886
12887
12888
12889 /* @func ajStrTraceFull *******************************************************
12890 **
12891 ** Checks a string object for consistency and reports its contents character
12892 ** by character.
12893 **
12894 ** @param [r] str [const AjPStr] String
12895 ** @return [void]
12896 **
12897 ** @release 4.0.0
12898 ** @@
12899 ******************************************************************************/
12900
ajStrTraceFull(const AjPStr str)12901 void ajStrTraceFull(const AjPStr str)
12902 {
12903 size_t i;
12904
12905 if(!str)
12906 {
12907 ajDebug("String tracechars NULL\n");
12908
12909 return;
12910 }
12911
12912 if(!ajStrGetValid(str))
12913 ajDebug("ajStrGetValid problems: see warning messages\n");
12914
12915 ajDebug("String tracechars use: %d size: %d len: %d string: ",
12916 str->Use, str->Res, str->Len);
12917
12918 if(str->Len)
12919 {
12920 ajDebug("\n");
12921
12922 for(i=0; i < str->Len; i++)
12923 ajDebug(" '%c' %20x [%d]\n",
12924 str->Ptr[i], (ajint) str->Ptr[i], i);
12925 }
12926 else
12927 ajDebug("<NULL>\n");
12928
12929 ajDebug(" ptr: %x charptr: %x\n",
12930 str, str->Ptr);
12931
12932 return;
12933 }
12934
12935
12936
12937
12938 /* @func ajStrTraceTitle ******************************************************
12939 **
12940 ** Checks a string object for consistency and reports its contents using a
12941 ** defined title for the report.
12942 **
12943 ** @param [r] str [const AjPStr] String
12944 ** @param [r] title [const char*] Report title
12945 ** @return [void]
12946 **
12947 ** @release 4.0.0
12948 ** @@
12949 ******************************************************************************/
12950
ajStrTraceTitle(const AjPStr str,const char * title)12951 void ajStrTraceTitle(const AjPStr str, const char* title)
12952 {
12953 ajDebug("%s\n",title);
12954 ajStrTrace(str);
12955
12956 return;
12957 }
12958
12959
12960
12961
12962 /* @section exit **************************************************************
12963 **
12964 ** Functions called on exit from the program by ajExit to do
12965 ** any necessary cleanup and to report internal statistics to the debug file
12966 **
12967 ** @fdata [AjPStr]
12968 ** @fnote general exit functions, no arguments
12969 **
12970 ** @nam3rule Exit Cleanup and report on exit
12971 **
12972 ** @valrule * [void]
12973 **
12974 ** @fcategory misc
12975 */
12976
12977
12978
12979
12980 /* @func ajStrExit ************************************************************
12981 **
12982 ** Prints a summary of string usage with debug calls.
12983 **
12984 ** @return [void]
12985 **
12986 ** @release 1.0.0
12987 ** @@
12988 ******************************************************************************/
12989
ajStrExit(void)12990 void ajStrExit(void)
12991 {
12992 #ifdef AJ_SAVESTATS
12993 ajDebug("String usage (bytes): %Ld allocated, %Ld resized, "
12994 "%Ld freed, %Ld in use\n",
12995 strAlloc, strExtra, strFree,
12996 (strAlloc + strExtra - strFree));
12997 ajDebug("String usage (number): %Ld allocated, %Ld freed %Ld in use\n",
12998 strTotal, strFreeCount, strCount);
12999 #endif
13000
13001 ajCharDel(&strParseCp);
13002
13003 return;
13004 }
13005
13006
13007
13008
13009 /* @datasection [const AjPStr] String constant *********************************
13010 **
13011 ** Functions for manipulating AJAX (AjPStr) string constants
13012 **
13013 ** @nam2rule Str Function is for manipulating strings
13014 **
13015 */
13016
13017
13018
13019
13020 /* @section string constant constructors ***************************************
13021 **
13022 ** Functions for constructing string constant objects
13023 **
13024 ** @fdata [const AjPStr]
13025 ** @fnote Same namrule as "String constructor functions:
13026 ** C-type (char*) strings"
13027 ** @nam3rule Const Construct a constant string.
13028 ** @nam4rule ConstEmpty Construct with an empty string.
13029 **
13030 ** @argrule S str [const AjPStr] Text string
13031 **
13032 ** @valrule * [const AjPStr] New string
13033 ** @fcategory new
13034 */
13035
13036
13037
13038
13039 /* @func ajStrConstS **********************************************************
13040 **
13041 ** Returns an unmodifiable empty string.
13042 **
13043 ** @param [r] str [const AjPStr] String
13044 ** @return [const AjPStr] Pointer to an empty string
13045 **
13046 ** @release 6.2.0
13047 ** @@
13048 ******************************************************************************/
13049
ajStrConstS(const AjPStr str)13050 const AjPStr ajStrConstS(const AjPStr str)
13051 {
13052 if(!str)
13053 return strPNULL;
13054
13055 return str;
13056 }
13057
13058
13059
13060
13061 /* @func ajStrConstEmpty ******************************************************
13062 **
13063 ** Returns an unmodifiable empty string.
13064 **
13065 ** @return [const AjPStr] Pointer to an empty string
13066 **
13067 ** @release 6.2.0
13068 ** @@
13069 ******************************************************************************/
13070
ajStrConstEmpty(void)13071 const AjPStr ajStrConstEmpty(void)
13072 {
13073 return strPNULL;
13074 }
13075
13076
13077
13078
13079 /* @datasection [AjIStr] String iterator *************************************
13080 **
13081 ** String iterators point to successive characters in a string
13082 **
13083 ** @nam2rule Str String
13084 ** @nam3rule Iter Iterator
13085 **
13086 ******************************************************************************/
13087
13088
13089
13090
13091 /* @section constructors ******************************************************
13092 **
13093 ** @fdata [AjIStr]
13094 **
13095 ** @nam4rule New String iterator constructor.
13096 ** @nam5rule NewBack String iterator reverse direction constructor.
13097 **
13098 ** @argrule New str [const AjPStr] Original string
13099 **
13100 ** @valrule * [AjIStr] String iterator
13101 **
13102 ** @fcategory new
13103 ******************************************************************************/
13104
13105
13106
13107
13108 /* @func ajStrIterNew *********************************************************
13109 **
13110 ** String iterator constructor which allocates memory for a string iterator,
13111 ** used to iterate over the characters in a string.
13112 **
13113 ** @param [r] str [const AjPStr] Original string
13114 **
13115 ** @return [AjIStr] String Iterator
13116 **
13117 ** @release 4.0.0
13118 ** @@
13119 ******************************************************************************/
13120
ajStrIterNew(const AjPStr str)13121 AjIStr ajStrIterNew(const AjPStr str)
13122 {
13123 AjIStr iter;
13124
13125 if(!str)
13126 ajFatal("ajStrIterNew source string NULL");
13127
13128 AJNEW0(iter);
13129 iter->Start = iter->Ptr = str->Ptr;
13130 iter->End = iter->Start + MAJSTRGETLEN(str) - 1;
13131
13132 return iter;
13133 }
13134
13135
13136
13137
13138 /* @func ajStrIterNewBack *****************************************************
13139 **
13140 ** String iterator constructor which allocates memory for a string iterator,
13141 ** used to iterate over the characters in a string, from end to start.
13142 **
13143 ** @param [r] str [const AjPStr] Original string
13144 ** @return [AjIStr] String Iterator
13145 **
13146 ** @release 4.0.0
13147 ** @@
13148 ******************************************************************************/
13149
ajStrIterNewBack(const AjPStr str)13150 AjIStr ajStrIterNewBack(const AjPStr str)
13151 {
13152 AjIStr iter;
13153
13154 if(!str)
13155 ajFatal("ajStrIterNewBack source string NULL");
13156
13157 AJNEW0(iter);
13158 iter->Start = str->Ptr;
13159 iter->End = iter->Ptr = iter->Start + MAJSTRGETLEN(str) - 1;
13160
13161 return iter;
13162 }
13163
13164
13165
13166
13167 /* @section destructors *******************************************************
13168 ** @fdata [AjIStr]
13169 **
13170 ** @nam4rule Del Destructor
13171 **
13172 ** @argrule Del iter [AjIStr*] String iterator
13173 **
13174 ** @valrule * [void]
13175 **
13176 ** @fcategory delete
13177 */
13178
13179
13180
13181
13182 /* @func ajStrIterDel *********************************************************
13183 **
13184 ** String iterator destructor which frees memory for a string iterator.
13185 **
13186 ** @param [d] iter [AjIStr*] String iterator
13187 ** @return [void]
13188 **
13189 ** @release 4.0.0
13190 ** @@
13191 ******************************************************************************/
13192
ajStrIterDel(AjIStr * iter)13193 void ajStrIterDel(AjIStr* iter)
13194 {
13195 AJFREE(*iter);
13196
13197 return;
13198 }
13199
13200
13201
13202
13203 /* @section tests *************************************************************
13204 ** @fdata [AjIStr]
13205 ** @nam4rule Done Check whether iteration has ended (no more
13206 ** characters).
13207 ** @nam5rule DoneBack Reverse iterator
13208 **
13209 ** @argrule Done iter [const AjIStr] Iterator
13210 **
13211 ** @valrule * [AjBool] Result of test
13212 **
13213 ** @fcategory use
13214 */
13215
13216
13217
13218
13219 /* @func ajStrIterDone ********************************************************
13220 **
13221 ** Tests whether a string iterator has completed yet.
13222 **
13223 ** @param [r] iter [const AjIStr] String iterator.
13224 ** @return [AjBool] true if complete
13225 **
13226 ** @release 4.0.0
13227 ** @@
13228 ******************************************************************************/
13229
ajStrIterDone(const AjIStr iter)13230 AjBool ajStrIterDone(const AjIStr iter)
13231 {
13232 return (iter->Ptr > iter->End);
13233 }
13234
13235
13236
13237
13238 /* @func ajStrIterDoneBack ****************************************************
13239 **
13240 ** Tests whether a string iterator (from end to start) has completed yet.
13241 **
13242 ** @param [r] iter [const AjIStr] String iterator.
13243 ** @return [AjBool] true if complete
13244 **
13245 ** @release 4.0.0
13246 ** @@
13247 ******************************************************************************/
13248
ajStrIterDoneBack(const AjIStr iter)13249 AjBool ajStrIterDoneBack(const AjIStr iter)
13250 {
13251 return (iter->Ptr < iter->Start);
13252 }
13253
13254
13255
13256
13257 /* @section resets ************************************************************
13258 ** @fdata [AjIStr]
13259 **
13260 ** @nam4rule Begin Resets iterator to start (first character).
13261 ** @nam4rule End Resets iterator to end (last character).
13262 ** @argrule * iter [AjIStr] String iterator
13263 **
13264 ** @valrule * [void]
13265 **
13266 ** @fcategory modify
13267 */
13268
13269
13270
13271
13272 /* @func ajStrIterBegin *******************************************************
13273 **
13274 ** Sets a string iterator to its start condition,
13275 **
13276 ** @param [u] iter [AjIStr] String iterator.
13277 ** @return [void]
13278 **
13279 ** @release 4.0.0
13280 ** @@
13281 ******************************************************************************/
13282
ajStrIterBegin(AjIStr iter)13283 void ajStrIterBegin(AjIStr iter)
13284 {
13285 iter->Ptr = iter->Start;
13286 return;
13287 }
13288
13289
13290
13291
13292 /* @func ajStrIterEnd *********************************************************
13293 **
13294 ** Sets a string iterator to its stop condition.
13295 **
13296 ** @param [u] iter [AjIStr] String iterator.
13297 ** @return [void]
13298 **
13299 ** @release 4.0.0
13300 ** @@
13301 ******************************************************************************/
13302
ajStrIterEnd(AjIStr iter)13303 void ajStrIterEnd(AjIStr iter)
13304 {
13305 iter->Ptr = iter->End;
13306
13307 return;
13308 }
13309
13310
13311
13312
13313 /* @section attributes ********************************************************
13314 **
13315 ** @fdata [AjIStr]
13316 **
13317 ** @nam4rule Get Return element
13318 **
13319 ** @argrule Get iter [const AjIStr] Iterator
13320 ** @valrule GetC [const char*]
13321 ** @valrule GetK [char]
13322 **
13323 ** @fcategory cast
13324 */
13325
13326
13327
13328
13329 /* @func ajStrIterGetC ********************************************************
13330 **
13331 ** Returns the remainder of the string at the current string iterator
13332 ** position.
13333 **
13334 ** @param [r] iter [const AjIStr] String iterator.
13335 ** @return [const char*] Current text string within iterator
13336 **
13337 ** @release 4.0.0
13338 ** @@
13339 ******************************************************************************/
13340
ajStrIterGetC(const AjIStr iter)13341 const char* ajStrIterGetC(const AjIStr iter)
13342 {
13343 return iter->Ptr;
13344 }
13345
13346
13347
13348
13349 /* @func ajStrIterGetK ********************************************************
13350 **
13351 ** Returns the value (character) at the current string iterator position.
13352 **
13353 ** @param [r] iter [const AjIStr] String iterator.
13354 ** @return [char] Current character within iterator
13355 **
13356 ** @release 4.0.0
13357 ** @@
13358 ******************************************************************************/
13359
ajStrIterGetK(const AjIStr iter)13360 char ajStrIterGetK(const AjIStr iter)
13361 {
13362 return *(iter->Ptr);
13363 }
13364
13365
13366
13367
13368 /* @section modifiers *********************************************************
13369 **
13370 ** @fdata [AjIStr]
13371 **
13372 ** @nam4rule Put Replace an element
13373 **
13374 ** @argrule * iter [AjIStr]
13375 ** @argrule K chr [char] Character to put at current position
13376 ** @valrule * [void]
13377 **
13378 ** @fcategory modify
13379 */
13380
13381
13382
13383
13384 /* @func ajStrIterPutK ********************************************************
13385 **
13386 ** Replaces the character at the current string iterator position.
13387 **
13388 ** @param [u] iter [AjIStr] String iterator.
13389 ** @param [r] chr [char] Character
13390 ** @return [void]
13391 **
13392 ** @release 4.0.0
13393 ** @@
13394 ******************************************************************************/
13395
ajStrIterPutK(AjIStr iter,char chr)13396 void ajStrIterPutK(AjIStr iter, char chr)
13397 {
13398 *iter->Ptr = chr;
13399
13400 return;
13401 }
13402
13403
13404
13405
13406 /* @section stepping **********************************************************
13407 **
13408 ** @fdata [AjIStr]
13409 **
13410 ** @nam4rule Next Iterate to next character.
13411 ** @nam5rule NextBack Reverse iterator
13412 **
13413 ** @argrule * iter [AjIStr] String iterator
13414 **
13415 ** @valrule * [AjIStr] Updated iterator
13416 **
13417 ** @fcategory modify
13418 */
13419
13420
13421
13422
13423 /* @func ajStrIterNext ********************************************************
13424 **
13425 ** Step to next character in string iterator.
13426 **
13427 ** @param [u] iter [AjIStr] String iterator.
13428 ** @return [AjIStr] Updated iterator duplicated as return value.
13429 **
13430 ** @release 1.0.0
13431 ** @@
13432 ******************************************************************************/
13433
ajStrIterNext(AjIStr iter)13434 AjIStr ajStrIterNext(AjIStr iter)
13435 {
13436 iter->Ptr++;
13437
13438 if(iter->Ptr > iter->End)
13439 return NULL;
13440
13441 return iter;
13442 }
13443
13444
13445
13446
13447 /* @func ajStrIterNextBack ****************************************************
13448 **
13449 ** Step to previous character in string iterator.
13450 **
13451 ** @param [u] iter [AjIStr] String iterator.
13452 ** @return [AjIStr] Updated iterator duplicated as return value.
13453 **
13454 ** @release 4.0.0
13455 ** @@
13456 ******************************************************************************/
13457
ajStrIterNextBack(AjIStr iter)13458 AjIStr ajStrIterNextBack(AjIStr iter)
13459 {
13460 iter->Ptr--;
13461
13462 if(iter->Ptr < iter->Start)
13463 return NULL;
13464
13465 return iter;
13466 }
13467
13468
13469
13470
13471 /* @datasection [AjPStrTok] String token parser *******************************
13472 **
13473 ** @nam2rule Str String
13474 ** @nam3rule Token Token parser
13475 **
13476 ******************************************************************************/
13477
13478
13479
13480
13481 /* @section constructors ******************************************************
13482 **
13483 ** @fdata [AjPStrTok]
13484 **
13485 ** @nam4rule New Constructor with string object data
13486 ** @nam4rule Newchar Constructor with C string data
13487 **
13488 ** @argrule New str [const AjPStr] string
13489 ** @argrule Newchar txt [const char*] string
13490 ** @argrule C txtdelim [const char*] Text delimiter
13491 ** @argrule S strdelim [const AjPStr] Text delimiter
13492 ** @valrule * [AjPStrTok] String token parser
13493 **
13494 ** @fcategory new
13495 */
13496
13497
13498
13499
13500 /* @func ajStrTokenNewC *******************************************************
13501 **
13502 ** String token parser constructor which allocates memory for a string token
13503 ** parser object from a string and a set of default delimiters defined in a
13504 ** text string.
13505 **
13506 ** @param [r] str [const AjPStr] Source string
13507 ** @param [r] txtdelim [const char*] Default delimiter(s)
13508 ** @return [AjPStrTok] A new string token parser.
13509 **
13510 ** @release 4.0.0
13511 ** @@
13512 ******************************************************************************/
13513
ajStrTokenNewC(const AjPStr str,const char * txtdelim)13514 AjPStrTok ajStrTokenNewC(const AjPStr str, const char* txtdelim)
13515 {
13516 AjPStrTok ret;
13517
13518 AJNEW0(ret);
13519
13520 ajStrAssignS(&ret->String, str);
13521
13522 ret->Delim = ajStrNewC(txtdelim);
13523 ret->Pos = 0; /* GFF parsing needed this change */
13524
13525 return ret;
13526 }
13527
13528
13529
13530
13531 /* @func ajStrTokenNewS *******************************************************
13532 **
13533 ** String token parser constructor which allocates memory for a string token
13534 ** parser object from a string and an optional set of default delimiters
13535 ** defined in a text string.
13536 **
13537 ** @param [r] str [const AjPStr] Source string
13538 ** @param [r] strdelim [const AjPStr] Default delimiter(s)
13539 ** @return [AjPStrTok] A new string token parser.
13540 **
13541 ** @release 4.0.0
13542 ** @@
13543 ******************************************************************************/
13544
ajStrTokenNewS(const AjPStr str,const AjPStr strdelim)13545 AjPStrTok ajStrTokenNewS(const AjPStr str, const AjPStr strdelim)
13546 {
13547 AjPStrTok ret;
13548
13549 AJNEW0(ret);
13550
13551 ajStrAssignS(&ret->String, str);
13552
13553 ret->Delim = ajStrNewS(strdelim);
13554 ret->Pos = 0; /* GFF parsing needed this change */
13555
13556 return ret;
13557 }
13558
13559
13560
13561
13562 /* @func ajStrTokenNewcharC ***************************************************
13563 **
13564 ** String token parser constructor which allocates memory for a string token
13565 ** parser object from a string and a set of default delimiters defined in a
13566 ** text string.
13567 **
13568 ** @param [r] txt [const char*] Source string
13569 ** @param [r] txtdelim [const char*] Default delimiter(s)
13570 ** @return [AjPStrTok] A new string token parser.
13571 **
13572 ** @release 6.4.0
13573 ** @@
13574 ******************************************************************************/
13575
ajStrTokenNewcharC(const char * txt,const char * txtdelim)13576 AjPStrTok ajStrTokenNewcharC(const char* txt, const char* txtdelim)
13577 {
13578 AjPStrTok ret;
13579
13580 AJNEW0(ret);
13581
13582 ajStrAssignC(&ret->String, txt);
13583
13584 ret->Delim = ajStrNewC(txtdelim);
13585 ret->Pos = 0; /* GFF parsing needed this change */
13586
13587 return ret;
13588 }
13589
13590
13591
13592
13593 /* @func ajStrTokenNewcharS ***************************************************
13594 **
13595 ** String token parser constructor which allocates memory for a string token
13596 ** parser object from a string and an optional set of default delimiters
13597 ** defined in a text string.
13598 **
13599 ** @param [r] txt [const char*] Source string
13600 ** @param [r] strdelim [const AjPStr] Default delimiter(s)
13601 ** @return [AjPStrTok] A new string token parser.
13602 **
13603 ** @release 6.4.0
13604 ** @@
13605 ******************************************************************************/
13606
ajStrTokenNewcharS(const char * txt,const AjPStr strdelim)13607 AjPStrTok ajStrTokenNewcharS(const char* txt, const AjPStr strdelim)
13608 {
13609 AjPStrTok ret;
13610
13611 AJNEW0(ret);
13612
13613 ajStrAssignC(&ret->String, txt);
13614
13615 ret->Delim = ajStrNewS(strdelim);
13616 ret->Pos = 0; /* GFF parsing needed this change */
13617
13618 return ret;
13619 }
13620
13621
13622
13623
13624 /* @section destructors *******************************************************
13625 **
13626 ** @fdata [AjPStrTok]
13627 **
13628 ** @nam4rule Del Destructor
13629 **
13630 ** @argrule Del Ptoken [AjPStrTok*] String token parser
13631 **
13632 ** @valrule * [void]
13633 **
13634 ** @fcategory delete
13635 */
13636
13637
13638
13639
13640 /* @func ajStrTokenDel ********************************************************
13641 **
13642 ** String token parser destructor which frees memory for a string token
13643 ** parser.
13644 **
13645 ** @param [d] Ptoken [AjPStrTok*] Token parser
13646 ** @return [void]
13647 **
13648 ** @release 4.0.0
13649 ** @@
13650 ******************************************************************************/
13651
ajStrTokenDel(AjPStrTok * Ptoken)13652 void ajStrTokenDel(AjPStrTok* Ptoken)
13653 {
13654 if(!*Ptoken)
13655 return;
13656
13657 ajStrDel(&(*Ptoken)->String);
13658 ajStrDel(&(*Ptoken)->Delim);
13659 AJFREE(*Ptoken);
13660
13661 return;
13662 }
13663
13664
13665
13666
13667 /* @section assignment ********************************************************
13668 **
13669 ** @fdata [AjPStrTok]
13670 **
13671 ** @nam4rule Assign Assignment of string and/or delimiter(s)
13672 ** @nam4rule Assignchar Assignment of C character string and/or delimiter(s)
13673 **
13674 ** @argrule Assign Ptoken [AjPStrTok*] Token parser
13675 ** @argrule Assignchar Ptoken [AjPStrTok*] Token parser
13676 ** @argrule Assign str [const AjPStr] String to be parsed
13677 ** @argrule Assignchar txt [const char*] String to be parsed
13678 ** @argrule C txtdelim [const char*] delimiter
13679 ** @argrule S strdelim [const AjPStr] delimiter
13680 **
13681 ** @valrule * [AjBool] True on success
13682 **
13683 ** @fcategory assign
13684 */
13685
13686
13687
13688
13689 /* @func ajStrTokenAssign *****************************************************
13690 **
13691 ** Generates a string token parser object from a string without a specific
13692 ** set of delimiters.
13693 **
13694 ** @param [w] Ptoken [AjPStrTok*] String token object
13695 ** @param [r] str [const AjPStr] Source string
13696 ** @return [AjBool] ajTrue on success.
13697 **
13698 ** @release 4.0.0
13699 ** @@
13700 ******************************************************************************/
13701
ajStrTokenAssign(AjPStrTok * Ptoken,const AjPStr str)13702 AjBool ajStrTokenAssign(AjPStrTok* Ptoken, const AjPStr str)
13703 {
13704 AjPStrTok tok;
13705
13706 if(*Ptoken)
13707 tok = *Ptoken;
13708 else
13709 {
13710 AJNEW0(tok);
13711 *Ptoken = tok;
13712 }
13713
13714 ajStrAssignS(&tok->String, str);
13715 ajStrAssignClear(&tok->Delim);
13716 tok->Pos = 0;
13717
13718 return ajTrue;
13719 }
13720
13721
13722
13723
13724 /* @func ajStrTokenAssignC ****************************************************
13725 **
13726 ** Generates a string token parser object from a string and an optional
13727 ** set of default delimiters defined in a text string.
13728 **
13729 ** The string token can be either an existing token to be overwritten
13730 ** or a NULL.
13731 **
13732 ** @param [w] Ptoken [AjPStrTok*] String token object
13733 ** @param [r] str [const AjPStr] Source string
13734 ** @param [r] txtdelim [const char*] Default delimiter(s)
13735 ** @return [AjBool] ajTrue on success.
13736 **
13737 ** @release 4.0.0
13738 ** @@
13739 ******************************************************************************/
13740
ajStrTokenAssignC(AjPStrTok * Ptoken,const AjPStr str,const char * txtdelim)13741 AjBool ajStrTokenAssignC(AjPStrTok* Ptoken, const AjPStr str,
13742 const char* txtdelim)
13743 {
13744 AjPStrTok tok;
13745
13746 if(*Ptoken)
13747 tok = *Ptoken;
13748 else
13749 {
13750 AJNEW0(tok);
13751 *Ptoken = tok;
13752 }
13753
13754 ajStrAssignS(&tok->String, str);
13755 ajStrAssignC(&tok->Delim, txtdelim);
13756 tok->Pos = strspn(tok->String->Ptr, tok->Delim->Ptr);
13757
13758 return ajTrue;
13759 }
13760
13761
13762
13763
13764 /* @func ajStrTokenAssignS ****************************************************
13765 **
13766 ** Generates a string token parser object from a string and an optional
13767 ** set of default delimiters defined in a string.
13768 **
13769 ** @param [w] Ptoken [AjPStrTok*] String token object
13770 ** @param [r] str [const AjPStr] Source string
13771 ** @param [r] strdelim [const AjPStr] Default delimiter(s)
13772 ** @return [AjBool] ajTrue on success.
13773 **
13774 ** @release 4.0.0
13775 ** @@
13776 ******************************************************************************/
13777
ajStrTokenAssignS(AjPStrTok * Ptoken,const AjPStr str,const AjPStr strdelim)13778 AjBool ajStrTokenAssignS(AjPStrTok* Ptoken, const AjPStr str,
13779 const AjPStr strdelim)
13780 {
13781 AjPStrTok tok;
13782
13783 if(*Ptoken)
13784 tok = *Ptoken;
13785 else
13786 {
13787 AJNEW0(tok);
13788 *Ptoken = tok;
13789 }
13790
13791 ajStrAssignS(&tok->String, str);
13792 ajStrAssignS(&tok->Delim, strdelim);
13793 tok->Pos = strspn(tok->String->Ptr, tok->Delim->Ptr);
13794
13795 return ajTrue;
13796 }
13797
13798
13799
13800
13801 /* @func ajStrTokenAssignchar *************************************************
13802 **
13803 ** Generates a string token parser object from a string without a specific
13804 ** set of delimiters.
13805 **
13806 ** @param [w] Ptoken [AjPStrTok*] String token object
13807 ** @param [r] txt [const char*] Source string
13808 ** @return [AjBool] ajTrue on success.
13809 **
13810 ** @release 4.0.0
13811 ** @@
13812 ******************************************************************************/
13813
ajStrTokenAssignchar(AjPStrTok * Ptoken,const char * txt)13814 AjBool ajStrTokenAssignchar(AjPStrTok* Ptoken, const char *txt)
13815 {
13816 AjPStrTok tok;
13817
13818 if(*Ptoken)
13819 tok = *Ptoken;
13820 else
13821 {
13822 AJNEW0(tok);
13823 *Ptoken = tok;
13824 }
13825
13826 ajStrAssignC(&tok->String, txt);
13827 ajStrAssignClear(&tok->Delim);
13828 tok->Pos = 0;
13829
13830 return ajTrue;
13831 }
13832
13833
13834
13835
13836 /* @func ajStrTokenAssigncharC ************************************************
13837 **
13838 ** Generates a string token parser object from a string and an optional
13839 ** set of default delimiters defined in a text string.
13840 **
13841 ** The string token can be either an existing token to be overwritten
13842 ** or a NULL.
13843 **
13844 ** @param [w] Ptoken [AjPStrTok*] String token object
13845 ** @param [r] txt [const char*] Source string
13846 ** @param [r] txtdelim [const char*] Default delimiter(s)
13847 ** @return [AjBool] ajTrue on success.
13848 **
13849 ** @release 4.0.0
13850 ** @@
13851 ******************************************************************************/
13852
ajStrTokenAssigncharC(AjPStrTok * Ptoken,const char * txt,const char * txtdelim)13853 AjBool ajStrTokenAssigncharC(AjPStrTok* Ptoken, const char *txt,
13854 const char* txtdelim)
13855 {
13856 AjPStrTok tok;
13857
13858 if(*Ptoken)
13859 tok = *Ptoken;
13860 else
13861 {
13862 AJNEW0(tok);
13863 *Ptoken = tok;
13864 }
13865
13866 ajStrAssignC(&tok->String, txt);
13867 ajStrAssignC(&tok->Delim, txtdelim);
13868 tok->Pos = strspn(tok->String->Ptr, tok->Delim->Ptr);
13869
13870 return ajTrue;
13871 }
13872
13873
13874
13875
13876 /* @func ajStrTokenAssigncharS ************************************************
13877 **
13878 ** Generates a string token parser object from a string and an optional
13879 ** set of default delimiters defined in a string.
13880 **
13881 ** @param [w] Ptoken [AjPStrTok*] String token object
13882 ** @param [r] txt [const char*] Source string
13883 ** @param [r] strdelim [const AjPStr] Default delimiter(s)
13884 ** @return [AjBool] ajTrue on success.
13885 **
13886 ** @release 4.0.0
13887 ** @@
13888 ******************************************************************************/
13889
ajStrTokenAssigncharS(AjPStrTok * Ptoken,const char * txt,const AjPStr strdelim)13890 AjBool ajStrTokenAssigncharS(AjPStrTok* Ptoken, const char *txt,
13891 const AjPStr strdelim)
13892 {
13893 AjPStrTok tok;
13894
13895 if(*Ptoken)
13896 tok = *Ptoken;
13897 else
13898 {
13899 AJNEW0(tok);
13900 *Ptoken = tok;
13901 }
13902
13903 ajStrAssignC(&tok->String, txt);
13904 ajStrAssignS(&tok->Delim, strdelim);
13905 tok->Pos = strspn(tok->String->Ptr, tok->Delim->Ptr);
13906
13907 return ajTrue;
13908 }
13909
13910
13911
13912
13913 /* @section reset *************************************************************
13914 **
13915 ** @fdata [AjPStrTok]
13916 **
13917 ** @nam4rule Reset Reset the token parser internals
13918 **
13919 ** @argrule * token [AjPStrTok] String token parser
13920 **
13921 ** @valrule * [void]
13922 **
13923 ** @fcategory modify
13924 */
13925
13926
13927
13928
13929 /* @func ajStrTokenReset ******************************************************
13930 **
13931 ** Clears the strings from a string token parser object.
13932 **
13933 ** @param [w] token [AjPStrTok] String token object
13934 ** @return [void]
13935 **
13936 ** @release 6.6.0
13937 ** @@
13938 ******************************************************************************/
13939
ajStrTokenReset(AjPStrTok token)13940 void ajStrTokenReset(AjPStrTok token)
13941 {
13942 if(!token)
13943 return;
13944
13945 ajStrDelStatic(&token->String);
13946 ajStrDelStatic(&token->Delim);
13947 token->Pos = 0;
13948
13949 return;
13950 }
13951
13952
13953
13954
13955 /* @section debugging *********************************************************
13956 **
13957 ** @fdata [AjPStrTok]
13958 **
13959 ** @nam4rule Trace Write internals to debug file
13960 **
13961 ** @argrule * token [const AjPStrTok] String token parser
13962 **
13963 ** @valrule * [void]
13964 **
13965 ** @fcategory misc
13966 */
13967
13968
13969
13970
13971 /* @func ajStrTokenTrace ******************************************************
13972 **
13973 ** Writes a debug trace of a string token parser object.
13974 **
13975 ** @param [r] token [const AjPStrTok] String token object
13976 ** @return [void]
13977 **
13978 ** @release 1.0.0
13979 ** @@
13980 ******************************************************************************/
13981
ajStrTokenTrace(const AjPStrTok token)13982 void ajStrTokenTrace(const AjPStrTok token)
13983 {
13984 ajDebug("ajStrTokenTrace %x\n", token);
13985
13986 if(!token)
13987 return;
13988
13989 ajDebug("... String:\n");
13990 ajStrTrace(token->String);
13991 ajDebug("... Delim:\n");
13992 ajStrTrace(token->Delim);
13993
13994 return;
13995 }
13996
13997
13998
13999
14000 /* @section parsing ***********************************************************
14001 **
14002 ** @fdata [AjPStrTok]
14003 **
14004 ** @nam4rule Next Return next token
14005 ** @nam5rule NextParse Use delimiter as a set of characters
14006 ** @nam5rule NextFind Use delimiter as a string
14007 ** @nam6rule Delimiters Also save the delimiter found in the source string
14008 ** @nam6rule NextParseNoskip Use delimiter as a string, stop at first delimiter
14009 ** @nam4rule Rest Return remainder of string
14010 ** @nam5rule RestParse Return remainder of string
14011 ** @nam4rule Step Use delimiter as a set of characters, no string returned
14012 **
14013 ** @argrule * token [AjPStrTok] String token parser
14014 ** @argrule C txtdelim [const char*] Delimiter
14015 ** @argrule S strdelim [const AjPStr] Delimiter
14016 ** @argrule Rest Pstr [AjPStr*] String result
14017 ** @argrule Next Pstr [AjPStr*] String result
14018 ** @argrule Delimiters Pdelim [AjPStr*] Delimiter(s) following the token
14019 **
14020 ** @valrule * [AjBool] True on success
14021 **
14022 ** @fcategory modify
14023 */
14024
14025
14026
14027
14028 /* @func ajStrTokenNextFind ***************************************************
14029 **
14030 ** Parses tokens from a string using a string token parser. Treats the
14031 ** whole delimiter as a single string between tokens.
14032 **
14033 ** @param [u] token [AjPStrTok] Token parser. Updated with the delimiter
14034 ** string (if any) in delim.
14035 ** @param [w] Pstr [AjPStr*] Token found
14036 **
14037 ** @return [AjBool] ajTrue if another token was found.
14038 **
14039 ** @release 4.0.0
14040 ** @@
14041 ******************************************************************************/
14042
ajStrTokenNextFind(AjPStrTok token,AjPStr * Pstr)14043 AjBool ajStrTokenNextFind(AjPStrTok token, AjPStr* Pstr)
14044 {
14045 size_t ilen;
14046 char* cp;
14047 char* cq;
14048
14049 if(!token)
14050 { /* token already cleared */
14051 ajStrAssignClear(Pstr);
14052
14053 return ajFalse;
14054 }
14055
14056 if(token->Pos >= token->String->Len)
14057 { /* all done */
14058 ajStrAssignClear(Pstr);
14059 ajStrTokenReset(token);
14060
14061 return ajFalse;
14062 }
14063
14064 cp = &token->String->Ptr[token->Pos];
14065 cq = strstr(cp, token->Delim->Ptr);
14066
14067 if(cq)
14068 {
14069 ilen = cq - cp;
14070 ajStrAssignSubS(Pstr, token->String, token->Pos,
14071 token->Pos + ilen - 1);
14072 token->Pos += ilen;
14073 token->Pos += token->Delim->Len;
14074
14075 return ajTrue;
14076 }
14077
14078 /* delimiter not found - return rest of string */
14079
14080 ilen = token->String->Len - token->Pos;
14081 ajStrAssignLenC(Pstr, cp, ilen);
14082 token->Pos += ilen;
14083
14084 return ajTrue;
14085 }
14086
14087
14088
14089
14090 /* @func ajStrTokenNextFindC **************************************************
14091 **
14092 ** Parses tokens from a string using a string token parser. Treats the
14093 ** whole delimiter as a single string between tokens.
14094 **
14095 ** @param [u] token [AjPStrTok] Token parser. Updated with the delimiter
14096 ** string in delim.
14097 ** @param [r] txtdelim [const char*] Delimiter string.
14098 ** @param [w] Pstr [AjPStr*] Token found
14099 **
14100 ** @return [AjBool] ajTrue if another token was found.
14101 **
14102 ** @release 4.0.0
14103 ** @@
14104 ******************************************************************************/
14105
ajStrTokenNextFindC(AjPStrTok token,const char * txtdelim,AjPStr * Pstr)14106 AjBool ajStrTokenNextFindC(AjPStrTok token, const char* txtdelim,
14107 AjPStr* Pstr)
14108 {
14109 ajStrAssignC(&token->Delim, txtdelim);
14110
14111 return ajStrTokenNextFind(token, Pstr);
14112 }
14113
14114
14115
14116
14117 /* @func ajStrTokenNextParse **************************************************
14118 **
14119 ** Parses tokens from a string using a string token parser. Uses any
14120 ** character defined in the string token parsing object delimiter
14121 ** character set as a delimiter.
14122 **
14123 ** The test uses the C function 'strcspn'.
14124 **
14125 ** @param [u] token [AjPStrTok] String token parsing object.
14126 ** @param [w] Pstr [AjPStr*] Next token returned, may be empty if the
14127 ** delimiter has changed.
14128 ** @return [AjBool] True if successfully parsed.
14129 ** False (and string set to empty) if there is nothing
14130 ** more to parse.
14131 **
14132 ** @release 4.0.0
14133 ** @@
14134 ******************************************************************************/
14135
ajStrTokenNextParse(AjPStrTok token,AjPStr * Pstr)14136 AjBool ajStrTokenNextParse(AjPStrTok token, AjPStr* Pstr)
14137 {
14138 size_t ilen;
14139 char* cp;
14140
14141 if(!token)
14142 { /* token already cleared */
14143 ajStrAssignClear(Pstr);
14144
14145 return ajFalse;
14146 }
14147
14148 if(token->Pos >= token->String->Len)
14149 { /* all done */
14150 ajStrAssignClear(Pstr);
14151 ajStrTokenReset(token);
14152
14153 return ajFalse;
14154 }
14155
14156 cp = &token->String->Ptr[token->Pos];
14157 ilen = strcspn(cp, token->Delim->Ptr);
14158
14159 if(ilen)
14160 {
14161 ajStrAssignSubS(Pstr, token->String,
14162 token->Pos, token->Pos + ilen - 1);
14163 }
14164 else
14165 {
14166 ajStrAssignClear(Pstr);
14167 }
14168
14169 token->Pos += ilen;
14170 token->Pos += strspn(&token->String->Ptr[token->Pos], token->Delim->Ptr);
14171
14172 return ajTrue;
14173 }
14174
14175
14176
14177
14178 /* @func ajStrTokenNextParseC *************************************************
14179 **
14180 ** Parses tokens from a string using a string token parser. Uses any
14181 ** character defined in the delimiter character set as a
14182 ** delimiter.
14183 **
14184 ** Returns the next token parsed from a string token parsing object
14185 **
14186 ** Note: This can return "true" but an empty string in cases where the
14187 ** delimiter has changed since the previous call.
14188 **
14189 ** The test uses the C function 'strcspn'.
14190 **
14191 ** @param [u] token [AjPStrTok] String token parsing object.
14192 ** @param [r] txtdelim [const char*] Delimiter character set.
14193 ** @param [w] Pstr [AjPStr*] Next token returned, may be empty if the
14194 ** delimiter has changed.
14195 ** @return [AjBool] True if successfully parsed.
14196 ** False (and string set to empty) if there is nothing
14197 ** more to parse.
14198 **
14199 ** @release 4.0.0
14200 ** @@
14201 ******************************************************************************/
14202
ajStrTokenNextParseC(AjPStrTok token,const char * txtdelim,AjPStr * Pstr)14203 AjBool ajStrTokenNextParseC(AjPStrTok token, const char* txtdelim,
14204 AjPStr* Pstr)
14205 {
14206 if(!token)
14207 {
14208 ajStrAssignClear(Pstr);
14209
14210 return ajFalse;
14211 }
14212
14213 ajStrAssignC(&(token)->Delim, txtdelim);
14214
14215 return ajStrTokenNextParse(token, Pstr);
14216 }
14217
14218
14219
14220
14221 /* @func ajStrTokenNextParseS *************************************************
14222 **
14223 ** Parses tokens from a string using a string token parser. Uses any
14224 ** character defined in the delimiter character set as a
14225 ** delimiter.
14226 **
14227 ** Note: This can return "true" but an empty string in cases where the
14228 ** delimiter has changed since the previous call.
14229 **
14230 ** The test uses the C function 'strcspn'.
14231 **
14232 ** @param [u] token [AjPStrTok] String token parsing object.
14233 ** @param [r] strdelim [const AjPStr] Delimiter character set.
14234 ** @param [w] Pstr [AjPStr*] Next token returned, may be empty if the
14235 ** delimiter has changed.
14236 ** @return [AjBool] True if successfully parsed.
14237 ** False (and string set to empty) if there is nothing
14238 ** more to parse.
14239 **
14240 ** @release 4.0.0
14241 ** @@
14242 ******************************************************************************/
14243
ajStrTokenNextParseS(AjPStrTok token,const AjPStr strdelim,AjPStr * Pstr)14244 AjBool ajStrTokenNextParseS(AjPStrTok token, const AjPStr strdelim,
14245 AjPStr* Pstr)
14246 {
14247 if(!token)
14248 {
14249 ajStrAssignClear(Pstr);
14250
14251 return ajFalse;
14252 }
14253
14254 ajStrAssignS(&(token)->Delim, strdelim);
14255
14256 return ajStrTokenNextParse(token, Pstr);
14257 }
14258
14259
14260
14261
14262 /* @func ajStrTokenNextParseDelimiters ****************************************
14263 **
14264 ** Parses tokens from a string using a string token parser. Uses any
14265 ** character defined in the string token parsing object delimiter
14266 ** character set as a delimiter.
14267 **
14268 ** The test uses the C function 'strcspn'.
14269 **
14270 ** @param [u] token [AjPStrTok] String token parsing object.
14271 ** @param [w] Pstr [AjPStr*] Next token returned, may be empty if the
14272 ** delimiter has changed.
14273 ** @param [w] Pdelim [AjPStr*] Delimiter(s) following the token.
14274 ** @return [AjBool] True if successfully parsed.
14275 ** False (and string set to empty) if there is nothing
14276 ** more to parse.
14277 **
14278 ** @release 6.4.0
14279 ** @@
14280 ******************************************************************************/
14281
ajStrTokenNextParseDelimiters(AjPStrTok token,AjPStr * Pstr,AjPStr * Pdelim)14282 AjBool ajStrTokenNextParseDelimiters(AjPStrTok token, AjPStr* Pstr,
14283 AjPStr* Pdelim)
14284 {
14285 size_t ilen;
14286 char* cp;
14287
14288 if(!token)
14289 { /* token already cleared */
14290 ajStrAssignClear(Pstr);
14291
14292 return ajFalse;
14293 }
14294
14295 if(token->Pos >= token->String->Len)
14296 { /* all done */
14297 ajStrAssignClear(Pstr);
14298 ajStrTokenReset(token);
14299
14300 return ajFalse;
14301 }
14302
14303 cp = &token->String->Ptr[token->Pos];
14304 ilen = strcspn(cp, token->Delim->Ptr);
14305
14306 if(ilen)
14307 {
14308 ajStrAssignSubS(Pstr, token->String,
14309 token->Pos, token->Pos + ilen - 1);
14310 }
14311 else
14312 {
14313 ajStrAssignClear(Pstr);
14314 }
14315
14316 token->Pos += ilen;
14317 ilen= strspn(&token->String->Ptr[token->Pos], token->Delim->Ptr);
14318 if(ilen)
14319 {
14320 ajStrAssignSubS(Pdelim, token->String,
14321 token->Pos, token->Pos + ilen - 1);
14322 }
14323 else
14324 {
14325 ajStrAssignClear(Pdelim);
14326 }
14327
14328 token->Pos +=ilen;
14329
14330 return ajTrue;
14331 }
14332
14333
14334
14335
14336 /* @func ajStrTokenNextParseNoskip ********************************************
14337 **
14338 ** Parses tokens from a string using a string token parser. Uses any
14339 ** character defined in the string token parsing object's delimiter
14340 ** character set as a delimiter.
14341 **
14342 ** The test uses the C function 'strcspn'.
14343 **
14344 ** @param [u] token [AjPStrTok] String token parsing object.
14345 ** @param [w] Pstr [AjPStr*] Next token returned, may be empty if the
14346 ** delimiter has changed or if next character
14347 ** was also a delimiter
14348 ** @return [AjBool] True if successfully parsed.
14349 ** False (and string set to empty) if there is nothing
14350 ** more to parse.
14351 **
14352 ** @release 6.2.0
14353 ** @@
14354 ******************************************************************************/
14355
ajStrTokenNextParseNoskip(AjPStrTok token,AjPStr * Pstr)14356 AjBool ajStrTokenNextParseNoskip(AjPStrTok token, AjPStr* Pstr)
14357 {
14358 size_t ilen;
14359 char* cp;
14360
14361 if(!token)
14362 { /* token already cleared */
14363 ajStrAssignClear(Pstr);
14364
14365 return ajFalse;
14366 }
14367
14368 if(token->Pos >= token->String->Len)
14369 { /* all done */
14370 ajStrAssignClear(Pstr);
14371 ajStrTokenReset(token);
14372
14373 return ajFalse;
14374 }
14375
14376 cp = &token->String->Ptr[token->Pos];
14377 ilen = strcspn(cp, token->Delim->Ptr);
14378
14379 if(ilen)
14380 {
14381 ajStrAssignSubS(Pstr, token->String,
14382 token->Pos, token->Pos + ilen - 1);
14383 }
14384 else
14385 {
14386 ajStrAssignClear(Pstr);
14387 }
14388
14389 token->Pos += ilen + 1;
14390
14391 return ajTrue;
14392 }
14393
14394
14395
14396
14397 /* @func ajStrTokenRestParse **************************************************
14398 **
14399 ** Returns the remainder of a string that has been partially parsed using a
14400 ** string token parser.
14401 **
14402 ** @param [u] token [AjPStrTok] String token parsing object.
14403 ** @param [w] Pstr [AjPStr*] Remainder of string
14404 ** @return [AjBool] True if successfully parsed.
14405 ** False (and string set to empty) if there is nothing
14406 ** more to parse.
14407 **
14408 ** @release 4.0.0
14409 ** @@
14410 ******************************************************************************/
14411
ajStrTokenRestParse(AjPStrTok token,AjPStr * Pstr)14412 AjBool ajStrTokenRestParse(AjPStrTok token, AjPStr* Pstr)
14413 {
14414 if(!token)
14415 { /* token already cleared */
14416 ajStrAssignClear(Pstr);
14417
14418 return ajFalse;
14419 }
14420
14421 if(token->Pos >= token->String->Len)
14422 { /* all done */
14423 ajStrAssignClear(Pstr);
14424 ajStrTokenReset(token);
14425
14426 return ajFalse;
14427 }
14428
14429 if(token->Pos < token->String->Len)
14430 ajStrAssignSubS(Pstr, token->String,
14431 token->Pos, token->String->Len);
14432 else
14433 ajStrAssignClear(Pstr);
14434
14435 token->Pos = token->String->Len;
14436
14437 return ajTrue;
14438 }
14439
14440
14441
14442
14443 /* @func ajStrTokenStep *******************************************************
14444 **
14445 ** Steps to next token from a string using a string token parser. Uses any
14446 ** character defined in the string token parsing object delimiter
14447 ** character set as a delimiter.
14448 **
14449 ** The test uses the C function 'strcspn'.
14450 **
14451 ** @param [u] token [AjPStrTok] String token parsing object.
14452 ** @return [AjBool] True if successfully parsed.
14453 ** False (and token parser deleted) if there is nothing
14454 ** more to parse.
14455 **
14456 ** @release 6.6.0
14457 ** @@
14458 ******************************************************************************/
14459
ajStrTokenStep(AjPStrTok token)14460 AjBool ajStrTokenStep(AjPStrTok token)
14461 {
14462 size_t ilen;
14463 char* cp;
14464
14465 if(!token)
14466 return ajFalse;
14467
14468 if(token->Pos >= token->String->Len)
14469 { /* all done */
14470 ajStrTokenReset(token);
14471
14472 return ajFalse;
14473 }
14474
14475 cp = &token->String->Ptr[token->Pos];
14476 ilen = strcspn(cp, token->Delim->Ptr);
14477
14478 token->Pos += ilen;
14479 token->Pos += strspn(&token->String->Ptr[token->Pos], token->Delim->Ptr);
14480
14481 return ajTrue;
14482 }
14483
14484
14485
14486
14487 /* @func ajStrTokenStepC ******************************************************
14488 **
14489 **Steps to next token from a string using a string token parser. Uses any
14490 ** character defined in the delimiter character set as a
14491 ** delimiter.
14492 **
14493 ** Note: This can return "true" without moving in cases where the
14494 ** delimiter has changed since the previous call.
14495 **
14496 ** The test uses the C function 'strcspn'.
14497 **
14498 ** @param [u] token [AjPStrTok] String token parsing object.
14499 ** @param [r] txtdelim [const char*] Delimiter character set.
14500 ** @return [AjBool] True if successfully parsed.
14501 ** False (and string set to empty) if there is nothing
14502 ** more to parse.
14503 **
14504 ** @release 6.6.0
14505 ** @@
14506 ******************************************************************************/
14507
ajStrTokenStepC(AjPStrTok token,const char * txtdelim)14508 AjBool ajStrTokenStepC(AjPStrTok token, const char* txtdelim)
14509 {
14510 if(!token)
14511 return ajFalse;
14512
14513 ajStrAssignC(&token->Delim, txtdelim);
14514
14515 return ajStrTokenStep(token);
14516 }
14517
14518
14519
14520
14521 /* @func ajStrTokenStepS ******************************************************
14522 **
14523 ** Parses tokens from a string using a string token parser. Uses any
14524 ** character defined in the delimiter character set as a
14525 ** delimiter.
14526 **
14527 ** Note: This can return "true" but an empty string in cases where the
14528 ** delimiter has changed since the previous call.
14529 **
14530 ** The test uses the C function 'strcspn'.
14531 **
14532 ** @param [u] token [AjPStrTok] String token parsing object.
14533 ** @param [r] strdelim [const AjPStr] Delimiter character set.
14534 ** @return [AjBool] True if successfully parsed.
14535 ** False (and string set to empty) if there is nothing
14536 ** more to parse.
14537 **
14538 ** @release 6.6.0
14539 ** @@
14540 ******************************************************************************/
14541
ajStrTokenStepS(AjPStrTok token,const AjPStr strdelim)14542 AjBool ajStrTokenStepS(AjPStrTok token, const AjPStr strdelim)
14543 {
14544 if(!token)
14545 return ajFalse;
14546
14547 ajStrAssignS(&token->Delim, strdelim);
14548
14549 return ajStrTokenStep(token);
14550 }
14551
14552
14553
14554
14555 #ifdef AJ_COMPILE_DEPRECATED_BOOK
14556 #endif
14557
14558
14559
14560
14561 #ifdef AJ_COMPILE_DEPRECATED
14562 /* @obsolete ajCharNew
14563 ** @rename ajCharNewS
14564 */
14565
ajCharNew(const AjPStr str)14566 __deprecated char *ajCharNew(const AjPStr str)
14567 {
14568 return ajCharNewS(str);
14569 }
14570
14571
14572
14573
14574 /* @obsolete ajCharNewL
14575 ** @rename ajCharNewRes
14576 */
14577
ajCharNewL(size_t size)14578 __deprecated char *ajCharNewL(size_t size)
14579 {
14580 return ajCharNewRes(size);
14581 }
14582
14583
14584
14585
14586 /* @obsolete ajCharNewLS
14587 ** @replace ajStrNewResS (1,2/2,1)
14588 */
14589
ajCharNewLS(size_t size,const AjPStr thys)14590 __deprecated char *ajCharNewLS(size_t size, const AjPStr thys)
14591 {
14592 return ajCharNewResS(thys, size);
14593 }
14594
14595
14596
14597
14598 /* @obsolete ajCharFree
14599 ** @rename ajCharDel
14600 */
14601
ajCharFree(char ** txt)14602 __deprecated void ajCharFree(char** txt)
14603 {
14604 ajCharDel(txt);
14605 }
14606
14607
14608
14609
14610 /* @obsolete ajCharToLower
14611 ** @rename ajCharFmtLower
14612 */
14613
ajCharToLower(char * txt)14614 __deprecated void ajCharToLower(char* txt)
14615 {
14616 ajCharFmtLower(txt);
14617 }
14618
14619
14620
14621
14622 /* @obsolete ajCharToUpper
14623 ** @rename ajCharFmtUpper
14624 */
14625
ajCharToUpper(char * txt)14626 __deprecated void ajCharToUpper(char* txt)
14627 {
14628 ajCharFmtUpper(txt);
14629 }
14630
14631
14632
14633
14634 /* @obsolete ajStrMatchCC
14635 ** @rename ajCharMatchC
14636 */
14637
ajStrMatchCC(const char * thys,const char * text)14638 __deprecated AjBool ajStrMatchCC(const char* thys, const char* text)
14639 {
14640 return ajCharMatchC(thys, text);
14641 }
14642
14643
14644
14645
14646 /* @obsolete ajStrMatchCaseCC
14647 ** @rename ajCharMatchCaseC
14648 */
14649
ajStrMatchCaseCC(const char * thys,const char * text)14650 __deprecated AjBool ajStrMatchCaseCC(const char* thys, const char* text)
14651 {
14652 return ajCharMatchCaseC(thys, text);
14653 }
14654
14655
14656
14657
14658 /* @obsolete ajStrMatchWildCC
14659 ** @rename ajCharMatchWildC
14660 */
14661
ajStrMatchWildCC(const char * str,const char * text)14662 __deprecated AjBool ajStrMatchWildCC(const char* str, const char* text)
14663 {
14664 return ajCharMatchWildC(str, text);
14665 }
14666
14667
14668
14669
14670 /* @obsolete ajStrMatchWildCO
14671 ** @rename ajCharMatchWildS
14672 */
14673
ajStrMatchWildCO(const char * str,const AjPStr wild)14674 __deprecated AjBool ajStrMatchWildCO(const char* str, const AjPStr wild)
14675 {
14676 return ajCharMatchWildS(str, wild);
14677 }
14678
14679
14680
14681
14682 /* @obsolete ajStrMatchWordCC
14683 ** @rename ajCharMatchWildWordS
14684 */
14685
ajStrMatchWordCC(const char * str,const char * txt)14686 __deprecated AjBool ajStrMatchWordCC (const char* str, const char* txt)
14687 {
14688 return ajCharMatchWildWordC(str, txt);
14689 }
14690
14691
14692
14693
14694 /* @obsolete ajStrPrefixCC
14695 ** @rename ajCharPrefixC
14696 */
14697
ajStrPrefixCC(const char * str,const char * pref)14698 __deprecated AjBool ajStrPrefixCC(const char* str, const char* pref)
14699 {
14700 return ajCharPrefixC(str, pref);
14701 }
14702
14703
14704
14705
14706 /* @obsolete ajStrPrefixCO
14707 ** @rename ajCharPrefixS
14708 */
14709
ajStrPrefixCO(const char * str,const AjPStr thys)14710 __deprecated AjBool ajStrPrefixCO(const char* str, const AjPStr thys)
14711 {
14712 return ajCharPrefixS(str, thys);
14713 }
14714
14715
14716
14717
14718 /* @obsolete ajStrPrefixCaseCC
14719 ** @rename ajCharPrefixCaseC
14720 */
14721
ajStrPrefixCaseCC(const char * thys,const char * pref)14722 __deprecated AjBool ajStrPrefixCaseCC(const char* thys, const char* pref)
14723 {
14724 return ajCharPrefixCaseC(thys, pref);
14725 }
14726
14727
14728
14729
14730 /* @obsolete ajStrPrefixCaseCO
14731 ** @rename ajCharPrefixCaseS
14732 */
14733
ajStrPrefixCaseCO(const char * thys,const AjPStr pref)14734 __deprecated AjBool ajStrPrefixCaseCO(const char* thys, const AjPStr pref)
14735 {
14736 return ajCharPrefixCaseS(thys, pref);
14737 }
14738
14739
14740
14741
14742 /* @obsolete ajStrSuffixCC
14743 ** @rename ajCharSuffixC
14744 */
14745
ajStrSuffixCC(const char * str,const char * suff)14746 __deprecated AjBool ajStrSuffixCC(const char* str, const char* suff)
14747 {
14748 return ajCharSuffixC(str, suff);
14749 }
14750
14751
14752
14753
14754 /* @obsolete ajStrSuffixCO
14755 ** @rename ajCharSuffixS
14756 */
14757
ajStrSuffixCO(const char * txt,const AjPStr suff)14758 __deprecated AjBool ajStrSuffixCO(const char* txt, const AjPStr suff)
14759 {
14760 return ajCharSuffixS(txt, suff);
14761 }
14762
14763
14764
14765
14766 /* @obsolete ajStrCmpCaseCC
14767 ** @rename ajCharCmpCase
14768 */
14769
ajStrCmpCaseCC(const char * str1,const char * str2)14770 __deprecated int ajStrCmpCaseCC(const char* str1, const char* str2)
14771 {
14772 return ajCharCmpCase (str1, str2);
14773 }
14774
14775
14776
14777
14778 /* @obsolete ajStrNCmpCaseCC
14779 ** @rename ajCharCmpCaseLen
14780 */
14781
ajStrNCmpCaseCC(const char * str1,const char * str2,ajint len)14782 __deprecated int ajStrNCmpCaseCC(const char* str1, const char* str2, ajint len)
14783 {
14784 return ajCharCmpCaseLen(str1, str2, len);
14785 }
14786
14787
14788
14789
14790 /* @obsolete ajStrCmpWildCC
14791 ** @rename ajCharCmpWild
14792 */
14793
ajStrCmpWildCC(const char * str,const char * text)14794 __deprecated ajint ajStrCmpWildCC(const char* str, const char* text)
14795 {
14796 return ajCharCmpWild (str, text);
14797 }
14798
14799
14800
14801
14802 /* @obsolete ajStrTokCC
14803 ** @rename ajCharParseC
14804 */
14805
ajStrTokCC(const char * txt,const char * delim)14806 __deprecated const AjPStr ajStrTokCC (const char* txt, const char* delim)
14807 {
14808 return ajCharParseC(txt, delim);
14809 }
14810
14811
14812
14813
14814 /* @obsolete ajStrDup
14815 ** @rename ajStrNewRef
14816 */
14817
ajStrDup(AjPStr thys)14818 __deprecated AjPStr ajStrDup(AjPStr thys)
14819 {
14820 return ajStrNewRef(thys);
14821 }
14822
14823
14824
14825
14826 /* @obsolete ajStrNewL
14827 ** @rename ajStrNewRes
14828 */
14829
ajStrNewL(size_t size)14830 __deprecated AjPStr ajStrNewL(size_t size)
14831 {
14832 return ajStrNewRes(size);
14833 }
14834
14835
14836
14837
14838 /* @obsolete ajStrNewCL
14839 ** @rename ajStrNewResC
14840 */
14841
ajStrNewCL(const char * txt,size_t size)14842 __deprecated AjPStr ajStrNewCL(const char* txt, size_t size)
14843 {
14844 return ajStrNewResC(txt, size);
14845 }
14846
14847
14848
14849
14850 /* @obsolete ajStrNewCIL
14851 ** @rename ajStrNewResLenC
14852 */
14853
ajStrNewCIL(const char * txt,ajint len,size_t size)14854 __deprecated AjPStr ajStrNewCIL(const char* txt, ajint len, size_t size)
14855 {
14856 return ajStrNewResLenC (txt, size, len);
14857 }
14858
14859
14860
14861
14862 /* @obsolete ajStrDelReuse
14863 ** @rename ajStrDelStatic
14864 */
14865
ajStrDelReuse(AjPStr * pthis)14866 __deprecated AjBool ajStrDelReuse(AjPStr* pthis)
14867 {
14868 ajStrDelStatic(pthis);
14869
14870 if(*pthis)
14871 return ajTrue;
14872
14873 return ajFalse;
14874 }
14875
14876
14877
14878
14879 /* @obsolete ajStrAssC
14880 ** @rename ajStrAssignC
14881 */
14882
ajStrAssC(AjPStr * pthis,const char * text)14883 __deprecated AjBool ajStrAssC(AjPStr* pthis, const char* text)
14884 {
14885 return ajStrAssignC (pthis, text);
14886 }
14887
14888
14889
14890
14891 /* @obsolete ajStrAssK
14892 ** @rename ajStrAssignK
14893 */
14894
ajStrAssK(AjPStr * pthis,const char text)14895 __deprecated AjBool ajStrAssK(AjPStr* pthis, const char text)
14896 {
14897 return ajStrAssignK(pthis, text);
14898 }
14899
14900
14901
14902
14903 /* @obsolete ajStrAssS
14904 ** @rename ajStrAssignS
14905 */
14906
ajStrAssS(AjPStr * pthis,const AjPStr str)14907 __deprecated AjBool ajStrAssS(AjPStr* pthis, const AjPStr str)
14908 {
14909 return ajStrAssignS(pthis, str);
14910 }
14911
14912
14913
14914
14915 /* @obsolete ajStrAssI
14916 ** @replace ajStrAssignS (1,2,3/1,2)
14917 */
14918
ajStrAssI(AjPStr * Pstr,const AjPStr str,size_t i)14919 __deprecated AjBool ajStrAssI(AjPStr* Pstr, const AjPStr str, size_t i)
14920 {
14921 (void) i;
14922
14923 return ajStrAssignS(Pstr, str);
14924 }
14925
14926
14927
14928
14929 /* @obsolete ajStrSetC
14930 ** @rename ajStrAssignEmptyC
14931 */
14932
ajStrSetC(AjPStr * pthis,const char * str)14933 __deprecated AjBool ajStrSetC(AjPStr* pthis, const char* str)
14934 {
14935 return ajStrAssignEmptyC(pthis, str);
14936 }
14937
14938
14939
14940
14941 /* @obsolete ajStrSet
14942 ** @rename ajStrAssignEmptyS
14943 */
14944
ajStrSet(AjPStr * pthis,const AjPStr str)14945 __deprecated AjBool ajStrSet(AjPStr* pthis, const AjPStr str)
14946 {
14947 AjBool ret = ajFalse;
14948 ajDebug("ajStrSet pthis:%x '%S' str:%x '%S'\n",
14949 *pthis, *pthis, str, str);
14950 ret = ajStrAssignEmptyS(pthis, str);
14951 ajDebug("ajStrSet ret:%B pthis:%x '%S' str:%x '%S'\n",
14952 ret, *pthis, *pthis, str, str);
14953
14954 return ret;
14955 }
14956
14957
14958
14959
14960 /* @obsolete ajStrAssCI
14961 ** @rename ajStrAssignLenC
14962 */
14963
ajStrAssCI(AjPStr * pthis,const char * txt,size_t ilen)14964 __deprecated AjBool ajStrAssCI(AjPStr* pthis, const char* txt, size_t ilen)
14965 {
14966 return ajStrAssignLenC(pthis, txt, ilen);
14967 }
14968
14969
14970
14971
14972 /* @obsolete ajStrCopy
14973 ** @rename ajStrAssignRef
14974 */
14975
ajStrCopy(AjPStr * pthis,AjPStr str)14976 __deprecated AjBool ajStrCopy(AjPStr* pthis, AjPStr str)
14977 {
14978 return ajStrAssignRef(pthis, str);
14979 }
14980
14981
14982
14983
14984 /* @obsolete ajStrAssCL
14985 ** @replace ajStrAssignResC (1,2,3/1,3,2)
14986 */
14987
ajStrAssCL(AjPStr * pthis,const char * txt,size_t i)14988 __deprecated AjBool ajStrAssCL(AjPStr* pthis, const char* txt, size_t i)
14989 {
14990 return ajStrAssignResC(pthis, i, txt);
14991 }
14992
14993
14994
14995
14996 /* @obsolete ajStrAssL
14997 ** @replace ajStrAssignResS (1,2,3/1,3,2)
14998 */
14999
ajStrAssL(AjPStr * pthis,const AjPStr str,size_t i)15000 __deprecated AjBool ajStrAssL(AjPStr* pthis, const AjPStr str, size_t i)
15001 {
15002 return ajStrAssignResS(pthis, i, str);
15003 }
15004
15005
15006
15007
15008 /* @obsolete ajStrAssSubC
15009 ** @rename ajStrAssignSubC
15010 */
15011
ajStrAssSubC(AjPStr * pthis,const char * txt,ajint begin,ajint end)15012 __deprecated AjBool ajStrAssSubC(AjPStr* pthis, const char* txt,
15013 ajint begin, ajint end)
15014 {
15015 return ajStrAssignSubC(pthis, txt, begin, end);
15016 }
15017
15018
15019
15020
15021 /* @obsolete ajStrAssSub
15022 ** @rename ajStrAssignSubS
15023 */
ajStrAssSub(AjPStr * pthis,const AjPStr src,ajint beginpos,ajint endpos)15024 __deprecated AjBool ajStrAssSub(AjPStr* pthis, const AjPStr src,
15025 ajint beginpos, ajint endpos)
15026 {
15027 return ajStrAssignSubS(pthis, src, beginpos, endpos);
15028 }
15029
15030
15031
15032
15033 /* @obsolete ajStrAppC
15034 ** @rename ajStrAppendC
15035 */
15036
ajStrAppC(AjPStr * pthis,const char * txt)15037 __deprecated AjBool ajStrAppC(AjPStr* pthis, const char* txt)
15038 {
15039 return ajStrAppendC(pthis, txt);
15040 }
15041
15042
15043
15044
15045 /* @obsolete ajStrAppK
15046 ** @rename ajStrAppendK
15047 */
15048
ajStrAppK(AjPStr * pthis,const char chr)15049 __deprecated AjBool ajStrAppK(AjPStr* pthis, const char chr)
15050 {
15051 return ajStrAppendK(pthis, chr);
15052 }
15053
15054
15055
15056
15057 /* @obsolete ajStrApp
15058 ** @rename ajStrAppendS
15059 */
15060
ajStrApp(AjPStr * pthis,const AjPStr src)15061 __deprecated AjBool ajStrApp(AjPStr* pthis, const AjPStr src)
15062 {
15063 return ajStrAppendS(pthis, src);
15064 }
15065
15066
15067
15068
15069 /* @obsolete ajStrAppKI
15070 ** @rename ajStrAppendCountK
15071 */
15072
ajStrAppKI(AjPStr * pthis,const char chr,ajint number)15073 __deprecated AjBool ajStrAppKI(AjPStr* pthis, const char chr, ajint number)
15074 {
15075 return ajStrAppendCountK(pthis, chr, number);
15076 }
15077
15078
15079
15080
15081 /* @obsolete ajStrAppCI
15082 ** @rename ajStrAppendLenC
15083 */
15084
ajStrAppCI(AjPStr * pthis,const char * txt,size_t i)15085 __deprecated AjBool ajStrAppCI(AjPStr* pthis, const char* txt, size_t i)
15086 {
15087 return ajStrAppendLenC(pthis, txt, i);
15088 }
15089
15090
15091
15092
15093 /* @obsolete ajStrAppSub
15094 ** @rename ajStrAppendSubS
15095 */
15096
ajStrAppSub(AjPStr * pthis,const AjPStr src,ajint begin,ajint end)15097 __deprecated AjBool ajStrAppSub(AjPStr* pthis, const AjPStr src,
15098 ajint begin, ajint end)
15099 {
15100 return ajStrAppendSubS(pthis, src, begin, end);
15101 }
15102
15103
15104
15105
15106 /* @obsolete ajStrInsert
15107 ** @rename ajStrInsertS
15108 */
15109
ajStrInsert(AjPStr * Pstr,ajint pos,const AjPStr str)15110 __deprecated AjBool ajStrInsert(AjPStr* Pstr, ajint pos, const AjPStr str )
15111 {
15112 return ajStrInsertS(Pstr, pos, str);
15113 }
15114
15115
15116
15117
15118 /* @obsolete ajStrMask
15119 ** @rename ajStrMaskRange
15120 */
15121
ajStrMask(AjPStr * Pstr,ajint pos1,ajint pos2,char maskchr)15122 __deprecated AjBool ajStrMask(AjPStr* Pstr, ajint pos1, ajint pos2,
15123 char maskchr)
15124 {
15125 return ajStrMaskRange(Pstr, pos1, pos2, maskchr);
15126 }
15127
15128
15129
15130
15131 /* @obsolete ajStrReplaceS
15132 ** @rename ajStrPasteS
15133 */
15134
ajStrReplaceS(AjPStr * pthis,ajint begin,const AjPStr overwrite)15135 __deprecated AjBool ajStrReplaceS( AjPStr* pthis, ajint begin,
15136 const AjPStr overwrite)
15137 {
15138 return ajStrPasteS(pthis, begin, overwrite);
15139 }
15140
15141
15142
15143
15144 /* @obsolete ajStrReplaceK
15145 ** @rename ajStrPasteCountK
15146 */
15147
ajStrReplaceK(AjPStr * pthis,ajint ibegin,char overwrite,ajint ilen)15148 __deprecated AjBool ajStrReplaceK( AjPStr* pthis, ajint ibegin,
15149 char overwrite, ajint ilen)
15150 {
15151 return ajStrPasteCountK(pthis, ibegin, overwrite, ilen);
15152 }
15153
15154
15155
15156
15157 /* @obsolete ajStrReplaceC
15158 ** @rename ajStrPasteMaxC
15159 */
15160
ajStrReplaceC(AjPStr * pthis,ajint begin,const char * overwrite,ajint ilen)15161 __deprecated AjBool ajStrReplaceC( AjPStr* pthis, ajint begin,
15162 const char* overwrite, ajint ilen)
15163 {
15164 return ajStrPasteMaxC(pthis, begin, overwrite, ilen);
15165 }
15166
15167
15168
15169
15170 /* @obsolete ajStrReplace
15171 ** @rename ajStrPasteMaxS
15172 */
ajStrReplace(AjPStr * pthis,ajint begin,const AjPStr overwrite,ajint ilen)15173 __deprecated AjBool ajStrReplace( AjPStr* pthis, ajint begin,
15174 const AjPStr overwrite, ajint ilen)
15175 {
15176 return ajStrPasteMaxS(pthis, begin, overwrite, ilen);
15177 }
15178
15179
15180
15181
15182 /* @obsolete ajStrUncomment
15183 ** @rename ajStrCutComments
15184 */
15185
ajStrUncomment(AjPStr * text)15186 __deprecated AjBool ajStrUncomment(AjPStr* text)
15187 {
15188 return ajStrCutComments(text);
15189 }
15190
15191
15192
15193
15194 /* @obsolete ajStrUncommentStart
15195 ** @rename ajStrCutCommentsStart
15196 */
15197
ajStrUncommentStart(AjPStr * text)15198 __deprecated AjBool ajStrUncommentStart(AjPStr* text)
15199 {
15200 return ajStrCutCommentsStart(text);
15201 }
15202
15203
15204
15205
15206 /* @obsolete ajStrTrim
15207 ** @replace ajStrCutStart (1,+/1,2)
15208 ** @replace ajStrCutEnd (1,-/1,-2)
15209 */
15210
ajStrTrim(AjPStr * pthis,ajint num)15211 __deprecated AjBool ajStrTrim(AjPStr* pthis, ajint num)
15212 {
15213 AjBool ret;
15214
15215 if(num >= 0)
15216 ret = ajStrCutStart(pthis, num);
15217 else
15218 ret = ajStrCutEnd(pthis, -num);
15219
15220 return ret;
15221 }
15222
15223
15224
15225
15226 /* @obsolete ajStrCut
15227 ** @rename ajStrCutRange
15228 */
15229
ajStrCut(AjPStr * pthis,ajint begin,ajint end)15230 __deprecated AjBool ajStrCut(AjPStr* pthis, ajint begin, ajint end)
15231 {
15232 return ajStrCutRange(pthis, begin, end);
15233 }
15234
15235
15236
15237
15238 /* @obsolete ajStrSub
15239 ** @rename ajStrKeepRange
15240 */
15241
ajStrSub(AjPStr * pthis,ajint begin,ajint end)15242 __deprecated AjBool ajStrSub(AjPStr* pthis, ajint begin, ajint end)
15243 {
15244 return ajStrKeepRange(pthis, begin, end);
15245 }
15246
15247
15248
15249
15250 /* @obsolete ajStrKeepC
15251 ** @rename ajStrKeepSetC
15252 */
15253
ajStrKeepC(AjPStr * s,const char * charset)15254 __deprecated AjBool ajStrKeepC(AjPStr* s, const char* charset)
15255 {
15256 return ajStrKeepSetC (s, charset);
15257 }
15258
15259
15260
15261
15262 /* @obsolete ajStrKeepAlphaC
15263 ** @rename ajStrKeepSetAlphaC
15264 */
15265
ajStrKeepAlphaC(AjPStr * s,const char * charset)15266 __deprecated AjBool ajStrKeepAlphaC(AjPStr* s, const char* charset)
15267 {
15268 return ajStrKeepSetAlphaC(s, charset);
15269 }
15270
15271
15272
15273
15274 /* @obsolete ajStrDegap
15275 ** @rename ajStrRemoveGap
15276 */
15277
ajStrDegap(AjPStr * thys)15278 __deprecated void ajStrDegap(AjPStr* thys)
15279 {
15280 ajStrRemoveGap(thys);
15281 }
15282
15283
15284
15285
15286 /* @obsolete ajStrRemoveNewline
15287 ** @rename ajStrRemoveLastNewline
15288 */
15289
ajStrRemoveNewline(AjPStr * thys)15290 __deprecated void ajStrRemoveNewline(AjPStr* thys)
15291 {
15292 ajStrRemoveLastNewline(thys);
15293 }
15294
15295
15296
15297
15298 /* @obsolete ajStrRemoveCharsC
15299 ** @rename ajStrRemoveSetC
15300 */
15301
ajStrRemoveCharsC(AjPStr * pthis,const char * strng)15302 __deprecated void ajStrRemoveCharsC(AjPStr* pthis, const char *strng)
15303 {
15304 ajStrRemoveSetC(pthis, strng);
15305 }
15306
15307
15308
15309
15310 /* @obsolete ajStrCleanWhite
15311 ** @rename ajStrRemoveWhite
15312 */
15313
ajStrCleanWhite(AjPStr * s)15314 __deprecated AjBool ajStrCleanWhite(AjPStr* s)
15315 {
15316 return ajStrRemoveWhite(s);
15317 }
15318
15319
15320
15321
15322 /* @obsolete ajStrClean
15323 ** @rename ajStrRemoveWhiteExcess
15324 */
15325
ajStrClean(AjPStr * s)15326 __deprecated AjBool ajStrClean(AjPStr* s)
15327 {
15328 return ajStrRemoveWhiteExcess(s);
15329 }
15330
15331
15332
15333
15334 /* @obsolete ajStrWildPrefix
15335 ** @rename ajStrRemoveWild
15336 */
15337
ajStrWildPrefix(AjPStr * str)15338 __deprecated AjBool ajStrWildPrefix(AjPStr* str)
15339 {
15340 return ajStrRemoveWild(str);
15341 }
15342
15343
15344
15345
15346 /* @obsolete ajStrChomp
15347 ** @rename ajStrTrimWhite
15348 */
15349
ajStrChomp(AjPStr * pthis)15350 __deprecated AjBool ajStrChomp(AjPStr* pthis)
15351 {
15352 return ajStrTrimWhite(pthis);
15353 }
15354
15355
15356
15357
15358 /* @obsolete ajStrChompC
15359 ** @rename ajStrTrimC
15360 */
15361
ajStrChompC(AjPStr * pthis,const char * delim)15362 __deprecated AjBool ajStrChompC(AjPStr* pthis, const char* delim)
15363 {
15364 return ajStrTrimC(pthis, delim);
15365 }
15366
15367
15368
15369
15370 /* @obsolete ajStrChop
15371 ** @replace ajStrCutEnd (1/1,'1')
15372 */
15373
ajStrChop(AjPStr * pthis)15374 __deprecated AjBool ajStrChop(AjPStr* pthis)
15375 {
15376 return ajStrCutEnd(pthis, 1);
15377 }
15378
15379
15380
15381
15382 /* @obsolete ajStrChompEnd
15383 ** @rename ajStrTrimWhiteEnd
15384 */
15385
ajStrChompEnd(AjPStr * pthis)15386 __deprecated AjBool ajStrChompEnd(AjPStr* pthis)
15387 {
15388 return ajStrTrimWhiteEnd(pthis);
15389 }
15390
15391
15392
15393
15394 /* @obsolete ajStrTruncate
15395 @rename ajStrTruncateLen
15396 */
15397
ajStrTruncate(AjPStr * Pstr,ajint pos)15398 __deprecated AjBool ajStrTruncate(AjPStr* Pstr, ajint pos)
15399 {
15400 return ajStrTruncateLen(Pstr, pos);
15401 }
15402
15403
15404
15405
15406 /* @obsolete ajStrSubstituteCC
15407 ** @rename ajStrExchangeCC
15408 */
15409
ajStrSubstituteCC(AjPStr * pthis,const char * replace,const char * putin)15410 __deprecated AjBool ajStrSubstituteCC(AjPStr* pthis, const char* replace,
15411 const char* putin)
15412 {
15413 return ajStrExchangeCC(pthis, replace, putin);
15414 }
15415
15416
15417
15418
15419 /* @obsolete ajStrSubstituteKK
15420 ** @rename ajStrExchangeKK
15421 */
15422
ajStrSubstituteKK(AjPStr * pthis,char replace,char putin)15423 __deprecated AjBool ajStrSubstituteKK(AjPStr* pthis, char replace, char putin)
15424 {
15425 return ajStrExchangeKK(pthis, replace, putin);
15426 }
15427
15428
15429
15430
15431 /* @obsolete ajStrSubstitute
15432 ** @rename ajStrExchangeSS
15433 */
15434
ajStrSubstitute(AjPStr * pthis,const AjPStr replace,const AjPStr putin)15435 __deprecated AjBool ajStrSubstitute(AjPStr* pthis,
15436 const AjPStr replace, const AjPStr putin)
15437 {
15438 return ajStrExchangeSS(pthis, replace, putin);
15439 }
15440
15441
15442
15443
15444 /* @obsolete ajStrConvertCC
15445 ** @rename ajStrExchangeSetCC
15446 */
15447
ajStrConvertCC(AjPStr * pthis,const char * oldc,const char * newc)15448 __deprecated AjBool ajStrConvertCC(AjPStr* pthis, const char* oldc,
15449 const char* newc)
15450 {
15451 return ajStrExchangeSetCC(pthis, oldc, newc);
15452 }
15453
15454
15455
15456
15457 /* @obsolete ajStrConvert
15458 ** @rename ajStrExchangeSetSS
15459 */
15460
ajStrConvert(AjPStr * pthis,const AjPStr oldc,const AjPStr newc)15461 __deprecated AjBool ajStrConvert(AjPStr* pthis, const AjPStr oldc,
15462 const AjPStr newc)
15463 {
15464 if(!oldc || !newc)
15465 return ajFalse;
15466
15467 return ajStrExchangeSetSS(pthis, oldc, newc);
15468 }
15469
15470
15471
15472
15473 /* @obsolete ajStrRev
15474 ** @rename ajStrReverse
15475 */
15476
ajStrRev(AjPStr * pthis)15477 __deprecated AjBool ajStrRev(AjPStr* pthis)
15478 {
15479 return ajStrReverse(pthis);
15480 }
15481
15482
15483
15484
15485 /* @obsolete ajStrCountC
15486 ** @rename ajStrCalcCountC
15487 */
15488
ajStrCountC(const AjPStr str,const char * txt)15489 __deprecated ajint ajStrCountC(const AjPStr str, const char* txt)
15490 {
15491 return (ajint) ajStrCalcCountC(str, txt);
15492 }
15493
15494
15495
15496
15497 /* @obsolete ajStrCountK
15498 ** @rename ajStrCalcCountK
15499 */
15500
ajStrCountK(const AjPStr str,char ch)15501 __deprecated ajint ajStrCountK(const AjPStr str, char ch)
15502 {
15503 return (ajint) ajStrCalcCountK(str, ch);
15504 }
15505
15506
15507
15508
15509 /* @obsolete ajStrParentheses
15510 ** @rename ajStrHasParentheses
15511 */
15512
ajStrParentheses(const AjPStr s)15513 __deprecated AjBool ajStrParentheses(const AjPStr s)
15514 {
15515 return ajStrHasParentheses(s);
15516 }
15517
15518
15519
15520
15521 /* @obsolete ajStrIsSpace
15522 ** @rename ajStrIsWhite
15523 */
15524
ajStrIsSpace(const AjPStr thys)15525 __deprecated AjBool ajStrIsSpace(const AjPStr thys)
15526 {
15527 return ajStrIsWhite(thys);
15528 }
15529
15530
15531
15532
15533 /* @obsolete ajStrChar
15534 ** @replace ajStrGetCharFirst (1,'0'/1)
15535 ** @replace ajStrGetCharLast (1,'-1'/1)
15536 ** @replace ajStrGetCharPos (1,2/1,2)
15537 */
15538
ajStrChar(const AjPStr thys,ajint pos)15539 __deprecated char ajStrChar(const AjPStr thys, ajint pos)
15540 {
15541 if(pos == 0)
15542 ajStrGetCharFirst(thys);
15543
15544 if(pos == -1)
15545 ajStrGetCharLast(thys);
15546
15547 return ajStrGetCharPos(thys, pos);
15548 }
15549
15550
15551
15552
15553 /* @obsolete ajStrLen
15554 ** @rename ajStrGetLen
15555 */
15556
ajStrLen(const AjPStr thys)15557 __deprecated ajint ajStrLen(const AjPStr thys)
15558 {
15559 return (ajint) ajStrGetLen(thys);
15560 }
15561
15562
15563
15564
15565 /* @obsolete MAJSTRLEN
15566 ** @rename MAJSTRGETLEN
15567 */
15568
MAJSTRLEN(const AjPStr thys)15569 __deprecated ajint MAJSTRLEN(const AjPStr thys)
15570 {
15571 return (ajint) MAJSTRGETLEN(thys);
15572 }
15573
15574
15575
15576
15577 /* @obsolete ajStrStr
15578 ** @rename ajStrGetPtr
15579 */
15580
ajStrStr(const AjPStr thys)15581 __deprecated const char *ajStrStr(const AjPStr thys)
15582 {
15583 return ajStrGetPtr(thys);
15584 }
15585
15586
15587
15588
15589 /* @obsolete MAJSTRSTR
15590 ** @rename MAJSTRGETPTR
15591 */
15592
MAJSTRSTR(const AjPStr thys)15593 __deprecated const char *MAJSTRSTR(const AjPStr thys)
15594 {
15595 return MAJSTRGETPTR(thys);
15596 }
15597
15598
15599
15600
15601 /* @obsolete ajStrSize
15602 ** @rename ajStrGetRes
15603 */
ajStrSize(const AjPStr thys)15604 __deprecated ajint ajStrSize(const AjPStr thys)
15605 {
15606 return (ajint) ajStrGetRes(thys);
15607 }
15608
15609
15610
15611
15612 /* @obsolete MAJSTRSIZE
15613 ** @rename MAJSTRGETRES
15614 */
MAJSTRSIZE(const AjPStr thys)15615 __deprecated ajint MAJSTRSIZE(const AjPStr thys)
15616 {
15617 return (ajint) MAJSTRGETRES(thys);
15618 }
15619
15620
15621
15622
15623 /* @obsolete ajStrRoom
15624 ** @rename ajStrGetRoom
15625 */
15626
ajStrRoom(const AjPStr thys)15627 __deprecated ajint ajStrRoom(const AjPStr thys)
15628 {
15629 return (ajint) ajStrGetRoom(thys);
15630 }
15631
15632
15633
15634
15635 /* @obsolete ajStrRef
15636 ** @rename ajStrGetUse
15637 */
15638
ajStrRef(const AjPStr thys)15639 __deprecated ajint ajStrRef(const AjPStr thys)
15640 {
15641 return ajStrGetUse(thys);
15642 }
15643
15644
15645
15646
15647 /* @obsolete MAJSTRREF
15648 ** @rename MAJSTRGETUSE
15649 */
15650
MAJSTRREF(const AjPStr thys)15651 __deprecated ajint MAJSTRREF(const AjPStr thys)
15652 {
15653 return MAJSTRGETUSE(thys);
15654 }
15655
15656
15657
15658
15659 /* @obsolete ajStrStrMod
15660 ** @rename ajStrGetuniquePtr
15661 */
15662
ajStrStrMod(AjPStr * pthis)15663 __deprecated char *ajStrStrMod(AjPStr *pthis)
15664 {
15665 return ajStrGetuniquePtr(pthis);
15666 }
15667
15668
15669
15670
15671 /* @obsolete ajStrMod
15672 ** @rename ajStrGetUniqueStr
15673 */
15674
ajStrMod(AjPStr * pthis)15675 __deprecated AjBool ajStrMod(AjPStr* pthis)
15676 {
15677 AjBool ret = ajTrue;
15678
15679 if ((*pthis)->Use == 1)
15680 ret = ajFalse;
15681 ajStrGetuniqueStr(pthis);
15682
15683 return ret;
15684 }
15685
15686
15687
15688
15689 /* @obsolete ajStrClear
15690 ** @rename ajStrSetClear
15691 */
15692
ajStrClear(AjPStr * pthis)15693 __deprecated AjBool ajStrClear(AjPStr* pthis)
15694 {
15695 return ajStrSetClear(pthis);
15696 }
15697
15698
15699
15700
15701 /* @obsolete ajStrModL
15702 ** @rename ajStrSetRes
15703 */
ajStrModL(AjPStr * pthis,size_t size)15704 __deprecated AjBool ajStrModL(AjPStr* pthis, size_t size)
15705 {
15706 return ajStrSetRes(pthis, size);
15707 }
15708
15709
15710
15711
15712 /* @obsolete ajStrModMinL
15713 ** @rename ajStrSetResRound
15714 */
15715
ajStrModMinL(AjPStr * pthis,ajuint size)15716 __deprecated AjBool ajStrModMinL(AjPStr* pthis, ajuint size)
15717 {
15718 return ajStrSetResRound(pthis, size);
15719 }
15720
15721
15722
15723
15724 /* @obsolete ajStrFix
15725 ** @rename ajStrSetValid
15726 */
15727
ajStrFix(AjPStr * pthis)15728 __deprecated void ajStrFix(AjPStr *pthis)
15729 {
15730 ajStrSetValid(pthis);
15731
15732 return;
15733 }
15734
15735
15736
15737
15738 /* @obsolete ajStrFixI
15739 ** @rename ajStrSetValidLen
15740 */
15741
ajStrFixI(AjPStr * pthis,ajint ilen)15742 __deprecated void ajStrFixI(AjPStr* pthis, ajint ilen)
15743 {
15744 ajStrSetValidLen(pthis, (size_t) ilen);
15745
15746 return;
15747 }
15748
15749
15750
15751
15752 /* @obsolete ajStrFromDoubleE
15753 ** @rename ajStrFromDoubleExp
15754 */
15755
ajStrFromDoubleE(AjPStr * Pstr,double val,ajint precision)15756 __deprecated AjBool ajStrFromDoubleE(AjPStr* Pstr, double val, ajint precision)
15757 {
15758 return ajStrFromDoubleExp(Pstr, val, precision);
15759 }
15760
15761
15762
15763
15764 /* @obsolete ajStrBlock
15765 ** @rename ajStrFmtBlock
15766 */
15767
ajStrBlock(AjPStr * pthis,ajint blksize)15768 __deprecated AjBool ajStrBlock(AjPStr* pthis, ajint blksize)
15769 {
15770 return ajStrFmtBlock(pthis, blksize);
15771 }
15772
15773
15774
15775
15776 /* @obsolete ajStrToLower
15777 ** @rename ajStrFmtLower
15778 */
ajStrToLower(AjPStr * pthis)15779 __deprecated AjBool ajStrToLower(AjPStr* pthis)
15780 {
15781 return ajStrFmtLower(pthis);
15782 }
15783
15784
15785
15786
15787 /* @obsolete ajStrToLowerII
15788 ** @rename ajStrFmtLowerSub
15789 */
ajStrToLowerII(AjPStr * pthis,ajint begin,ajint end)15790 __deprecated AjBool ajStrToLowerII(AjPStr* pthis, ajint begin, ajint end)
15791 {
15792 return ajStrFmtLowerSub(pthis, begin, end);
15793 }
15794
15795
15796
15797
15798 /* @obsolete ajStrQuote
15799 ** @rename ajStrFmtQuote
15800 */
15801
ajStrQuote(AjPStr * s)15802 __deprecated void ajStrQuote(AjPStr* s)
15803 {
15804 ajStrFmtQuote(s);
15805 }
15806
15807
15808
15809
15810 /* @obsolete ajStrToTitle
15811 ** @rename ajStrFmtTitle
15812 */
15813
ajStrToTitle(AjPStr * pthis)15814 __deprecated AjBool ajStrToTitle(AjPStr* pthis)
15815 {
15816 return ajStrFmtTitle(pthis);
15817 }
15818
15819
15820
15821
15822 /* @obsolete ajStrToUpper
15823 ** @rename ajStrFmtUpper
15824 */
15825
ajStrToUpper(AjPStr * pthis)15826 __deprecated AjBool ajStrToUpper(AjPStr* pthis)
15827 {
15828 return ajStrFmtUpper(pthis);
15829 }
15830
15831
15832
15833
15834 /* @obsolete ajStrToUpperII
15835 ** @rename ajStrFmtUpperII
15836 */
15837
ajStrToUpperII(AjPStr * pthis,ajint begin,ajint end)15838 __deprecated AjBool ajStrToUpperII(AjPStr* pthis, ajint begin, ajint end)
15839 {
15840 return ajStrFmtUpperSub(pthis, begin, end);
15841 }
15842
15843
15844
15845
15846 /* @obsolete ajStrWrap
15847 ** @rename ajStrFmtWrap
15848 */
15849
ajStrWrap(AjPStr * Pstr,ajint width)15850 __deprecated AjBool ajStrWrap(AjPStr* Pstr, ajint width )
15851 {
15852 return ajStrFmtWrap(Pstr, width);
15853 }
15854
15855
15856
15857
15858 /* @obsolete ajStrWrapLeft
15859 ** @rename ajStrFmtWrapLeft
15860 */
15861
ajStrWrapLeft(AjPStr * pthis,ajint width,ajint left)15862 __deprecated AjBool ajStrWrapLeft(AjPStr* pthis, ajint width, ajint left)
15863 {
15864 return ajStrFmtWrapLeft(pthis, width, 0, left);
15865 }
15866
15867
15868
15869
15870 /* @obsolete ajStrMatch
15871 ** @rename ajStrMatchS
15872 */
ajStrMatch(const AjPStr str,const AjPStr str2)15873 __deprecated AjBool ajStrMatch(const AjPStr str, const AjPStr str2)
15874 {
15875 return ajStrMatchS(str, str2);
15876 }
15877
15878
15879
15880
15881
15882 /* @obsolete ajStrMatchCase
15883 ** @rename ajStrMatchCaseS
15884 */
15885
ajStrMatchCase(const AjPStr str,const AjPStr str2)15886 __deprecated AjBool ajStrMatchCase(const AjPStr str, const AjPStr str2)
15887 {
15888 return ajStrMatchCaseS(str, str2);
15889 }
15890
15891
15892
15893
15894 /* @obsolete ajStrMatchWild
15895 ** @rename ajStrMatchWildS
15896 */
15897
ajStrMatchWild(const AjPStr str,const AjPStr str2)15898 __deprecated AjBool ajStrMatchWild(const AjPStr str, const AjPStr str2)
15899 {
15900 return ajStrMatchWildS(str, str2);
15901 }
15902
15903
15904
15905
15906 /* @obsolete ajStrMatchWord
15907 ** @rename ajStrMatchWildWordS
15908 */
15909
ajStrMatchWord(const AjPStr str,const AjPStr str2)15910 __deprecated AjBool ajStrMatchWord(const AjPStr str, const AjPStr str2)
15911 {
15912 return ajStrMatchWildWordS(str, str2);
15913 }
15914
15915
15916
15917
15918 /* @obsolete ajStrPrefix
15919 ** @rename ajStrPrefixS
15920 */
15921
ajStrPrefix(const AjPStr str,const AjPStr str2)15922 __deprecated AjBool ajStrPrefix(const AjPStr str, const AjPStr str2)
15923 {
15924 return ajStrPrefixS(str, str2);
15925 }
15926
15927
15928
15929
15930 /* @obsolete ajStrPrefixCase
15931 ** @rename ajStrPrefixCaseS
15932 */
15933
ajStrPrefixCase(const AjPStr str,const AjPStr str2)15934 __deprecated AjBool ajStrPrefixCase(const AjPStr str, const AjPStr str2)
15935 {
15936 return ajStrPrefixCaseS(str,str2);
15937 }
15938
15939
15940
15941
15942 /* @obsolete ajStrSuffix
15943 ** @rename ajStrSuffixS
15944 */
15945
ajStrSuffix(const AjPStr str,const AjPStr str2)15946 __deprecated AjBool ajStrSuffix(const AjPStr str, const AjPStr str2)
15947 {
15948 return ajStrSuffixS(str, str2);
15949 }
15950
15951
15952
15953
15954 /* @obsolete ajStrNCmpC
15955 ** @rename ajStrCmpLenC
15956 */
15957
ajStrNCmpC(const AjPStr str,const char * txt,ajint len)15958 __deprecated int ajStrNCmpC(const AjPStr str, const char* txt, ajint len)
15959 {
15960 return ajStrCmpLenC(str, txt, len);
15961 }
15962
15963
15964
15965
15966 /* @obsolete ajStrCmpO
15967 ** @rename ajStrCmpS
15968 */
15969
ajStrCmpO(const AjPStr thys,const AjPStr anoth)15970 __deprecated int ajStrCmpO(const AjPStr thys, const AjPStr anoth)
15971 {
15972 return ajStrCmpS(thys, anoth);
15973 }
15974
15975
15976
15977
15978 /* @obsolete ajStrCmpCase
15979 ** @rename ajStrCmpCaseS
15980 */
15981
ajStrCmpCase(const AjPStr str,const AjPStr str2)15982 __deprecated int ajStrCmpCase(const AjPStr str, const AjPStr str2)
15983 {
15984 return ajStrCmpCaseS(str, str2);
15985 }
15986
15987
15988
15989
15990 /* @obsolete ajStrNCmpO
15991 ** @rename ajStrCmpLenS
15992 */
15993
ajStrNCmpO(const AjPStr str,const AjPStr str2,ajint len)15994 __deprecated int ajStrNCmpO(const AjPStr str, const AjPStr str2, ajint len)
15995 {
15996 return ajStrCmpLenS(str, str2, len);
15997 }
15998
15999
16000
16001
16002 /* @obsolete ajStrCmpWild
16003 ** @rename ajStrCmpWildS
16004 */
16005
16006
ajStrCmpWild(const AjPStr str,const AjPStr str2)16007 __deprecated int ajStrCmpWild(const AjPStr str, const AjPStr str2)
16008 {
16009 return ajStrCmpWildS(str, str2);
16010 }
16011
16012
16013
16014
16015 /* @obsolete ajStrCmp
16016 ** @rename ajStrVcmp
16017 */
16018
ajStrCmp(const void * str,const void * str2)16019 __deprecated int ajStrCmp(const void* str, const void* str2)
16020 {
16021 return ajStrVcmp(str, str2);
16022 }
16023
16024
16025
16026
16027 /* @obsolete ajStrFind
16028 ** @rename ajStrFindS
16029 */
16030
ajStrFind(const AjPStr str,const AjPStr str2)16031 __deprecated ajint ajStrFind(const AjPStr str, const AjPStr str2)
16032 {
16033 return (ajint) ajStrFindS(str, str2);
16034 }
16035
16036
16037
16038
16039 /* @obsolete ajStrFindK
16040 ** @rename ajStrFindAnyK
16041 */
16042
ajStrFindK(const AjPStr thys,const char chr)16043 __deprecated ajint ajStrFindK(const AjPStr thys, const char chr)
16044 {
16045 return (ajint) ajStrFindAnyK(thys, chr);
16046 }
16047
16048
16049
16050
16051 /* @obsolete ajStrFindCase
16052 ** @rename ajStrFindCaseS
16053 */
16054
ajStrFindCase(const AjPStr str,const AjPStr str2)16055 __deprecated ajint ajStrFindCase(const AjPStr str, const AjPStr str2)
16056 {
16057 return (ajint) ajStrFindCaseS(str,str2);
16058 }
16059
16060
16061
16062
16063 /* @obsolete ajStrRFindC
16064 ** @rename ajStrFindlastC
16065 */
16066
ajStrRFindC(const AjPStr thys,const char * text)16067 __deprecated ajint ajStrRFindC(const AjPStr thys, const char* text)
16068 {
16069 return (ajint) ajStrFindlastC(thys, text);
16070 }
16071
16072
16073
16074
16075 /* @obsolete ajStrTokC
16076 ** @rename ajStrParseC
16077 */
16078
ajStrTokC(const AjPStr thys,const char * delim)16079 __deprecated const AjPStr ajStrTokC(const AjPStr thys, const char* delim)
16080 {
16081 return ajStrParseC(thys, delim);
16082 }
16083
16084
16085
16086
16087 /* @obsolete ajStrTokenCount
16088 ** @rename ajStrParseCountC
16089 */
16090
ajStrTokenCount(const AjPStr line,const char * delim)16091 __deprecated ajint ajStrTokenCount(const AjPStr line, const char *delim)
16092 {
16093 return ajStrParseCountC(line, delim);
16094 }
16095
16096
16097
16098
16099 /* @obsolete ajStrTokenCountR
16100 ** @rename ajStrParseCountMultiC
16101 */
16102
ajStrTokenCountR(const AjPStr line,const char * delim)16103 __deprecated ajint ajStrTokenCountR(const AjPStr line, const char *delim)
16104 {
16105 return ajStrParseCountMultiC(line, delim);
16106 }
16107
16108
16109
16110
16111 /* @obsolete ajStrListToArray
16112 ** @rename ajStrParseSplit
16113 */
16114
ajStrListToArray(const AjPStr thys,AjPStr ** array)16115 __deprecated ajint ajStrListToArray(const AjPStr thys, AjPStr **array)
16116 {
16117 return ajStrParseSplit(thys, array);
16118 }
16119
16120
16121
16122
16123 /* @obsolete ajStrTok
16124 ** @rename ajStrParseWhite
16125 */
16126
ajStrTok(const AjPStr str)16127 __deprecated const AjPStr ajStrTok(const AjPStr str)
16128 {
16129 return ajStrParseWhite(str);
16130 }
16131
16132
16133
16134
16135 /* @obsolete ajStrFill
16136 ** @replace ajStrAppendCountK (1,2,3/1,3,*)
16137 */
16138
ajStrFill(AjPStr * pthys,ajint len,char fill)16139 __deprecated void ajStrFill(AjPStr* pthys, ajint len, char fill)
16140 {
16141 ajint icount;
16142 icount = len - (*pthys)->Len;
16143 ajStrAppendCountK(pthys, fill, icount);
16144
16145 return;
16146 }
16147
16148
16149
16150
16151 /* @obsolete ajStrPos
16152 ** @replace ajCvtSposToPos (1,2/'ajStrGetLen[1]',2)
16153 */
16154
ajStrPos(const AjPStr thys,ajint ipos)16155 __deprecated ajint ajStrPos(const AjPStr thys, ajint ipos)
16156 {
16157 return (ajint) ajCvtSposToPos(thys->Len, ipos);
16158 }
16159
16160
16161
16162
16163 /* @obsolete ajStrPosI
16164 ** @replace ajCvtSposToPosStart (1,2,3/'ajStrGetLen[1]',2,3)
16165 */
16166
ajStrPosI(const AjPStr thys,ajint imin,ajint ipos)16167 __deprecated ajint ajStrPosI(const AjPStr thys, ajint imin, ajint ipos)
16168 {
16169 return (ajint) ajCvtSposToPosStart(thys->Len, imin, ipos);
16170 }
16171
16172
16173
16174
16175 /* @obsolete ajStrPosII
16176 ** @rename ajCvtSposToPosStart
16177 */
16178
ajStrPosII(ajint ilen,ajint imin,ajint ipos)16179 __deprecated ajint ajStrPosII(ajint ilen, ajint imin, ajint ipos)
16180 {
16181 return (ajint) ajCvtSposToPosStart(ilen, imin, ipos);
16182 }
16183
16184
16185
16186
16187 /* @obsolete ajCharPos
16188 ** @replace ajCvtSposToPos (1,2/'strlen[1]',2)
16189 */
16190
ajCharPos(const char * thys,ajint ipos)16191 __deprecated ajint ajCharPos(const char* thys, ajint ipos)
16192 {
16193 return (ajint) ajCvtSposToPos(strlen(thys), ipos);
16194 }
16195
16196
16197
16198
16199 /* @obsolete ajStrIter
16200 ** @rename ajStrIterNew
16201 */
16202
ajStrIter(const AjPStr str)16203 __deprecated AjIStr ajStrIter(const AjPStr str)
16204 {
16205 return ajStrIterNew(str);
16206 }
16207
16208
16209
16210
16211 /* @obsolete ajStrIterBack
16212 ** @rename ajStrIterNewBack
16213 */
16214
ajStrIterBack(const AjPStr str)16215 __deprecated AjIStr ajStrIterBack(const AjPStr str)
16216 {
16217 return ajStrIterNewBack(str);
16218 }
16219
16220
16221
16222
16223 /* @obsolete ajStrIterFree
16224 ** @rename ajStrIterDel
16225 */
16226
ajStrIterFree(AjIStr * iter)16227 __deprecated void ajStrIterFree(AjIStr* iter)
16228 {
16229 ajStrIterDel(iter);
16230 }
16231
16232
16233
16234
16235 /* @obsolete ajStrIterBackDone
16236 ** @rename ajStrIterDoneBack
16237 */
16238
ajStrIterBackDone(AjIStr iter)16239 __deprecated AjBool ajStrIterBackDone(AjIStr iter)
16240 {
16241 return ajStrIterDoneBack(iter);
16242 }
16243
16244
16245
16246
16247 /* @obsolete ajStrIterBackNext
16248 ** @rename ajStrIterNextBack
16249 */
16250
ajStrIterBackNext(AjIStr iter)16251 __deprecated AjIStr ajStrIterBackNext(AjIStr iter)
16252 {
16253 return ajStrIterNextBack(iter);
16254 }
16255
16256
16257
16258
16259 /* @obsolete ajStrIterMore
16260 ** @replace ajStrIterDone (1/!1)
16261 */
16262
ajStrIterMore(AjIStr iter)16263 __deprecated AjBool ajStrIterMore(AjIStr iter)
16264 {
16265 return (!ajStrIterDone(iter));
16266 }
16267
16268
16269
16270
16271 /* @obsolete ajStrIterMoreBack
16272 ** @rename ajStrIterDoneBack
16273 */
16274
ajStrIterMoreBack(AjIStr iter)16275 __deprecated AjBool ajStrIterMoreBack(AjIStr iter)
16276 {
16277 return (!ajStrIterDoneBack(iter));
16278 }
16279
16280
16281
16282
16283 /* @obsolete ajStrTokenInit
16284 ** @rename ajStrTokenNewC
16285 */
16286
ajStrTokenInit(const AjPStr thys,const char * delim)16287 __deprecated AjPStrTok ajStrTokenInit(const AjPStr thys, const char* delim)
16288 {
16289 return ajStrTokenNewC(thys, delim);
16290 }
16291
16292
16293
16294
16295 /* @obsolete ajStrTokenClear
16296 ** @rename ajStrTokenDel
16297 */
16298
ajStrTokenClear(AjPStrTok * token)16299 __deprecated void ajStrTokenClear(AjPStrTok* token)
16300 {
16301 ajStrTokenDel(token);
16302 return;
16303 }
16304
16305
16306
16307
16308 /* @obsolete ajStrTokenAss
16309 ** @rename ajStrTokenAssignC
16310 */
16311
ajStrTokenAss(AjPStrTok * ptok,const AjPStr thys,const char * delim)16312 __deprecated AjBool ajStrTokenAss(AjPStrTok* ptok, const AjPStr thys,
16313 const char* delim)
16314 {
16315 return ajStrTokenAssignC(ptok, thys, delim);
16316 }
16317
16318
16319
16320
16321 /* @obsolete ajStrDelim
16322 ** @replace ajStrTokenNextFind (1,2,n/2,1)
16323 ** @replace ajStrTokenNextFindC (1,2,3/2,3,1)
16324 */
16325
ajStrDelim(AjPStr * pthis,AjPStrTok * ptoken,const char * delim)16326 __deprecated AjBool ajStrDelim(AjPStr* pthis, AjPStrTok* ptoken,
16327 const char* delim)
16328 {
16329 if(delim)
16330 return ajStrTokenNextFindC(ptoken, delim, pthis);
16331
16332 return ajStrTokenNextFind(ptoken, pthis);
16333 }
16334
16335
16336
16337
16338 /* @obsolete ajStrToken
16339 ** @replace ajStrTokenNextParse (1,2,n/2,1)
16340 ** @replace ajStrTokenNextParseC (1,2,3/2,3,1)
16341 */
ajStrToken(AjPStr * pthis,AjPStrTok * ptoken,const char * delim)16342 __deprecated AjBool ajStrToken(AjPStr* pthis, AjPStrTok* ptoken,
16343 const char* delim)
16344 {
16345 if(delim)
16346 return ajStrTokenNextParseC(ptoken, delim, pthis);
16347
16348 return ajStrTokenNextParse(ptoken, pthis);
16349 }
16350
16351
16352
16353
16354 /* @obsolete ajStrTokenRest
16355 ** @replace ajStrTokenRestParse (1,2/2,1)
16356 */
16357
ajStrTokenRest(AjPStr * pthis,AjPStrTok * ptoken)16358 __deprecated AjBool ajStrTokenRest(AjPStr* pthis, AjPStrTok* ptoken)
16359 {
16360 return ajStrTokenRestParse(ptoken, pthis);
16361 }
16362
16363
16364
16365
16366 /* @obsolete ajStrNull
16367 ** @remove Make a local empty string instead
16368 */
16369
ajStrNull(void)16370 __deprecated const AjPStr ajStrNull(void)
16371 {
16372 return strPNULL;
16373 }
16374
16375
16376
16377
16378 /* @obsolete ajStrArrayDel
16379 ** @remove Make a local copy if needed -
16380 ** no need for full set of array functions
16381 */
16382
ajStrArrayDel(AjPStr ** pthis)16383 __deprecated void ajStrArrayDel(AjPStr** pthis)
16384 {
16385 AjPStr* thys;
16386 ajint i;
16387
16388 thys = pthis ? *pthis : 0;
16389
16390 if(!pthis)
16391 return;
16392
16393 if(!*pthis)
16394 return;
16395
16396 for(i=0; thys[i];i++)
16397 ajStrDel(&thys[i]);
16398
16399 AJFREE(*pthis);
16400
16401 return;
16402 }
16403
16404
16405
16406
16407 /* @obsolete ajStrAss
16408 ** @replace ajStrAssignC (1,n/1,'""')
16409 ** @replace ajStrAssignRef (1,2/1,2)
16410 */
16411
ajStrAss(AjPStr * pthis,AjPStr str)16412 __deprecated AjBool ajStrAss(AjPStr* pthis, AjPStr str)
16413 {
16414 AjBool ret = ajTrue; /* always true for now */
16415
16416 ajStrDel(pthis); /* we just use the ref count of str */
16417
16418 if(str)
16419 ajStrAssignRef(pthis, str);
16420 else
16421 ajStrAssignClear(pthis);
16422
16423 return ret;
16424 }
16425
16426
16427
16428
16429 /* @obsolete ajStrCopyC
16430 ** @replace ajStrDel (1,n/1)
16431 ** @replace ajStrAssignC (1,2/1,2)
16432 */
16433
ajStrCopyC(AjPStr * pthis,const char * str)16434 __deprecated AjBool ajStrCopyC(AjPStr* pthis, const char* str)
16435 {
16436 AjBool ret = ajTrue; /* true if ajStrDup is used */
16437
16438 if(!str)
16439 ajStrDel(pthis);
16440 else
16441 ajStrAssignC(pthis, str);
16442
16443 return ret;
16444 }
16445 #endif
16446