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(&copy, 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(&copy);
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(&copy);
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