1 /* @source ajutil *************************************************************
2 **
3 **AJAX utility functions
4 **
5 ** @author Copyright (C) 1998 Ian Longden
6 ** @author Copyright (C) 1998 Peter Rice
7 ** @version $Revision: 1.67 $
8 ** @modified $Date: 2012/09/03 14:52:38 $ by $Author: rice $
9 ** @@
10 **
11 ** This library is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU Lesser General Public
13 ** License as published by the Free Software Foundation; either
14 ** version 2.1 of the License, or (at your option) any later version.
15 **
16 ** This library is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** Lesser General Public License for more details.
20 **
21 ** You should have received a copy of the GNU Lesser General Public
22 ** License along with this library; if not, write to the Free Software
23 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 ** MA 02110-1301, USA.
25 **
26 ******************************************************************************/
27
28 #include "ajlib.h"
29
30 #include "ajutil.h"
31
32 /* include anything with an Exit function */
33
34 #include "ajindex.h"
35 #include "ajsql.h"
36 #include "ajmatrices.h"
37 #include "ajtree.h"
38 #include "ajdmx.h"
39 #include "ajdomain.h"
40 #include "ajquery.h"
41 #include "ajtext.h"
42 #include "ajfeat.h"
43 #include "ajseq.h"
44 #include "ajobo.h"
45 #include "ajassem.h"
46 #include "ajrefseq.h"
47 #include "ajtax.h"
48 #include "ajurl.h"
49 #include "ajvar.h"
50 #include "ajxml.h"
51 #include "ajresource.h"
52 #include "ajphylo.h"
53 #include "ajnexus.h"
54 #include "ajalign.h"
55 #include "ajreport.h"
56 #include "ajnam.h"
57 #include "ajsys.h"
58 #include "ajcall.h"
59 #include "ajbase.h"
60 #include "ajcod.h"
61 #include "ajtranslate.h"
62 #include "ajdan.h"
63 #include "ajtime.h"
64 #include "ajreg.h"
65 #include "ajarr.h"
66 #include "ajfiledata.h"
67 #include "ajfile.h"
68 #include "ajlist.h"
69 #include "ajtable.h"
70 #include "ajstr.h"
71 #include "ajmem.h"
72
73 #include <stdarg.h>
74 #ifdef WIN32
75 #include "win32.h"
76 #include <winsock2.h>
77 #include <lmcons.h> /* for UNLEN */
78 #else /* !WIN32 */
79 #include <pwd.h>
80 #include <unistd.h>
81 #endif /* WIN32 */
82
83
84
85 static AjBool utilBigendian;
86 static ajint utilBigendCalled = 0;
87
88 static AjBool utilIsBase64(char c);
89 static char utilBase64Encode(unsigned char u);
90 static unsigned char utilBase64Decode(char c);
91
92
93
94
95 /* @filesection ajutil ********************************************************
96 **
97 ** @nam1rule aj Function belongs to the AJAX library.
98 **
99 ******************************************************************************/
100
101
102
103
104 /* @datasection [none] Exit functions *****************************************
105 **
106 ** @nam2rule Exit Functions for exiting cleanly
107 **
108 ******************************************************************************/
109
110
111
112
113 /* @section exit *************************************************************
114 **
115 ** Functions for exiting cleanly.
116 **
117 ** @fdata [none]
118 **
119 ** @nam3rule Abort Exits without flushing any files.
120 ** @nam3rule Bad Calls 'exit' with an unsuccessful code (EXIT_FAILURE
121 ** defined in stdlib.h).
122 **
123 ** @valrule * [void] All functions do not return
124 **
125 ** @fcategory misc
126 **
127 ******************************************************************************/
128
129
130
131
132 /* @func ajExit ***************************************************************
133 **
134 ** Calls 'exit' with a successful code (zero), but first calls ajReset to
135 ** call memory clean up and debug reporting functions.
136 **
137 ** No cleanup or reporting routines are called. Simply crashes.
138 **
139 ** @return [void]
140 **
141 ** @release 1.0.0
142 ** @@
143 ******************************************************************************/
144
ajExit(void)145 __noreturn void ajExit(void)
146 {
147 ajReset();
148 exit(EXIT_SUCCESS);
149 }
150
151
152
153
154 /* @func ajExitAbort **********************************************************
155 **
156 ** Exits without flushing any files. Needed for exit from, for example,
157 ** a failed system call (ajFileNewInPipe, and so on) where the parent
158 ** process has open output files, and the child process needs to exit
159 ** without affecting them. Failure to exit this way can mean the output
160 ** buffer is flushed twice.
161 **
162 ** Calls '_exit' with an unsuccessful code (EXIT_FAILURE defined in stdlib.h).
163 **
164 ** No cleanup or reporting routines are called. Simply crashes.
165 **
166 ** @return [void]
167 **
168 ** @release 3.0.0
169 ** @@
170 ******************************************************************************/
171
ajExitAbort(void)172 __noreturn void ajExitAbort(void)
173 {
174 _exit(EXIT_FAILURE);
175 }
176
177
178
179
180 /* @func ajExitBad ************************************************************
181 **
182 ** Calls 'exit' with an unsuccessful code (EXIT_FAILURE defined in stdlib.h).
183 **
184 ** No cleanup or reporting routines are called. Simply crashes.
185 **
186 ** @return [void]
187 **
188 ** @release 1.0.0
189 ** @@
190 ******************************************************************************/
191
ajExitBad(void)192 __noreturn void ajExitBad(void)
193 {
194 exit(EXIT_FAILURE);
195 }
196
197
198
199
200 /* @datasection [none] Memory cleanup functions *******************************
201 **
202 ** @nam2rule Reset Resets internal memory and returns.
203 **
204 ******************************************************************************/
205
206
207
208
209 /* @section reset *************************************************************
210 **
211 ** Functions for memory cleanup
212 **
213 ** @fdata [none]
214 **
215 **
216 ** @valrule * [void] No return value
217 **
218 ** @fcategory misc
219 **
220 ******************************************************************************/
221
222
223
224
225 /* @func ajReset **************************************************************
226 **
227 ** Cleans up all internal memory by calling cleanup routines which
228 ** can report on resource usage etc.
229 **
230 ** Intended to be called at the end of processing by exit functions.
231 **
232 ** @return [void]
233 **
234 ** @release 5.0.0
235 ** @@
236 ******************************************************************************/
237
ajReset(void)238 void ajReset(void)
239 {
240 #ifdef WIN32
241 WSACleanup();
242 #endif /* WIN32 */
243 ajDebug("\nFinal Summary\n=============\n\n");
244 ajBtreeExit();
245 ajSqlExit();
246 ajMatrixExit();
247 ajTreeExit();
248 ajPdbExit();
249 ajDmxExit();
250 ajDomainExit();
251 ajQueryExit();
252 ajTextExit();
253 ajFeatExit();
254 ajSeqExit();
255 ajOboExit();
256 ajAssemExit();
257 ajRefseqExit();
258 ajTaxExit();
259 ajUrlExit();
260 ajVarExit();
261 ajXmlExit();
262 ajResourceExit();
263 ajPhyloExit();
264 ajNexusExit();
265 ajAlignExit();
266 ajReportExit();
267 ajNamExit();
268 ajSysExit();
269 ajCallExit();
270 ajBaseExit();
271 ajCodExit();
272 ajTrnExit();
273 ajMeltExit();
274 ajTimeExit();
275 ajRegExit();
276 ajArrExit();
277 ajDatafileExit();
278 ajFileExit();
279 ajListExit();
280 ajMessExit();
281 ajTableExit();
282 ajStrExit();
283 ajMemExit();
284 ajMessExitDebug(); /* clears data for ajDebug - do this last!!! */
285
286 return;
287 }
288
289
290
291
292 /* @datasection [none] Byte manipulation functions ****************************
293 **
294 ** @nam2rule Byte Manipulate a byte of data.
295 **
296 ******************************************************************************/
297
298
299
300
301 /* @section byte manipulation functions **************************************
302 **
303 ** Functions for manipulating bytes.
304 **
305 ** @fdata [none]
306 **
307 ** @nam3rule Rev Reverse the byte order.
308 ** @nam4rule RevLen2 Reverse the byte order in a 2 byte integer.
309 ** @nam4rule RevLen4 Reverse the byte order in a 4 byte integer.
310 ** @nam4rule RevLen8 Reverse the byte order in a 8 byte integer.
311 ** @nam4rule RevLen2u Reverse the byte order in a 2 byte unsigned integer.
312 ** @nam4rule RevLen4u Reverse the byte order in a 4 byte unsigned integer.
313 ** @nam4rule RevLen8u Reverse the byte order in a 8 byte unsigned integer.
314 ** @nam4rule RevInt Reverse the byte order in an integer.
315 ** @nam4rule RevShort Reverse the byte order in a short integer.
316 ** @nam4rule RevLong Reverse the byte order in a long.
317 ** @nam4rule RevUint Reverse the byte order in an unsigned integer.
318 ** @nam4rule RevUlong Reverse the byte order in an unsigned long.
319 **
320 ** @argrule RevLen2 sval [ajshort*] Short to be reversed
321 ** @argrule RevLen4 ival [ajint*] Integer to be reversed
322 ** @argrule RevLen8 lval [ajlong*] Long integer to be reversed
323 ** @argrule RevLen2u sval [ajushort*] Unsigned short to be reversed
324 ** @argrule RevLen4u ival [ajuint*] Unsigned integer to be reversed
325 ** @argrule RevLen8u lval [ajulong*] Unsigned long integer to be reversed
326 ** @argrule RevShort sval [ajshort*] Short to be reversed
327 ** @argrule RevInt ival [ajint*] Integer to be reversed
328 ** @argrule RevLong lval [ajlong*] Long integer to be reversed
329 ** @argrule RevUint ival [ajuint*] Unsigned integer to be reversed
330 ** @argrule RevUlong lval [ajulong*] Unsigned long integer to be reversed
331 **
332 ** @valrule * [void]
333 **
334 ** @fcategory misc
335 **
336 ******************************************************************************/
337
338
339
340
341 /* @func ajByteRevInt *********************************************************
342 **
343 ** Reverses the byte order in an integer.
344 **
345 ** @param [u] ival [ajint*] Integer in wrong byte order.
346 ** Returned in correct order.
347 ** @return [void]
348 **
349 ** @release 5.0.0
350 ** @@
351 ******************************************************************************/
352
ajByteRevInt(ajint * ival)353 void ajByteRevInt(ajint* ival)
354 {
355 union lbytes
356 {
357 char chars[8];
358 ajint i;
359 } data, revdata;
360
361 char* cs;
362 char* cd;
363 ajuint i;
364
365 data.i = *ival;
366 cs = data.chars;
367 cd = &revdata.chars[sizeof(ajint)-1];
368
369 for(i=0; i < sizeof(ajint); i++)
370 {
371 *cd = *cs++;
372 --cd;
373 }
374
375 *ival = revdata.i;
376
377 return;
378 }
379
380
381
382
383 /* @func ajByteRevLen2 ********************************************************
384 **
385 ** Reverses the byte order in a 2 byte integer.
386 **
387 ** Intended for cases where the number of bytes is known, for
388 ** example when reading a binary file.
389 **
390 ** @param [u] sval [ajshort*] Short integer in wrong byte order.
391 ** Returned in correct order.
392 ** @return [void]
393 **
394 ** @release 5.0.0
395 ** @@
396 ******************************************************************************/
397
ajByteRevLen2(ajshort * sval)398 void ajByteRevLen2(ajshort* sval)
399 {
400 union lbytes
401 {
402 char chars[2];
403 ajshort s;
404 } data, revdata;
405
406 char* cs;
407 char* cd;
408 ajint i;
409
410 data.s = *sval;
411 cs = data.chars;
412 cd = &revdata.chars[1];
413
414 for(i=0; i < 2; i++)
415 {
416 *cd = *cs++;
417 --cd;
418 }
419
420 *sval = revdata.s;
421
422 return;
423 }
424
425
426
427
428 /* @func ajByteRevLen2u *******************************************************
429 **
430 ** Reverses the byte order in a 2 byte integer.
431 **
432 ** Intended for cases where the number of bytes is known, for
433 ** example when reading a binary file.
434 **
435 ** @param [u] sval [ajushort*] Short integer in wrong byte order.
436 ** Returned in correct order.
437 ** @return [void]
438 **
439 ** @release 6.2.0
440 ** @@
441 ******************************************************************************/
442
ajByteRevLen2u(ajushort * sval)443 void ajByteRevLen2u(ajushort* sval)
444 {
445 union lbytes
446 {
447 char chars[2];
448 ajushort s;
449 } data, revdata;
450
451 char* cs;
452 char* cd;
453 ajint i;
454
455 data.s = *sval;
456 cs = data.chars;
457 cd = &revdata.chars[1];
458
459 for(i=0; i < 2; i++)
460 {
461 *cd = *cs++;
462 --cd;
463 }
464
465 *sval = revdata.s;
466
467 return;
468 }
469
470
471
472
473 /* @func ajByteRevLen4 ********************************************************
474 **
475 ** Reverses the byte order in a 4 byte integer.
476 **
477 ** Intended for cases where the number of bytes is known, for
478 ** example when reading a binary file.
479 **
480 ** @param [u] ival [ajint*] Integer in wrong byte order.
481 ** Returned in correct order.
482 ** @return [void]
483 **
484 ** @release 5.0.0
485 ** @@
486 ******************************************************************************/
487
ajByteRevLen4(ajint * ival)488 void ajByteRevLen4(ajint* ival)
489 {
490 union lbytes
491 {
492 char chars[4];
493 ajint i;
494 } data, revdata;
495
496 char* cs;
497 char* cd;
498 ajint i;
499
500 data.i = *ival;
501 cs = data.chars;
502 cd = &revdata.chars[3];
503
504 for(i=0; i < 4; i++)
505 {
506 *cd = *cs++;
507 --cd;
508 }
509
510 *ival = revdata.i;
511
512 return;
513 }
514
515
516
517
518 /* @func ajByteRevLen4u *******************************************************
519 **
520 ** Reverses the byte order in a 4 byte integer.
521 **
522 ** Intended for cases where the number of bytes is known, for
523 ** example when reading a binary file.
524 **
525 ** @param [u] ival [ajuint*] Integer in wrong byte order.
526 ** Returned in correct order.
527 ** @return [void]
528 **
529 ** @release 6.2.0
530 ** @@
531 ******************************************************************************/
532
ajByteRevLen4u(ajuint * ival)533 void ajByteRevLen4u(ajuint* ival)
534 {
535 union lbytes
536 {
537 char chars[4];
538 ajuint i;
539 } data, revdata;
540
541 char* cs;
542 char* cd;
543 ajint i;
544
545 data.i = *ival;
546 cs = data.chars;
547 cd = &revdata.chars[3];
548
549 for(i=0; i < 4; i++)
550 {
551 *cd = *cs++;
552 --cd;
553 }
554
555 *ival = revdata.i;
556
557 return;
558 }
559
560
561
562
563 /* @func ajByteRevLen8 ********************************************************
564 **
565 ** Reverses the byte order in an 8 byte long.
566 **
567 ** Intended for cases where the number of bytes is known, for
568 ** example when reading a binary file.
569 **
570 ** @param [u] lval [ajlong*] Integer in wrong byte order.
571 ** Returned in correct order.
572 ** @return [void]
573 **
574 ** @release 5.0.0
575 ** @@
576 ******************************************************************************/
577
ajByteRevLen8(ajlong * lval)578 void ajByteRevLen8(ajlong* lval)
579 {
580 union lbytes
581 {
582 char chars[8];
583 ajlong l;
584 } data, revdata;
585
586 char* cs;
587 char* cd;
588 ajint i;
589
590 data.l = *lval;
591 cs = data.chars;
592 cd = &revdata.chars[7];
593
594 for(i=0; i < 8; i++)
595 {
596 *cd = *cs++;
597 --cd;
598 }
599
600 *lval = revdata.l;
601
602 return;
603 }
604
605
606
607
608 /* @func ajByteRevLen8u *******************************************************
609 **
610 ** Reverses the byte order in an 8 byte long.
611 **
612 ** Intended for cases where the number of bytes is known, for
613 ** example when reading a binary file.
614 **
615 ** @param [u] lval [ajulong*] Integer in wrong byte order.
616 ** Returned in correct order.
617 ** @return [void]
618 **
619 ** @release 6.2.0
620 ** @@
621 ******************************************************************************/
622
ajByteRevLen8u(ajulong * lval)623 void ajByteRevLen8u(ajulong* lval)
624 {
625 union lbytes
626 {
627 char chars[8];
628 ajulong l;
629 } data, revdata;
630
631 char* cs;
632 char* cd;
633 ajint i;
634
635 data.l = *lval;
636 cs = data.chars;
637 cd = &revdata.chars[7];
638
639 for(i=0; i < 8; i++)
640 {
641 *cd = *cs++;
642 --cd;
643 }
644
645 *lval = revdata.l;
646
647 return;
648 }
649
650
651
652
653 /* @func ajByteRevLong ********************************************************
654 **
655 ** Reverses the byte order in a long.
656 **
657 ** @param [u] lval [ajlong*] Integer in wrong byte order.
658 ** Returned in correct order.
659 ** @return [void]
660 **
661 ** @release 5.0.0
662 ** @@
663 ******************************************************************************/
664
ajByteRevLong(ajlong * lval)665 void ajByteRevLong(ajlong* lval)
666 {
667 union lbytes
668 {
669 char chars[8];
670 ajlong l;
671 } data, revdata;
672
673 char* cs;
674 char* cd;
675 ajuint i;
676
677 data.l = *lval;
678 cs = data.chars;
679 cd = &revdata.chars[sizeof(ajlong)-1];
680
681 for(i=0; i < sizeof(ajlong); i++)
682 {
683 *cd = *cs++;
684 --cd;
685 }
686
687 *lval = revdata.l;
688
689 return;
690 }
691
692
693
694
695 /* @func ajByteRevShort *******************************************************
696 **
697 ** Reverses the byte order in a short integer.
698 **
699 ** @param [u] sval [ajshort*] Short integer in wrong byte order.
700 ** Returned in correct order.
701 ** @return [void]
702 **
703 ** @release 5.0.0
704 ** @@
705 ******************************************************************************/
706
ajByteRevShort(ajshort * sval)707 void ajByteRevShort(ajshort* sval)
708 {
709 union lbytes
710 {
711 char chars[8];
712 short s;
713 } data, revdata;
714
715 char* cs;
716 char* cd;
717 ajuint i;
718
719 data.s = *sval;
720 cs = data.chars;
721 cd = &revdata.chars[sizeof(ajshort)-1];
722
723 for(i=0; i < sizeof(ajshort); i++)
724 {
725 *cd = *cs++;
726 --cd;
727 }
728
729 *sval = revdata.s;
730
731 return;
732 }
733
734
735
736
737 /* @func ajByteRevUint ********************************************************
738 **
739 ** Reverses the byte order in an unsigned integer.
740 **
741 ** @param [u] ival [ajuint*] Unsigned integer in wrong byte order.
742 ** Returned in correct order.
743 ** @return [void]
744 **
745 ** @release 5.0.0
746 ** @@
747 ******************************************************************************/
748
ajByteRevUint(ajuint * ival)749 void ajByteRevUint(ajuint* ival)
750 {
751 union lbytes
752 {
753 char chars[8];
754 ajuint i;
755 } data, revdata;
756
757 char* cs;
758 char* cd;
759 ajuint i;
760
761 data.i = *ival;
762 cs = data.chars;
763 cd = &revdata.chars[sizeof(ajuint)-1];
764
765 for(i=0; i < sizeof(ajuint); i++)
766 {
767 *cd = *cs++;
768 --cd;
769 }
770
771 *ival = revdata.i;
772
773 return;
774 }
775
776
777
778
779 /* @func ajByteRevUlong *******************************************************
780 **
781 ** Reverses the byte order in an unsigned long.
782 **
783 ** @param [u] lval [ajulong*] Integer in wrong byte order.
784 ** Returned in correct order.
785 ** @return [void]
786 **
787 ** @release 6.4.0
788 ** @@
789 ******************************************************************************/
790
ajByteRevUlong(ajulong * lval)791 void ajByteRevUlong(ajulong* lval)
792 {
793 union lbytes
794 {
795 char chars[8];
796 ajulong l;
797 } data, revdata;
798
799 char* cs;
800 char* cd;
801 ajuint i;
802
803 data.l = *lval;
804 cs = data.chars;
805 cd = &revdata.chars[sizeof(ajulong)-1];
806
807 for(i=0; i < sizeof(ajulong); i++)
808 {
809 *cd = *cs++;
810 --cd;
811 }
812
813 *lval = revdata.l;
814
815 return;
816 }
817
818
819
820
821 /* @datasection [none] Miscellaneous utility functions ***********************
822 **
823 ** Miscellaneous utility functions.
824 **
825 ** @nam2rule Util Miscellaneous utility functions.
826 **
827 ******************************************************************************/
828
829
830
831
832 /* @section Miscellaneous utility functions ***********************************
833 **
834 ** Miscellaneous utility functions.
835 **
836 ** @fdata [none]
837 **
838 ** @nam3rule Base64 Base-64 encode/decode functions
839 ** @nam4rule Decode Base-64 decode
840 ** @nam4rule Encode Base-64 encode
841 ** @nam3rule Catch Dummy function to be called in special cases so
842 ** it can be used when debugging in GDB.
843 ** @nam3rule Get Retrieve system information
844 ** @nam4rule GetBigendian Tests whether the host system uses big endian
845 ** byte order.
846 ** @nam4rule GetUid Returns the user's userid.
847 **
848 ** @nam3rule Loginfo If a log file is in use, writes run details to
849 ** end of file.
850 ** @suffix C Character string input
851 **
852 ** @argrule GetUid Puid [AjPStr*] User's userid
853 ** @argrule Decode Pdest [AjPStr*] Decoded string
854 ** @argrule Decode src [const char*] Encoded input string
855 ** @argrule Encode Pdest [AjPStr*] Decoded string
856 ** @argrule Encode size [size_t] Length of input string
857 ** @argrule Encode src [const unsigned char*] Input string
858 **
859 ** @valrule * [void]
860 ** @valrule *Decode [size_t] Length of encoded string
861 ** @valrule *Encode [AjBool] True if operation was successful.
862 ** @valrule *Get [AjBool] True if operation was successful.
863 **
864 ** @fcategory misc
865 **
866 ******************************************************************************/
867
868
869
870
871 /* @func ajUtilBase64DecodeC **************************************************
872 **
873 ** Decode a base 64 string
874 **
875 ** @param [w] Pdest [AjPStr*] Decoded string
876 ** @param [r] src [const char*] source base64 string
877 ** @return [size_t] Length of decoded string (zero if decode error)
878 **
879 ** @release 6.4.0
880 ** @@
881 ******************************************************************************/
882
ajUtilBase64DecodeC(AjPStr * Pdest,const char * src)883 size_t ajUtilBase64DecodeC(AjPStr *Pdest, const char *src)
884 {
885 unsigned char *buf = NULL;
886 size_t srclen;
887 size_t i,j;
888 char c1 = 'A';
889 char c2 = 'A';
890 char c3 = 'A';
891 char c4 = 'A';
892 unsigned char b1 = 0;
893 unsigned char b2 = 0;
894 unsigned char b3 = 0;
895 unsigned char b4 = 0;
896
897 if(!src)
898 return 0;
899
900 if(!*src)
901 return 0;
902
903 if(!Pdest)
904 return 0;
905
906 if(!*Pdest)
907 *Pdest = ajStrNew();
908
909 ajStrSetClear(Pdest);
910
911 srclen = strlen(src);
912
913 buf = (unsigned char *) ajCharNewRes(srclen);
914
915 /* Ignore non-base64 chars */
916 for(i = 0, j = 0; src[i]; ++i)
917 if(utilIsBase64(src[i]))
918 buf[j++] = src[i];
919
920 for(i = 0; i < j; i += 4)
921 {
922 c1 = buf[i];
923
924 if(i+1 < j)
925 c2 = buf[i+1];
926
927 if(i+2 < j)
928 c3 = buf[i+2];
929
930 if(i+3 < j)
931 c4 = buf[i+3];
932
933
934 b1 = utilBase64Decode(c1);
935 b2 = utilBase64Decode(c2);
936 b3 = utilBase64Decode(c3);
937 b4 = utilBase64Decode(c4);
938
939 ajStrAppendK(Pdest, ((b1<<2)|(b2>>4)));
940
941 if(c3 != '=')
942 ajStrAppendK(Pdest, (((b2&0xf)<<4)|(b3>>2)));
943
944 if(c4 != '=')
945 ajStrAppendK(Pdest, (((b3&0x3)<<6)|b4));
946 }
947
948 AJFREE(buf);
949
950 return ajStrGetLen(*Pdest);
951
952 }
953
954
955
956
957 /* @func ajUtilBase64EncodeC **************************************************
958 **
959 ** Decode a base 64 string
960 **
961 ** @param [u] Pdest [AjPStr*] Encoded string
962 ** @param [r] size [size_t] Size of data to encode
963 ** @param [r] src [const unsigned char *] source data
964 ** @return [AjBool] True on success
965 **
966 ** @release 6.4.0
967 ** @@
968 ******************************************************************************/
969
ajUtilBase64EncodeC(AjPStr * Pdest,size_t size,const unsigned char * src)970 AjBool ajUtilBase64EncodeC(AjPStr *Pdest, size_t size, const unsigned char *src)
971 {
972 size_t i;
973 unsigned char b1 = 0;
974 unsigned char b2 = 0;
975 unsigned char b3 = 0;
976 unsigned char b4 = 0;
977 unsigned char b5 = 0;
978 unsigned char b6 = 0;
979 unsigned char b7 = 0;
980
981 if(!src)
982 return ajFalse;
983
984 if(!Pdest)
985 return ajFalse;
986
987 if(!*Pdest)
988 return ajFalse;
989
990 if(!size)
991 size = strlen((const char *)src);
992
993
994 for(i = 0; i < size; i += 3)
995 {
996 b1 = src[i];
997
998 if(i+1 < size)
999 b2 = src[i+1];
1000
1001 if(i+2 < size)
1002 b3 = src[i+2];
1003
1004 b4 = b1 >> 2;
1005 b5 = ((b1 & 0x3) << 4) | (b2 >> 4);
1006 b6 = ((b2 & 0xf) << 2) | (b3 >> 6);
1007 b7 = b3 & 0x3f;
1008
1009 ajStrAppendK(Pdest, utilBase64Encode(b4));
1010 ajStrAppendK(Pdest, utilBase64Encode(b5));
1011
1012 if(i+1 < size)
1013 ajStrAppendK(Pdest, utilBase64Encode(b6));
1014 else
1015 ajStrAppendK(Pdest, '=');
1016
1017 if(i+2 < size)
1018 ajStrAppendK(Pdest, utilBase64Encode(b7));
1019 else
1020 ajStrAppendK(Pdest, '=');
1021 }
1022
1023 return ajTrue;
1024 }
1025
1026
1027
1028
1029 /* @funcstatic utilIsBase64 ***************************************************
1030 **
1031 ** Test for valid base 64 character
1032 **
1033 ** @param [r] c [char] Character
1034 ** @return [AjBool] True if valid base64 character
1035 **
1036 ** @release 6.4.0
1037 ** @@
1038 ******************************************************************************/
1039
utilIsBase64(char c)1040 static AjBool utilIsBase64(char c)
1041 {
1042
1043 if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
1044 (c >= '0' && c <= '9') || (c == '+') ||
1045 (c == '/') || (c == '='))
1046 return ajTrue;
1047
1048 return ajFalse;
1049 }
1050
1051
1052
1053
1054 /* @funcstatic utilBase64Encode ***********************************************
1055 **
1056 ** Encode one byte to base 64
1057 **
1058 ** @param [r] u [unsigned char] Character
1059 ** @return [char] Encoded character
1060 **
1061 ** @release 6.4.0
1062 ** @@
1063 ******************************************************************************/
1064
utilBase64Encode(unsigned char u)1065 static char utilBase64Encode(unsigned char u)
1066 {
1067
1068 if(u < 26)
1069 return 'A' + u;
1070
1071 if(u < 52)
1072 return 'a' + (u-26);
1073
1074 if(u < 62)
1075 return '0' + (u-52);
1076
1077 if(u == 62)
1078 return '+';
1079
1080 return '/';
1081 }
1082
1083
1084
1085
1086 /* @funcstatic utilBase64Decode ***********************************************
1087 **
1088 ** Decode one byte from base 64
1089 **
1090 ** @param [r] c [char] Character
1091 ** @return [unsigned char] Decoded character
1092 **
1093 ** @release 6.4.0
1094 ** @@
1095 ******************************************************************************/
1096
utilBase64Decode(char c)1097 static unsigned char utilBase64Decode(char c)
1098 {
1099
1100 if(c >= 'A' && c <= 'Z')
1101 return(c - 'A');
1102
1103 if(c >= 'a' && c <= 'z')
1104 return(c - 'a' + 26);
1105
1106 if(c >= '0' && c <= '9')
1107 return(c - '0' + 52);
1108
1109 if(c == '+')
1110 return 62;
1111
1112 return 63;
1113 }
1114
1115
1116
1117
1118 /* @func ajUtilCatch **********************************************************
1119 **
1120 ** Dummy function to be called in special cases so it can be used when
1121 ** debugging in GDB.
1122 **
1123 ** To use, simply put a call to ajUtilCatch() into your code, and use
1124 ** "break ajUtilCatch" in gdb to get a traceback.
1125 **
1126 ** @return [void]
1127 **
1128 ** @release 2.5.0
1129 ** @@
1130 ******************************************************************************/
1131
ajUtilCatch(void)1132 void ajUtilCatch(void)
1133 {
1134 static ajint calls = 0;
1135
1136 calls = calls + 1;
1137
1138 return;
1139 }
1140
1141
1142
1143
1144 /* @func ajUtilGetBigendian ***************************************************
1145 **
1146 ** Tests whether the host system uses big endian byte order.
1147 **
1148 ** @return [AjBool] ajTrue if host is big endian.
1149 **
1150 ** @release 5.0.0
1151 ** @@
1152 ******************************************************************************/
1153
ajUtilGetBigendian(void)1154 AjBool ajUtilGetBigendian(void)
1155 {
1156 static union lbytes
1157 {
1158 char chars[sizeof(ajint)];
1159 ajint i;
1160 } data;
1161
1162 if(!utilBigendCalled)
1163 {
1164 utilBigendCalled = 1;
1165 data.i = 0;
1166 data.chars[0] = '\1';
1167
1168 if(data.i == 1)
1169 utilBigendian = ajFalse;
1170 else
1171 utilBigendian = ajTrue;
1172 }
1173
1174 return utilBigendian;
1175 }
1176
1177
1178
1179
1180 /* @func ajUtilGetUid *********************************************************
1181 **
1182 ** Returns the user's userid
1183 **
1184 ** @param [w] Puid [AjPStr*] String to return result
1185 ** @return [AjBool] ajTrue on success
1186 **
1187 ** @release 5.0.0
1188 ** @@
1189 ******************************************************************************/
1190
ajUtilGetUid(AjPStr * Puid)1191 AjBool ajUtilGetUid(AjPStr* Puid)
1192 {
1193 #ifndef WIN32
1194 ajint uid;
1195 struct passwd* pwd;
1196
1197 ajDebug("ajUtilUid\n");
1198
1199 uid = getuid();
1200
1201 if(!uid)
1202 {
1203 ajStrAssignClear(Puid);
1204
1205 return ajFalse;
1206 }
1207
1208 ajDebug(" uid: %d\n", uid);
1209 pwd = getpwuid(uid);
1210
1211 if(!pwd)
1212 {
1213 ajStrAssignClear(Puid);
1214
1215 return ajFalse;
1216 }
1217
1218 ajDebug(" pwd: '%s'\n", pwd->pw_name);
1219
1220 ajStrAssignC(Puid, pwd->pw_name);
1221
1222 return ajTrue;
1223
1224 #else /* WIN32 */
1225 char nameBuf[UNLEN+1];
1226 DWORD nameLen = UNLEN+1;
1227
1228 ajDebug("ajUtilUid\n");
1229
1230 if (GetUserName(nameBuf, &nameLen))
1231 {
1232 ajDebug(" pwd: '%s'\n", nameBuf);
1233 ajStrAssignC(Puid, nameBuf);
1234
1235 return ajTrue;
1236 }
1237
1238 ajStrAssignC(Puid, "");
1239
1240 return ajFalse;
1241 #endif /* !WIN32 */
1242 }
1243
1244
1245
1246
1247 /* @func ajUtilLoginfo ********************************************************
1248 **
1249 ** If a log file is in use, writes run details to end of file.
1250 **
1251 ** @return [void]
1252 **
1253 ** @release 5.0.0
1254 ** @@
1255 ******************************************************************************/
1256
ajUtilLoginfo(void)1257 void ajUtilLoginfo(void)
1258 {
1259 AjPFile logf;
1260 AjPStr logfname = NULL;
1261 AjPStr uids = NULL;
1262 AjPTime today = NULL;
1263 double walltime;
1264 double cputime;
1265
1266 today = ajTimeNewTodayFmt("log");
1267
1268 if(ajNamGetValueC("logfile", &logfname))
1269 {
1270 logf = ajFileNewOutappendNameS(logfname);
1271
1272 if(!logf)
1273 return;
1274
1275 walltime = ajTimeDiff(ajTimeRefToday(),today);
1276 cputime = ajClockSeconds();
1277
1278 if(walltime < cputime)
1279 walltime = cputime; /* avoid reporting 0.0 if cpu time appears */
1280
1281 ajUtilGetUid(&uids),
1282 ajFmtPrintF(logf, "%S\t%S\t%D\t%.1f\t%.1f\n",
1283 ajUtilGetProgram(),
1284 uids,
1285 today,
1286 cputime, walltime);
1287 ajStrDel(&uids);
1288 ajStrDel(&logfname);
1289 ajFileClose(&logf);
1290 }
1291
1292
1293 ajTimeDel(&today);
1294
1295 return;
1296 }
1297
1298
1299
1300
1301 /* @section provenance ********************************************************
1302 **
1303 ** Functions providing information about the run-time environment
1304 **
1305 ** @fdata [none]
1306 **
1307 ** @nam3rule Get Return data as a string
1308 ** @nam4rule GetCmdline Return the full commandline equivalent
1309 ** @nam4rule GetInputs Return the full commandline equivalent
1310 ** @nam4rule GetProgram Return the program name
1311 **
1312 ** @valrule * [const AjPStr]
1313 ** @fcategory misc
1314 **
1315 ******************************************************************************/
1316
1317
1318
1319
1320 /* @func ajUtilGetCmdline *****************************************************
1321 **
1322 ** Returns the original command line as qualifiers and values with newline
1323 ** delimiters
1324 **
1325 ** @return [const AjPStr] Commandline with newlines between qualifiers
1326 ** and parameters
1327 **
1328 ** @release 6.2.0
1329 ******************************************************************************/
1330
ajUtilGetCmdline(void)1331 const AjPStr ajUtilGetCmdline (void)
1332 {
1333 return acdArgSave;
1334 }
1335
1336
1337
1338
1339 /* @func ajUtilGetInputs ******************************************************
1340 **
1341 ** Returns the user non-default inputs in commandline form
1342 **
1343 ** @return [const AjPStr] Commandline with newlines between qualifiers
1344 ** and parameters
1345 **
1346 ** @release 6.2.0
1347 ******************************************************************************/
1348
ajUtilGetInputs(void)1349 const AjPStr ajUtilGetInputs (void)
1350 {
1351 return acdInputSave;
1352 }
1353
1354
1355
1356
1357 /* @func ajUtilGetProgram *****************************************************
1358 **
1359 ** Returns the application (program) name from the ACD definition.
1360 **
1361 ** @return [const AjPStr] Program name
1362 **
1363 ** @release 6.2.0
1364 ** @@
1365 ******************************************************************************/
1366
ajUtilGetProgram(void)1367 const AjPStr ajUtilGetProgram(void)
1368 {
1369 return acdProgram;
1370 }
1371
1372
1373
1374
1375 #ifdef AJ_COMPILE_DEPRECATED_BOOK
1376 #endif /* AJ_COMPILE_DEPRECATED_BOOK */
1377
1378
1379
1380
1381
1382 #ifdef AJ_COMPILE_DEPRECATED
1383 /* @obsolete ajUtilRevInt
1384 ** @rename ajByteRevInt
1385 */
1386
ajUtilRevInt(ajint * ival)1387 __deprecated void ajUtilRevInt(ajint* ival)
1388 {
1389 ajByteRevInt(ival);
1390
1391 return;
1392 }
1393
1394
1395
1396
1397 /* @obsolete ajUtilRev2
1398 ** @rename ajByteRev2
1399 */
1400
ajUtilRev2(ajshort * sval)1401 __deprecated void ajUtilRev2(ajshort* sval)
1402 {
1403 ajByteRevLen2(sval);
1404
1405 return;
1406 }
1407
1408
1409
1410
1411 /* @obsolete ajUtilRev4
1412 ** @rename ajByteRevLen4
1413 */
1414
ajUtilRev4(ajint * ival)1415 __deprecated void ajUtilRev4(ajint* ival)
1416 {
1417 ajByteRevLen4(ival);
1418
1419 return;
1420 }
1421
1422
1423
1424
1425 /* @obsolete ajUtilRev8
1426 ** @rename ajByteRevLen8
1427 */
1428
ajUtilRev8(ajlong * lval)1429 __deprecated void ajUtilRev8(ajlong* lval)
1430 {
1431 ajByteRevLen8(lval);
1432 }
1433
1434
1435
1436
1437 /* @obsolete ajUtilRevLong
1438 ** @rename ajByteRevLong
1439 */
1440
ajUtilRevLong(ajlong * lval)1441 __deprecated void ajUtilRevLong(ajlong* lval)
1442 {
1443 ajByteRevLong(lval);
1444
1445 return;
1446 }
1447
1448
1449
1450
1451 /* @obsolete ajUtilRevShort
1452 ** @rename ajByteRevShort
1453 */
1454
ajUtilRevShort(ajshort * sval)1455 __deprecated void ajUtilRevShort(ajshort* sval)
1456 {
1457 ajByteRevShort(sval);
1458 }
1459
1460
1461
1462
1463 /* @obsolete ajUtilRevUint
1464 ** @rename ajByteRevUint
1465 */
1466
ajUtilRevUint(ajuint * ival)1467 __deprecated void ajUtilRevUint(ajuint* ival)
1468 {
1469 ajByteRevUint(ival);
1470 }
1471
1472
1473
1474
1475 /* @obsolete ajUtilBigendian
1476 ** @rename ajUtilGetBigendian
1477 */
ajUtilBigendian(void)1478 __deprecated AjBool ajUtilBigendian(void)
1479 {
1480 return ajUtilGetBigendian();
1481 }
1482
1483
1484
1485
1486 /* @obsolete ajUtilUid
1487 ** @rename ajUtilGetUid
1488 */
1489
ajUtilUid(AjPStr * dest)1490 __deprecated AjBool ajUtilUid(AjPStr* dest)
1491 {
1492 return ajUtilGetUid(dest);
1493 }
1494
1495
1496
1497
1498 /* @obsolete ajLogInfo
1499 ** @rename ajUtilLoginfo
1500 */
1501
ajLogInfo(void)1502 __deprecated void ajLogInfo(void)
1503 {
1504 ajUtilLoginfo();
1505
1506 return;
1507 }
1508
1509
1510
1511
1512 /* @obsolete ajAcdGetCmdline
1513 ** @rename ajUtilGetCmdline
1514 */
ajAcdGetCmdline(void)1515 __deprecated const AjPStr ajAcdGetCmdline (void)
1516 {
1517 return ajUtilGetCmdline();
1518 }
1519
1520
1521
1522
1523 /* @obsolete ajAcdGetInputs
1524 ** @rename ajUtilGetInputs
1525 */
1526
ajAcdGetInputs(void)1527 __deprecated const AjPStr ajAcdGetInputs (void)
1528 {
1529 return ajUtilGetInputs();
1530 }
1531
1532
1533
1534
1535 /* @obsolete ajAcdProgramS
1536 ** @remove Use ajAcdGetProgram
1537 */
1538
ajAcdProgramS(AjPStr * pgm)1539 __deprecated void ajAcdProgramS(AjPStr* pgm)
1540 {
1541 ajStrAssignS(pgm, acdProgram);
1542 return;
1543 }
1544
1545
1546
1547
1548 /* @obsolete ajAcdGetProgram
1549 ** @rename ajUtilGetProgram
1550 */
ajAcdGetProgram(void)1551 __deprecated const AjPStr ajAcdGetProgram(void)
1552 {
1553 return ajUtilGetProgram();
1554 }
1555
1556
1557
1558
1559 /* @obsolete ajAcdProgram
1560 ** @remove Use ajAcdGetProgram
1561 */
1562
ajAcdProgram(void)1563 __deprecated const char* ajAcdProgram(void)
1564 {
1565 return ajStrGetPtr(acdProgram);
1566 }
1567
1568 #endif /* AJ_COMPILE_DEPRECATED */
1569