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 |