[c++ options] Restore forward & backward compatibility, fix crash.

Store Number Range option values as a pair '(percentage . value) or '(pixels .
value) depending on the size of value as 4.x and earlier expect. When reading a
stored number range option handle the possibility that value is fixed
point (e.g. 50.0) as 4.x and earlier emit, avoiding a crash.
This commit is contained in:
John Ralls 2023-02-23 13:32:46 -08:00
parent 0780cfbfd2
commit 408b5ec216
2 changed files with 40 additions and 12 deletions

View File

@ -1080,6 +1080,18 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
return scm_cons(desig, scm_from_int(val));
}
static SCM
get_scm_value(const GncOptionRangeValue<double>& option)
{
return scm_from_double(option.get_value());
}
static SCM
get_scm_default_value(const GncOptionRangeValue<double>& option)
{
return scm_from_double(option.get_default_value());
}
static SCM
get_scm_value(const GncOptionDateValue& option)
{
@ -1285,14 +1297,14 @@ inline SCM return_scm_value(ValueType value)
is_same_decayed_v<decltype(option),
GncOptionRangeValue<double>>)
{
auto serial{option.serialize()};
if (serial.empty())
auto serial{get_scm_value(option)};
if (serial == SCM_BOOL_F)
{
return no_value;
}
else
{
auto scm_str{scm_list_1(scm_from_utf8_string(serial.c_str()))};
auto scm_str{scm_list_1(serial)};
return scm_simple_format(SCM_BOOL_F, ticked_format_str, scm_str);
}
}
@ -1368,10 +1380,11 @@ inline SCM return_scm_value(ValueType value)
if constexpr (is_same_decayed_v<decltype(option),
GncOptionRangeValue<int>>)
{
if (scm_is_pair(new_value))
option.set_value(scm_to_int(scm_cdr(new_value)));
else
option.set_value(scm_to_int(new_value));
auto value_num{scm_is_pair(new_value) ? scm_cdr(new_value) : new_value};
int value_int = scm_is_exact_integer(value_num) ?
scm_to_int(value_num) :
static_cast<int>(scm_to_double(value_num));
option.set_value(value_int);
return;
}
if constexpr (is_same_decayed_v<decltype(option),

View File

@ -127,6 +127,21 @@
"
(gncBudgetGetGUID value)))
(define (test-number-range-output-template value)
(format #f "
; Section: foo
(let ((option (gnc:lookup-option options
\"foo\"
\"bar\")))
((lambda (o) (if o (gnc:option-set-value o ~a))) option))
" (if (exact-integer? value)
(if (< value 100)
(format #f "'(percent . ~d)" value)
(format #f "'(pixels . ~f)" value))
(format #f "'~f" value)
)))
(define (test-option-scheme-output name make-option-func get-value-func test-template default value)
(let ((odb (gnc:new-options))
@ -438,10 +453,10 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(test-equal "number-range unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template))
(test-template test-number-range-output-template))
(gnc:option-set-value option 42.0)
(test-equal "number-range form"
(test-template (GncOption-serialize option))
(test-template (string->number (GncOption-serialize option)))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-number-range-option-to-scheme"))
@ -460,10 +475,10 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
(test-equal "number-plot unchanged" test-unchanged-section-output-template
(gnc:generate-restore-forms odb "options"))
(let ((option (gnc:lookup-option odb "foo" "bar"))
(test-template test-literal-output-template))
(gnc:option-set-value option 42)
(test-template test-number-range-output-template))
(gnc:option-set-value option 48)
(test-equal "number-plot form"
(test-template (GncOption-serialize option))
(test-template (string->number (GncOption-serialize option)))
(gnc:generate-restore-forms odb "options"))
))
(test-end "test-gnc-number-plot-size-option-to-scheme"))