core: made format not leak memory; test: added test for format and fmt

This commit is contained in:
hellerve 2017-12-30 20:16:31 +01:00
parent 6a5e73e088
commit 7c9eaeac9f
11 changed files with 86 additions and 23 deletions

View File

@ -3,4 +3,5 @@
(register /= (Fn [Bool Bool] Bool))
(register str (Fn [Bool] String))
(register copy (Fn [&Bool] Bool))
(register format (Fn [&String Bool] String))
)

View File

@ -4,6 +4,7 @@
(register to-int (Fn [Char] Int))
(register from-int (Fn [Int] Char))
(register copy (Fn [&Char] Char))
(register format (Fn [&String Char] String))
(defn random []
(from-int (Int.random)))

View File

@ -39,7 +39,7 @@
(register mod (Fn [Double Double] Double))
(register copy (Fn [(Ref Double)] Double))
(register abs (Fn [Double] Double))
(register format (Fn [String Double] String))
(register format (Fn [&String Double] String))
(defn clamp [min, max, val]
(if (> val max)

View File

@ -11,7 +11,7 @@
(register random-between (λ [Float Float] Float))
(register str (Fn [Float] String))
(register copy (Fn [(Ref Float)] Float))
(register format (Fn [String Float] String))
(register format (Fn [&String Float] String))
(register = (Fn [Float Float] Bool))
(defn /= [x y]

View File

@ -17,9 +17,9 @@
(if (= -1 next)
(if (< 1 (count args))
(macro-error "error in format string: too many arguments to format string")
(list 'format (list 'copy s) (car args)))
(list 'format s (car args)))
(let [slice (String.substring s 0 (+ (inc idx) next))]
(list 'String.append (list 'format (list 'copy slice) (car args))
(list 'String.append (list 'format slice (car args))
(fmt-internal (String.substring s (+ (inc idx) next) len)
(cdr args)))))))))))

View File

@ -22,7 +22,7 @@
(register inc (λ [Int] Int))
(register dec (λ [Int] Int))
(register copy (λ [&Int] Int)) ;; TODO: Should not be needed when refs to value types are auto-converted to non-refs.
(register format (Fn [String Int] String))
(register format (Fn [&String Int] String))
(register safe-add (λ [Int Int (Ref Int)] Bool))
(register safe-sub (λ [Int Int (Ref Int)] Bool))

View File

@ -1,6 +1,6 @@
(definterface = (λ [a a] Bool))
(definterface /= (λ [a a] Bool))
(definterface format (λ [String a] String))
(definterface format (λ [&String a] String))
(definterface zero (λ [] a))
(definterface add-ref (λ [&a &a] a))

View File

@ -23,7 +23,7 @@
(register to-int (λ [Long] Int))
(register from-int (λ [Int] Long))
(register copy (λ [&Long] Long)) ;; TODO: Should not be needed when refs to value types are auto-converted to non-refs.
(register format (Fn [String Long] String))
(register format (Fn [&String Long] String))
(defn /= [x y]
(not (Long.= x y)))

View File

@ -12,7 +12,7 @@
(register chars (Fn [&String] (Array Char)))
(register from-chars (Fn [(Array Char)] String))
(register tail (λ [(Ref String)] String))
(register format (Fn [String String] String))
(register format (Fn [&String &String] String))
(defn /= [a b]
(not (= (the (Ref String) a) b)))

View File

@ -186,10 +186,10 @@ string Int_str(int x) {
return buffer;
}
string Int_format(string str, int x) {
int n = strlen(str) + 32;
string Int_format(string* str, int x) {
int n = strlen(*str) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, str, x);
snprintf(buffer, n+1, *str, x);
return buffer;
}
@ -224,10 +224,10 @@ string Long_str(long x) {
return buffer;
}
string Long_format(string str, long x) {
int n = strlen(str) + 32;
string Long_format(string* str, long x) {
int n = strlen(*str) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, str, x);
snprintf(buffer, n+1, *str, x);
return buffer;
}
@ -297,10 +297,10 @@ char String_char_MINUS_at(string* s, int i) {
return (*s)[i];
}
string String_format(string str, string s) {
int n = strlen(s) + strlen(str);
string String_format(string *str, string *s) {
int n = strlen(*s) + strlen(*str);
string buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, str, s);
snprintf(buffer, n+1, *str, *s);
return buffer;
}
@ -353,6 +353,14 @@ char Char_copy(char *c) {
return *c;
}
string Char_format(string* str, char b) {
int n = strlen(*str) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, *str, b);
return buffer;
}
// Double.toInt : Double -> Int
int Double_to_MINUS_int(double x) {
return (int)x;
@ -470,10 +478,10 @@ double Double_random_MINUS_between(double lower, double upper) {
return lower + diff * r;
}
string Double_format(string s, double x) {
int n = strlen(s) + 32;
string Double_format(string* s, double x) {
int n = strlen(*s) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, s, x);
snprintf(buffer, n+1, *s, x);
return buffer;
}
@ -585,10 +593,10 @@ string Float_str(float x) {
return buffer;
}
string Float_format(string str, float x) {
int n = strlen(str) + 32;
string Float_format(string* str, float x) {
int n = strlen(*str) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, str, x);
snprintf(buffer, n+1, *str, x);
return buffer;
}
@ -615,6 +623,13 @@ string Bool_str(bool b) {
}
}
string Bool_format(string* str, bool b) {
int n = strlen(*str) + 32;
char *buffer = CARP_MALLOC(n+1);
snprintf(buffer, n+1, *str, b);
return buffer;
}
void System_exit(int code) {
exit(code);
}

46
test/format.carp Normal file
View File

@ -0,0 +1,46 @@
(load "Test.carp")
(use Test)
(defn main []
(with-test test
(assert-equal test
"c"
&(format "%c" \c)
"format works on chars"
)
(assert-equal test
"1"
&(format "%d" true)
"format works on bools"
)
(assert-equal test
"10"
&(format "%d" 10)
"format works on ints"
)
(assert-equal test
"10"
&(format "%ld" 10)
"format works on longs"
)
(assert-equal test
"10.0"
&(format "%.1f" 10.0f)
"format works on floats"
)
(assert-equal test
"10.050"
&(format "%2.3f" 10.05)
"format works on doubles"
)
(assert-equal test
"outside string: inside string :outside string"
&(format "outside string: %s :outside string" "inside string")
"format works on strings"
)
(assert-equal test
"10 %% 12.0 yay"
&(fmt "%d %% %.1f %s" 10 12.0 "yay")
"fmt macro works"
)
(print-test-results test)))