Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Common Lispでは同じパッケージ内で同名関数を再定義すると警
すべての出力ファイル名生成関数が`opts`を第一引数として受け取るAPIに統一され、
テストスイートでの検証とバイナリビルドでの動作確認も完了。

#### GIFモードのオプション制限強化
#### GIFモードのオプション制限強化 ✅ **完了**
GIFモードで`--input`オプションとの組み合わせエラーが適切に処理されていない問題を修正:

**問題:**
Expand Down
5 changes: 2 additions & 3 deletions src/package.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
:validate-codec
:validate-mono
:validate-speed
:parse-speed-float
:validate-options
:validate-output
:dispatch-validation

;; util.lisp
:input-extension
:parse-float
:safe-parse-float
:parse-number
:parse-number-or-exit
:parse-frame-rate
:resolution-from-key
:parse-dimensions
Expand Down
34 changes: 17 additions & 17 deletions src/util.lisp
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
(in-package :visp)

(defun parse-float (str)
"Parse a string as a float. Returns NIL if not parsable."
(handler-case
(let ((val (read-from-string str)))
(if (floatp val)
val
(coerce val 'float))) ; int → float に変換
(error () nil)))
(defun parse-number (str)
"Parse string to number. Returns nil on failure. Secure version with *read-eval* disabled."
(let ((*read-eval* nil))
(handler-case
(let ((result (with-input-from-string (s str) (read s))))
(if (numberp result) result nil))
(error () nil))))

(defun parse-number-or-exit (str &optional (context "number"))
"Parse string to number. Exit with error message on failure."
(let ((result (parse-number str)))
(unless result
(format t "~a Invalid ~a value: ~a~%" (log-tag "error") context str)
(uiop:quit 1))
result))

(defun safe-parse-float (str)
(let ((val (parse-float str)))
(if val
val
(progn
(format t "~a Invalid float value: ~a~%" (log-tag "error") str)
(uiop:quit 1)))))

(defun parse-frame-rate (rate)
(handler-case
(let ((parts (uiop:split-string rate :separator "/")))
(if (= (length parts) 2)
(/ (parse-float (first parts)) (parse-float (second parts)))
(parse-float rate)))
(/ (parse-number (first parts)) (parse-number (second parts)))
(parse-number rate)))
(error () nil)))

(defun input-extension (filename)
Expand Down
13 changes: 1 addition & 12 deletions src/validate.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -285,23 +285,12 @@
(when (member codec '("prores" "hap") :test #'string=)
(error "The --mono option is not supported with codec ~A." codec)))))

(defun parse-speed-float (string)
"Parse a string as a float for speed validation. Throws an error if not a valid number."
(let ((*read-eval* nil)
(result nil))
(with-input-from-string (s string)
(setf result (read s)))
;; 読み取った結果が数値でない場合はエラー
(unless (numberp result)
(error "Not a valid number: ~a" string))
result))

(defun validate-speed (opts)
"Validate that --speed is a positive number if specified."
(let ((speed (visp-options-speed opts)))
(when speed
(let ((speedf (handler-case (parse-speed-float speed)
(error () nil))))
(let ((speedf (parse-number speed)))
;; speedは必ず0より大きい数値
(unless (and (numberp speedf) (> speedf 0))
(format t "~a --speed must be a positive number, but got '~a'.~%"
Expand Down
6 changes: 3 additions & 3 deletions src/video.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
(parts (uiop:split-string output :separator "/")))
(cond
((= (length parts) 2)
(/ (safe-parse-float (first parts)) (safe-parse-float (second parts))))
(/ (parse-number-or-exit (first parts) "fps") (parse-number-or-exit (second parts) "fps")))
((= (length parts) 1)
(safe-parse-float (first parts)))
(parse-number-or-exit (first parts) "fps"))
(t
(format t "~a Failed to extract FPS from input: ~a~%" (log-tag "error") output)
(uiop:quit 1)))))
Expand Down Expand Up @@ -65,7 +65,7 @@
`(:width ,(when width (parse-integer (cdr width)))
:height ,(when height (parse-integer (cdr height)))
:fps ,(when rate (parse-frame-rate (cdr rate)))
:duration ,(when duration (parse-float (cdr duration)))
:duration ,(when duration (parse-number (cdr duration)))
:has-audio ,has-audio
:audio-codec ,(if has-audio audio-codec nil)
:video-codec ,(when codec (cdr codec))))))
Expand Down
22 changes: 11 additions & 11 deletions t/test-validate.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
(:use :cl :rove)
(:import-from :visp
:make-visp-options
:parse-speed-float
:parse-number
:validate-speed
:validate-gif-mode))

(in-package :visp.test.validate)

(deftest parse-speed-float-tests
(testing "Parses valid float strings"
(ok (= (visp:parse-speed-float "2.0") 2.0))
(ok (= (visp:parse-speed-float "0.5") 0.5))
(ok (= (visp:parse-speed-float "1") 1.0))
(ok (= (visp:parse-speed-float "3.14159") 3.14159)))
(deftest parse-number-tests
(testing "Parses valid number strings"
(ok (= (visp:parse-number "2.0") 2.0))
(ok (= (visp:parse-number "0.5") 0.5))
(ok (= (visp:parse-number "1") 1.0))
(ok (= (visp:parse-number "3.14159") 3.14159)))

(testing "Throws error for invalid strings"
(ok (signals (visp:parse-speed-float "invalid")))
(ok (signals (visp:parse-speed-float "abc")))
(ok (signals (visp:parse-speed-float "")))))
(testing "Returns NIL for invalid strings"
(ok (null (visp:parse-number "invalid")))
(ok (null (visp:parse-number "abc")))
(ok (null (visp:parse-number "")))))

(deftest validate-speed-tests
(testing "Validates positive float values"
Expand Down