Qcert.Basic.Util.RString
Module AsciiOrder <: OrderedTypeFull with Definition t:=ascii.
Definition t:= ascii.
Definition eq := @eq t.
Definition eq_equiv : (Equivalence eq) := eq_equivalence.
Definition eq_dec := ascii_dec.
Definition compare (a b:ascii) : comparison :=
nat_compare (nat_of_ascii a) (nat_of_ascii b).
Definition lt (a b:ascii) := compare a b = Lt.
Lemma lt_strorder : StrictOrder lt.
Lemma lt_compat : Proper (eq ==> eq ==> iff) lt.
Lemma compare_eq_iff a b: compare a b = Eq ↔ a = b.
Lemma compare_spec :
∀ x y : t, CompareSpec (eq x y) (lt x y) (lt y x) (compare x y).
Lemma trichotemy a b : {lt a b} + {eq a b} + {lt b a}.
Definition le (a b:ascii) :=
match compare a b with
| Lt ⇒ True
| Eq ⇒ True
| Gt ⇒ False
end.
Lemma le_lteq : ∀ x y : t, le x y ↔ lt x y ∨ eq x y.
Lemma compare_refl_eq a: compare a a = Eq.
End AsciiOrder.
Module StringOrder <: OrderedTypeFull with Definition t:=string.
Definition t:= string.
Definition eq := @eq t.
Definition eq_equiv : (Equivalence eq) := eq_equivalence.
Definition eq_dec := string_dec.
Fixpoint compare (a:string) (b:string) : comparison :=
match a, b with
| EmptyString, EmptyString ⇒ Eq
| EmptyString, String _ _ ⇒ Lt
| String _ _, EmptyString ⇒ Gt
| String a' a's, String b' b's ⇒
match AsciiOrder.compare a' b' with
| Lt ⇒ Lt
| Eq ⇒ compare a's b's
| Gt ⇒ Gt
end
end.
Definition lt (a b:string) := compare a b = Lt.
Lemma compare_spec :
∀ x y : t, CompareSpec (eq x y) (lt x y) (lt y x) (compare x y).
Lemma trichotemy a b : {lt a b} + {eq a b} + {lt b a}.
Lemma compare_refl_eq a: compare a a = Eq.
Lemma compare_eq_iff a b: compare a b = Eq ↔ a = b.
Instance lt_strorder : StrictOrder lt.
Lemma lt_compat : Proper (eq ==> eq ==> iff) lt.
Program Definition lt_dec (a b:string) : {lt a b} + {¬lt a b}
:= match compare a b with
| Lt ⇒ left _
| Eq ⇒ right _
| Gt ⇒ right _
end.
Definition le (a b:string) :=
match compare a b with
| Lt ⇒ True
| Eq ⇒ True
| Gt ⇒ False
end.
Lemma le_lteq : ∀ x y : t, le x y ↔ lt x y ∨ eq x y.
Program Definition le_dec (a b:string) : {le a b} + {¬le a b}
:= match compare a b with
| Lt ⇒ left _
| Eq ⇒ left _
| Gt ⇒ right _
end.
End StringOrder.
Section ToString.
Fixpoint string_reverse_helper (s:string) (acc:string)
:= match s with
| EmptyString ⇒ acc
| String x xs ⇒ string_reverse_helper xs (String x acc)
end.
Definition string_reverse (s:string) := string_reverse_helper s EmptyString.
Fixpoint string_to_list (s:string) : list ascii
:= match s with
| EmptyString ⇒ nil
| String x xs ⇒ cons x (string_to_list xs)
end.
Fixpoint list_to_string (l:list ascii) : string
:= match l with
| nil ⇒ EmptyString
| cons x xs ⇒ String x (list_to_string xs)
end.
Lemma string_to_list_to_string (s:string) :
list_to_string (string_to_list s) = s.
Lemma list_to_string_to_list (l:list ascii) :
string_to_list (list_to_string l) = l.
Lemma string_to_list_inj (x y:string) :
string_to_list x = string_to_list y → x = y.
Lemma list_to_string_inj (x y:list ascii) :
list_to_string x = list_to_string y → x = y.
Lemma string_reverse_helper_reverse_append s acc:
string_reverse_helper s acc = list_to_string (List.rev_append (string_to_list s) (string_to_list acc)).
Lemma string_reverse_reverse s :
string_reverse s = list_to_string (List.rev (string_to_list s)).
Lemma string_reverse_involutive x : string_reverse (string_reverse x) = x.
Lemma string_reverse_inj x y :
string_reverse x = string_reverse y →
x = y.
Lemma lt_contr1 s1 s2 :
¬StringOrder.lt s1 s2 → ¬StringOrder.lt s2 s1 → StringOrder.eq s1 s2.
Lemma lt_contr2 s1 s2 :
StringOrder.lt s1 s2 → ¬StringOrder.eq s1 s2.
Lemma lt_contr3 s :
StringOrder.lt s s → False.
End ToString.
Fixpoint map_string (f:ascii→ascii) (s:string)
:= match s with
| EmptyString ⇒ EmptyString
| String a s' ⇒ String (f a) (map_string f s')
end.
Fixpoint flat_map_string (f:ascii→string) (s:string)
:= match s with
| EmptyString ⇒ EmptyString
| String a s' ⇒ append (f a) (flat_map_string f s')
end.
Global Instance ascii_dec : EqDec ascii eq
:= ascii_dec.
Section like.
Inductive like_clause :=
| like_literal (literal:string) : like_clause
| like_any_char : like_clause
| like_any_string : like_clause.
Fixpoint make_like_clause (s:string) (escape:option ascii) {struct s}: list like_clause
:= match s with
| EmptyString ⇒ nil
| String "_"%char tail ⇒ like_any_char :: make_like_clause tail escape
| String "%"%char tail ⇒ like_any_string :: make_like_clause tail escape
| other ⇒
(fix make_like_literal_clause (ss:string) (acc:string) {struct ss} : list like_clause
:= match ss with
| EmptyString ⇒ like_literal (string_reverse acc) :: nil
| String "_"%char tail ⇒ like_literal (string_reverse acc) :: like_any_char :: make_like_clause tail escape
| String "%"%char tail ⇒ like_literal (string_reverse acc) :: like_any_string :: make_like_clause tail escape
| String h tail ⇒
if Some h == escape
then
match tail with
| EmptyString ⇒
like_literal (string_reverse (String h acc)) :: nil
| String "_"%char tail ⇒ make_like_literal_clause tail (String "_" acc)
| String "%"%char tail ⇒ make_like_literal_clause tail (String "%" acc)
| String nh ntail ⇒
if Some nh == escape
then make_like_literal_clause ntail (String nh acc)
else
make_like_literal_clause ntail (String nh (String h acc))
end
else
make_like_literal_clause tail (String h acc)
end
) other ""%string
end.
Example make_like_clause_example1 := make_like_clause "hello_there^^^%%" None.
Example make_like_clause_example2 := make_like_clause "hello_there^^^%%" (Some "^"%char).
Fixpoint string_exists_suffix (f:string→bool) (s:string) : bool
:= f s ||
match s with
| EmptyString ⇒ false
| String _ tail ⇒ string_exists_suffix f tail
end.
Fixpoint like_clause_matches_string (pat:list like_clause) (s:string)
:= match pat with
| nil ⇒ s ==b EmptyString
| (like_literal literal)::rest ⇒
andb (prefix literal s)
(like_clause_matches_string rest (substring (String.length literal) (String.length s - String.length literal) s))
| like_any_char::rest ⇒
match s with
| EmptyString ⇒ false
| String _ tail ⇒ like_clause_matches_string rest tail
end
| like_any_string::rest ⇒
string_exists_suffix (like_clause_matches_string rest) s
end.
Definition string_like (str pattern:string) (escape:option ascii) : bool
:= let pat_clause := make_like_clause pattern escape in
like_clause_matches_string pat_clause str.
Example string_like_example1 := string_like "hello there" "hello there" None.
Example string_like_example2 := string_like "hello there" "hello %there" None.
Example string_like_example3 := string_like "hello there" "he%th_re" None.
Example string_like_example4 := string_like "hello there " "he%th_re" None.
Example string_like_example5 := string_like "hello thethare" "he%th_re" None.
Example string_like_example6 := string_like "hello thetheare" "he%th_re" None.
End like.