src/server/util/util.c

changeset 102
136a76e293b5
parent 99
b9a6af0ae41a
child 103
d3b514e2ddbd
equal deleted inserted replaced
101:7fbcdbad0baa 102:136a76e293b5
527 a.pool = pool; 527 a.pool = pool;
528 return a; 528 return a;
529 } 529 }
530 530
531 531
532 // new - code in parts from params.cpp 532 // new - code from params.cpp
533 NSAPI_PUBLIC pblock* util_parse_param(pool_handle_t *pool, char *query) { 533 NSAPI_PUBLIC pblock* util_parse_param(pool_handle_t *pool, char *query) {
534 pblock *pb = pblock_create_pool(pool, 32); 534 pblock *pb = pblock_create_pool(pool, 32);
535 if(!pb) { 535 if(!pb) {
536 return NULL; 536 return NULL;
537 } 537 }
598 memcpy(newstring.ptr, s.ptr, s.length); 598 memcpy(newstring.ptr, s.ptr, s.length);
599 } 599 }
600 600
601 return newstring; 601 return newstring;
602 } 602 }
603
604
605
606 /* ---------------------------- util_mstr2num ----------------------------- */
607
608 static const int MSTR2NUM_HT_MASK = 0xf;
609
610 static const struct {
611 unsigned ucmstr; // Uppercase 3 character month string in a machine word
612 int mnum; // 0-based month number for this month string
613 } MSTR2NUM_HT[MSTR2NUM_HT_MASK + 1] = {
614 { 'A' << 16 | 'P' << 8 | 'R', 3 },
615 { 'S' << 16 | 'E' << 8 | 'P', 8 },
616 { 'M' << 16 | 'A' << 8 | 'Y', 4 },
617 { 0, -1 },
618 { 'M' << 16 | 'A' << 8 | 'R', 2 },
619 { 'F' << 16 | 'E' << 8 | 'B', 1 },
620 { 0, -1 },
621 { 'D' << 16 | 'E' << 8 | 'C', 11 },
622 { 'O' << 16 | 'C' << 8 | 'T', 9 },
623 { 'J' << 16 | 'U' << 8 | 'N', 5 },
624 { 0, -1 },
625 { 'A' << 16 | 'U' << 8 | 'G', 7 },
626 { 'J' << 16 | 'A' << 8 | 'N', 0 },
627 { 'J' << 16 | 'U' << 8 | 'L', 6 },
628 { 0, -1 },
629 { 'N' << 16 | 'O' << 8 | 'V', 10 }
630 };
631
632 static inline int _mstr2num(const char *s)
633 {
634 const unsigned char *mstr = (const unsigned char *) s;
635
636 /*
637 * We compute ucmstr (an uppercase 3 character month string stored in a
638 * machine word) and hash (a perfect hash based on the last 2 characters
639 * of the 3 character uppercase month string) from the input string s.
640 * Note that each character from the input string is masked by 0xdf; in
641 * ASCII, this has the effect of converting alphabetic characters to
642 * uppercase while 1. not changing any nonalphabetic characters into
643 * alphabetic characters and 2. leaving any nul characters unchanged.
644 *
645 * The hash value is used as an index into the MSTR2NUM_HT[] hash table.
646 * If the ucmstr at that index matches our computed ucmstr, the mnum at
647 * that index is the 0-based month number corresponding to the input
648 * string.
649 *
650 * Note that we never read past the end of the input string and always
651 * return -1 if the input string doesn't begin with a valid 3 character
652 * month string.
653 */
654
655 unsigned char ucmstr0 = mstr[0] & 0xdf;
656 unsigned ucmstr = ucmstr0 << 16;
657 if (ucmstr0 != '\0') {
658 unsigned char ucmstr1 = mstr[1] & 0xdf;
659 ucmstr |= ucmstr1 << 8;
660 if (ucmstr1 != '\0') {
661 unsigned char ucmstr2 = mstr[2] & 0xdf;
662 ucmstr |= ucmstr2;
663
664 unsigned hash = (ucmstr1 >> 2) ^ (ucmstr2 << 1);
665
666 int i = hash & MSTR2NUM_HT_MASK;
667
668 if (MSTR2NUM_HT[i].ucmstr == ucmstr)
669 return MSTR2NUM_HT[i].mnum;
670 }
671 }
672
673 return -1;
674 }
675
676 NSAPI_PUBLIC int util_mstr2num(const char *s)
677 {
678 return _mstr2num(s);
679 }
680
681
682 /* ------------------------- util_str_time_equal -------------------------- */
683
684 /*
685 * Function to compare if two time strings are equal
686 *
687 * Acceptable date formats:
688 * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
689 * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
690 * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
691 *
692 * Return 0 if equal, -1 if not equal.
693 */
694
695 static inline const char * _parse_day_month(const char *p, int *day, int *month)
696 {
697 *day = 0;
698
699 if (*p == ',') {
700 // Parse day and month: ", 06 Nov", ", 06-Nov"
701 p++;
702 if (*p == ' ')
703 p++;
704 while (*p >= '0' && *p <= '9')
705 *day = *day * 10 + (*p++ - '0');
706 if (*p == ' ' || *p == '-')
707 p++;
708 *month = _mstr2num(p);
709 if (*month != -1)
710 p += 3;
711 } else {
712 // Parse month and day: " Nov 6"
713 if (*p == ' ')
714 p++;
715 *month = _mstr2num(p);
716 if (*month != -1)
717 p += 3;
718 while (*p == ' ')
719 p++;
720 while (*p >= '0' && *p <= '9')
721 *day = *day * 10 + (*p++ - '0');
722 }
723
724 return p;
725 }
726
727 static inline void _parse_year_time(const char *p, int *year, const char ** time)
728 {
729 int _year = 0;
730
731 if (*p == '-') {
732 // Parse year and time: "-94 08:49:37"
733 p++;
734 while (*p >= '0' && *p <= '9')
735 _year = _year * 10 + (*p++ - '0');
736 if (_year < 70) {
737 _year += 2000;
738 } else {
739 _year += 1900;
740 }
741 if (*p == ' ')
742 p++;
743 *time = p;
744 } else {
745 // Parse year and time or time and year
746 if (*p == ' ')
747 p++;
748 if (p[0] && p[1] && p[2] == ':') {
749 // Parse time and year: "08:49:37 1994"
750 *time = p;
751 p += 3;
752 while (*p && *p != ' ')
753 p++;
754 if (*p == ' ')
755 p++;
756 while (*p >= '0' && *p <= '9')
757 _year = _year * 10 + (*p++ - '0');
758 } else {
759 // Parse year and time: "1994 08:49:37"
760 while (*p >= '0' && *p <= '9')
761 _year = _year * 10 + (*p++ - '0');
762 if (*p == ' ')
763 p++;
764 *time = p;
765 }
766 }
767
768 *year = _year;
769 }
770
771 NSAPI_PUBLIC int util_str_time_equal(const char *t1, const char *t2)
772 {
773 // Skip leading whitespace and day of week
774 while (isspace(*t1))
775 t1++;
776 while (isalpha(*t1))
777 t1++;
778 while (isspace(*t2))
779 t2++;
780 while (isalpha(*t2))
781 t2++;
782
783 // Day and month: ", 06 Nov", ", 06-Nov", or " Nov 6"
784 int day1;
785 int month1;
786 t1 = _parse_day_month(t1, &day1, &month1);
787 int day2;
788 int month2;
789 t2 = _parse_day_month(t2, &day2, &month2);
790 if (day1 != day2)
791 return -1;
792 if (month1 != month2)
793 return -1;
794
795 // Year and time: " 1994 08:49:37", "-94 08:49:37", or " 08:49:37 1994"
796 int year1;
797 const char *time1;
798 _parse_year_time(t1, &year1, &time1);
799 int year2;
800 const char *time2;
801 _parse_year_time(t2, &year2, &time2);
802 if (year1 != year2)
803 return -1;
804 while (*time1 && *time1 != ' ' && *time1 == *time2) {
805 time1++;
806 time2++;
807 }
808 if (*time2 && *time2 != ' ')
809 return -1;
810
811 return 0;
812 }
813
814
815 /* --------------------------- util_later_than ---------------------------- */
816
817 static int _time_compare(const struct tm *lms, const char *ims)
818 {
819 while (isspace(*ims))
820 ims++;
821 while (isalpha(*ims))
822 ims++;
823
824 int day;
825 int month;
826 ims = _parse_day_month(ims, &day, &month);
827 if (month == -1)
828 return 1;
829
830 int year;
831 const char *time;
832 _parse_year_time(ims, &year, &time);
833
834 int rv;
835
836 rv = (lms->tm_year + 1900) - year;
837 if (rv)
838 return rv;
839
840 rv = lms->tm_mon - month;
841 if (rv)
842 return rv;
843
844 rv = lms->tm_mday - day;
845 if (rv)
846 return rv;
847
848 const char *p = time;
849
850 int hour = 0;
851 while (*p >= '0' && *p <= '9')
852 hour = hour * 10 + (*p++ - '0');
853 if (*p == ':')
854 p++;
855
856 rv = lms->tm_hour - hour;
857 if (rv)
858 return rv;
859
860 int minutes = 0;
861 while (*p >= '0' && *p <= '9')
862 minutes = minutes * 10 + (*p++ - '0');
863 if (*p == ':')
864 p++;
865
866 rv = lms->tm_min - minutes;
867 if (rv)
868 return rv;
869
870 int seconds = 0;
871 while (*p >= '0' && *p <= '9')
872 seconds = seconds * 10 + (*p++ - '0');
873 if (*p == ':')
874 p++;
875
876 rv = lms->tm_sec - seconds;
877 if (rv)
878 return rv;
879
880 return 0;
881 }
882
883 NSAPI_PUBLIC int util_later_than(const struct tm *lms, const char *ims)
884 {
885 /*
886 * Returns 0 if lms later than ims
887 * 0 if ims is malformed
888 * 1 if ims later than lms
889 * 1 if equal
890 */
891
892 return _time_compare(lms, ims) <= 0;
893 }
894
895 NSAPI_PUBLIC int util_time_equal(const struct tm *lms, const char *ims)
896 {
897 return _time_compare(lms, ims) == 0;
898 }
899
900
901 NSAPI_PUBLIC struct tm *
902 util_gmtime(const time_t *clock, struct tm *res)
903 {
904 return gmtime_r(clock, res);
905 }
906

mercurial