chk/0000755000176200001440000000000014745002005011014 5ustar liggesuserschk/tests/0000755000176200001440000000000014654734236012177 5ustar liggesuserschk/tests/testthat/0000755000176200001440000000000014745002005014016 5ustar liggesuserschk/tests/testthat/test-chk-character.R0000644000176200001440000000077714436206156017642 0ustar liggesuserstest_that("vld_character", { expect_true(vld_character("1")) expect_true(vld_character(matrix("a"))) expect_true(vld_character(character(0))) expect_true(vld_character(NA_character_)) expect_false(vld_character(1)) expect_false(vld_character(TRUE)) expect_false(vld_character(factor("text"))) }) test_that("chk_character", { expect_identical(chk_character("1"), "1") expect_invisible(chk_character("1")) expect_chk_error( chk_character(TRUE), "^`TRUE` must be character[.]$" ) }) chk/tests/testthat/test-check-names.R0000644000176200001440000000266114436206156017313 0ustar liggesuserstest_that("check_names", { expect_identical(check_names(c(x = 1)), c(x = 1)) expect_invisible(check_names(c(x = 1))) expect_identical(check_names(c(x = 1), "x"), check_names(c(x = 1), "x")) expect_identical( check_names(c(x = 1, y = 2), "x"), check_names(c(x = 1, y = 2), "x") ) expect_identical( check_names(c(x = 1, y = 2), c("y", "x")), check_names(c(x = 1, y = 2), c("y", "x")) ) }) test_that("check_names fails", { expect_chk_error( check_names(character(0)), "^`character[(]0[)]` must be named[.]$" ) x <- structure(list(), .Names = character(0)) x <- structure(list(), .Names = character(0)) expect_chk_error( check_names(c(x = 1), exclusive = TRUE), "^`c[(]x = 1[)]` must not have any elements[.]$" ) expect_chk_error( check_names(x, "x"), "^`names[(]x[)]` must include 'x'[.]$" ) expect_chk_error( check_names(c(x = 1), c("x", "y")), "`names[(]c[(]x = 1[)][)]` must include 'y'[.]$" ) expect_chk_error( check_names(c(x = 1, z = 2), "x", exclusive = TRUE), "^`names[(]c[(]x = 1, z = 2[)][)]` must not include 'z'[.]$" ) expect_chk_error( check_names(c(x = 1, y = 2), c("y", "x"), order = TRUE), "`names[(]c[(]x = 1, y = 2[)][)]` must include 'y' and 'x' in that order[.]$" ) expect_chk_error( check_names(c(x = 1, y = 2), c("y", "x"), order = TRUE, x_name = "b"), "`names[(]b[)]` must include 'y' and 'x' in that order[.]$" ) }) chk/tests/testthat/test-chkor-vld.R0000644000176200001440000000160714436206156017025 0ustar liggesuserstest_that("chkor_vld", { expect_null(chkor_vld()) expect_invisible(chkor_vld()) expect_null(chkor_vld(vld_flag(TRUE))) expect_null(chkor_vld(vld_flag(TRUE), vld_number(1))) expect_null(chkor_vld(vld_flag(1), vld_flag(TRUE))) expect_chk_error(chkor_vld(vld_flag(1)), "^`1` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor_vld(vld_flag(1), vld_flag(1)), "^`1` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor_vld(vld_flag(1), vld_flag(2)), "^At least one of the following conditions must be met:\n[*] `1` must be a flag [(]TRUE or FALSE[)][.]\n[*] `2` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor_vld(vld_flag(1), vld_flag(2), vld_flag(0)), "^At least one of the following conditions must be met:\n[*] `1` must be a flag [(]TRUE or FALSE[)].\n[*] `2` must be a flag [(]TRUE or FALSE[)].\n[*] `0` must be a flag [(]TRUE or FALSE[)].$") }) chk/tests/testthat/test-chk-superset.R0000644000176200001440000000120614436206156017544 0ustar liggesuserstest_that("vld_superset", { expect_true(vld_superset(1, 1)) expect_true(vld_superset(1:2, 1)) expect_true(vld_superset(1:3, 1:2)) expect_true(vld_superset(c(1:3, NA), 1:2)) expect_false(vld_superset(c(1:3), c(1:2, NA))) expect_true(vld_superset(c(1:3, NA), c(1:2, NA))) expect_false(vld_superset(1, 1:2)) }) test_that("chk_superset", { expect_identical(chk_superset(1, 1), 1, 1) expect_invisible(chk_superset(1, 1)) expect_chk_error(chk_superset(1, 1:2), "^`1` must include 2[.]$") expect_chk_error(chk_superset(1, 1:3), "^`1` must include 2 and 3[.]$") expect_chk_error(chk_superset(2, 1), "^`2` must include 1[.]$") }) chk/tests/testthat/test-utils.R0000644000176200001440000000126414743771477016311 0ustar liggesuserstest_that("deparse_backtick_chk", { expect_identical(deparse_backtick_chk(1), "`1`") expect_identical(deparse_backtick_chk(NA), "`NA`") expect_identical(deparse_backtick_chk("1"), "`\"1\"`") expect_identical(deparse_backtick_chk(substitute(1)), "`1`") expect_identical(deparse_backtick_chk(substitute(NA)), "`NA`") expect_identical(deparse_backtick_chk(substitute("1")), "`\"1\"`") }) test_that("backtick_chk", { expect_identical(backtick_chk(1), "`1`") expect_identical(backtick_chk("`1`"), "`1`") }) test_that("unbacktick_chk", { expect_identical(unbacktick_chk(1), "1") expect_identical(unbacktick_chk("`1`"), "1") expect_identical(unbacktick_chk("``1``"), "1") }) chk/tests/testthat/test-chk-date.R0000644000176200001440000000110214436206156016602 0ustar liggesuserstest_that("vld_date", { expect_false(vld_date(NULL)) expect_false(vld_date(as.Date("2000-01-01")[-1])) expect_false(vld_date(as.Date("2000-01-01")[c(1, 1)])) expect_true(vld_date(as.Date("2000-01-01"))) }) test_that("chk_date", { expect_identical(chk_date(as.Date("2000-01-01")), as.Date("2000-01-01")) expect_invisible(chk_date(as.Date("2000-01-01"))) expect_chk_error(chk_date(1), "^`1` must be a date [(]non-missing Date scalar[)][.]$") expect_chk_error(chk_date(1, x_name = "2001-02-04"), "^2001-02-04 must be a date [(]non-missing Date scalar[)][.]$") }) chk/tests/testthat/test-chk-complex.R0000644000176200001440000000074114743771477017362 0ustar liggesuserstest_that("vld_complex", { expect_true(vld_complex(as.complex(1))) expect_true(vld_complex(as.complex(1:2))) expect_true(vld_complex(complex(0))) expect_true(vld_complex(NA_complex_)) expect_false(vld_complex(1)) expect_false(vld_complex(TRUE)) }) test_that("chk_complex", { expect_identical(chk_complex(as.complex(1)), as.complex(1)) expect_invisible(chk_complex(as.complex(1))) expect_chk_error( chk_complex(TRUE), "^`TRUE` must be complex[.]$" ) }) chk/tests/testthat/test-chk-not-missing.R0000644000176200001440000000207414436206156020145 0ustar liggesuserstest_that("vld_not_missing", { expect_false(vld_not_missing()) expect_true(vld_not_missing(1)) }) test_that("vld_not_missing in function", { fun <- function(x) vld_not_missing(x) expect_false(fun()) expect_true(fun(1)) }) test_that("vld_not_missing in function default", { fun <- function(x = 1) vld_not_missing(x) # this might be expected to be false if testing whether specified expect_true(fun()) expect_true(fun(1)) }) test_that("chk_not_missing", { expect_identical(chk_not_missing(1), 1) expect_invisible(chk_not_missing(1)) expect_chk_error(chk_not_missing(), "^`x` must not be missing\\.$") expect_chk_error(chk_not_missing(x_name = "`y`"), "^`y` must not be missing\\.$") }) test_that("chk_not_missing in function", { fun <- function(x) chk_not_missing(x) expect_chk_error(fun(), "^`x` must not be missing\\.$") expect_identical(fun(1), 1) }) test_that("chk_not_missing in function default", { fun <- function(x = 1) chk_not_missing(x) expect_identical(fun(NULL), NULL) expect_identical(fun(), 1) expect_identical(fun(2), 2) }) chk/tests/testthat/test-chk-length.R0000644000176200001440000000127214436206156017156 0ustar liggesuserstest_that("vld_length", { expect_true(vld_length(1)) expect_true(vld_length(1:2, 2)) expect_true(vld_length(NA)) expect_true(vld_length(character(0), 0)) expect_true(vld_length(data.frame(x = 1:2))) expect_false(vld_length(1:2)) expect_true(vld_length(1:2, upper = 2)) expect_true(vld_length(1:2, upper = 3)) }) test_that("chk_length", { expect_identical(chk_length(1), 1) expect_invisible(chk_length(1)) expect_chk_error(chk_length(1:2), "^`1:2` must be length 1 not 2[.]$") expect_chk_error(chk_length(1:2, length = 3, upper = 4), "^`1:2` must have a length between 3 and 4 not 2[.]$") expect_chk_error(chk_length(1:2, x_name = 1L), "^1 must be length 1 not 2[.]$") }) chk/tests/testthat/test-chk-true.R0000644000176200001440000000321114743771477016665 0ustar liggesuserstest_that("vld_true", { expect_true(vld_true(TRUE)) expect_true(vld_true(c(x = TRUE))) expect_true(vld_true(structure(TRUE, x = "y"))) expect_false(vld_true(FALSE)) expect_false(vld_true(NA)) expect_false(vld_true(c(TRUE, TRUE))) expect_false(vld_true(1)) }) test_that("chk_true", { expect_identical(chk_true(TRUE), TRUE) expect_invisible(chk_true(TRUE)) expect_identical(chk_true(c(x = TRUE)), c(x = TRUE)) expect_chk_error(chk_true(FALSE), "^`FALSE` must be TRUE[.]$") expect_chk_error(chk_true(FALSE, x_name = TRUE), "^TRUE must be TRUE[.]$") }) test_that("vld_false", { expect_true(vld_false(FALSE)) expect_false(vld_false(TRUE)) expect_true(vld_false(c(x = FALSE))) expect_true(vld_false(structure(FALSE, x = "y"))) expect_false(vld_false(NA)) expect_false(vld_false(c(FALSE, FALSE))) expect_false(vld_false(0)) }) test_that("chk_false", { expect_identical(chk_false(FALSE), FALSE) expect_invisible(chk_false(FALSE)) expect_identical(chk_false(c(x = FALSE)), c(x = FALSE)) expect_chk_error(chk_false(TRUE), "^`TRUE` must be FALSE[.]$") expect_chk_error(chk_false(TRUE, x_name = FALSE), "^FALSE must be FALSE[.]$") }) test_that("vld_flag", { expect_true(vld_flag(FALSE)) expect_true(vld_flag(TRUE)) expect_false(vld_flag(logical(0))) expect_false(vld_flag(NA)) expect_false(vld_flag(c(FALSE, TRUE))) expect_false(vld_flag(1)) }) test_that("chk_flag", { expect_identical(chk_flag(TRUE), TRUE) expect_invisible(chk_flag(TRUE)) expect_chk_error(chk_flag(1), "^`1` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chk_flag(1, x_name = "2"), "^2 must be a flag [(]TRUE or FALSE[)][.]$") }) chk/tests/testthat/test-aaa-deprecated.R0000644000176200001440000000205114436206156017746 0ustar liggesuserstest_that("vld_no_missing", { rlang::local_options(lifecycle_verbosity = "quiet") expect_true(vld_no_missing(1)) expect_true(vld_no_missing(integer(0))) expect_false(vld_no_missing(NA)) expect_false(vld_no_missing(c(NA, 1))) }) test_that("chk_no_missing", { rlang::local_options(lifecycle_verbosity = "quiet") expect_null(chk_no_missing(1)) expect_invisible(chk_no_missing(1)) expect_chk_error(chk_no_missing(NA), "^`NA` must not have missing values[.]$") expect_chk_error(chk_no_missing(NA, x_name = "1"), "^1 must not have missing values[.]$") }) test_that("warning messages are generated for dep functions", { rlang::local_options(lifecycle_verbosity = "warning") expect_warning(chk_dirs(tempdir())) expect_warning(chk_has(1:3, 1)) expect_warning(chk_in(1, 1:3)) expect_warning(expect_warning(chk_no_missing(1))) expect_warning(vld_no_missing(1)) expect_warning(chk_proportion(1)) expect_warning(deparse_backtick(2)) file <- tempfile() writeLines(file, text = "some test data") expect_warning(chk_files(file)) }) chk/tests/testthat/test-check-key.R0000644000176200001440000000155614436206156017002 0ustar liggesuserstest_that("check_key works", { expect_identical(check_key(data.frame()), data.frame()) expect_invisible(check_key(data.frame())) expect_invisible(check_key(data.frame(x = 1))) expect_invisible(check_key(data.frame(x = 1), "x")) expect_invisible(check_key(data.frame(x = c(1, 1), y = 1:2), c("y", "x"))) expect_invisible(check_key(data.frame(x = c(1, 1), y = c(NA, 1)), c("y", "x"))) expect_invisible(check_key(data.frame(x = c(1, 1), y = NA), c("y", "x"), na_distinct = TRUE)) }) test_that("check_key fails", { x <- data.frame(x = c(1, 2), y = c(1, 1), z = NA) expect_chk_error( check_key(x, c("y", "y")), "`key` must be unique[.]$" ) expect_chk_error( check_key(x, "y"), "^Column 'y' in `x` must be a unique key[.]$" ) expect_chk_error( check_key(x, c("y", "z")), "^Columns 'y' and 'z' in `x` must be a unique key[.]$" ) }) chk/tests/testthat/test-chkor.R0000644000176200001440000000154214436206156016240 0ustar liggesuserstest_that("chkor", { rlang::local_options(lifecycle_verbosity = "quiet") expect_null(chkor()) expect_invisible(chkor()) expect_null(chkor(chk_flag(TRUE))) expect_null(chkor(chk_flag(1), chk_flag(TRUE))) expect_chk_error(chkor(chk_flag(1)), "^`1` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor(chk_flag(1), chk_flag(1)), "^`1` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor(chk_flag(1), chk_flag(2)), "^At least one of the following conditions must be met:\n[*] `1` must be a flag [(]TRUE or FALSE[)][.]\n[*] `2` must be a flag [(]TRUE or FALSE[)][.]$") expect_chk_error(chkor(chk_flag(1), chk_flag(2), chk_flag(0)), "^At least one of the following conditions must be met:\n[*] `1` must be a flag [(]TRUE or FALSE[)].\n[*] `2` must be a flag [(]TRUE or FALSE[)].\n[*] `0` must be a flag [(]TRUE or FALSE[)].$") }) chk/tests/testthat/test-chk-missing.R0000644000176200001440000000232314436206156017344 0ustar liggesuserstest_that("vld_missing", { expect_true(vld_missing()) expect_false(vld_missing(1)) }) test_that("vld_missing in function", { fun <- function(x) vld_missing(x) expect_true(fun()) expect_false(fun(1)) }) test_that("vld_missing in function default", { fun <- function(x = 1) vld_missing(x) # this might be expected to be true if testing whether specified expect_false(fun()) expect_false(fun(1)) }) test_that("chk_missing", { expect_null(chk_missing()) expect_invisible(chk_missing()) expect_chk_error(chk_missing(1), "^`1` must be missing\\.$") expect_chk_error(chk_missing(1, x_name = "`y`"), "^`y` must be missing\\.$") }) test_that("chk_missing in function", { fun <- function(x) chk_missing(x) expect_null(fun()) expect_invisible(fun()) expect_chk_error(fun(1), "^`x` must be missing\\.$") }) test_that("chk_missing in function default", { fun <- function(x = 1) chk_missing(x) # this might be expected to be an error if testing whether specified expect_chk_error(fun(), "^`x` must be missing\\.$") # this might be expected to be an error if testing whether specified expect_chk_error(fun(NULL), "^`x` must be missing\\.$") expect_chk_error(fun(1), "^`x` must be missing\\.$") }) chk/tests/testthat/test-chk-date-time.R0000644000176200001440000000226714436206156017553 0ustar liggesuserstest_that("vld_date_time", { expect_false(vld_date_time(NULL)) expect_false(vld_date_time(Sys.time()[-1])) expect_false(vld_date_time(Sys.time()[c(1, 1)])) expect_true(vld_date_time(Sys.time())) }) test_that("chk_date_time", { time <- Sys.time() expect_identical(chk_date_time(time), time) expect_invisible(chk_date_time(Sys.time())) expect_chk_error(chk_date_time(1), "^`1` must be a date time [(]non-missing POSIXct scalar[)][.]$") expect_chk_error(chk_date(1, x_name = 1), "^1 must be a date [(]non-missing Date scalar[)][.]$") }) test_that("vld_datetime", { rlang::local_options(lifecycle_verbosity = "quiet") expect_false(vld_datetime(NULL)) expect_false(vld_datetime(Sys.time()[-1])) expect_false(vld_datetime(Sys.time()[c(1, 1)])) expect_true(vld_datetime(Sys.time())) }) test_that("chk_datetime", { rlang::local_options(lifecycle_verbosity = "quiet") time <- Sys.time() expect_identical(chk_date_time(time), time) expect_invisible(chk_datetime(Sys.time())) expect_chk_error(chk_datetime(1), "^`1` must be a date time [(]non-missing POSIXct scalar[)][.]$") expect_chk_error(chk_date(1, x_name = 1), "^1 must be a date [(]non-missing Date scalar[)][.]$") }) chk/tests/testthat/test-chk-atomic.R0000644000176200001440000000116314507601123017140 0ustar liggesuserstest_that("vld_atomic", { expect_true(vld_atomic(1)) expect_true(vld_atomic(matrix(1:3))) expect_true(vld_atomic(character(0))) expect_false(vld_atomic(list(1))) skip_on_cran() if (sub("(R version )((\\d+\\.){2,2}\\d+)(.*)", "\\2", R.version$version.string) <= "4.4.0") { expect_true(vld_atomic(NULL)) } else { expect_false(vld_atomic(NULL)) } }) test_that("chk_atomic", { expect_identical(chk_atomic(1), 1) expect_invisible(chk_atomic(1)) expect_chk_error(chk_atomic(list(1)), "^`list[(]1[)]` must be atomic[.]$") expect_chk_error(chk_atomic(list(1), x_name = 1), "^1 must be atomic[.]$") }) chk/tests/testthat/test-chk-wnum.R0000644000176200001440000000140514436206156016661 0ustar liggesuserstest_that("vld_wnum", { rlang::local_options(lifecycle_verbosity = "quiet") lifecycle::expect_deprecated(vld_wnum(1)) expect_false(vld_wnum(numeric(0))) expect_true(vld_wnum(NA_integer_)) expect_true(vld_wnum(1)) expect_true(vld_wnum(1L)) expect_false(vld_wnum(1.1)) expect_true(vld_wnum(-1)) expect_true(vld_wnum(Inf)) expect_false(vld_wnum(c(1, 2))) expect_false(vld_wnum(TRUE)) }) test_that("chk_wnum", { rlang::local_options(lifecycle_verbosity = "quiet") lifecycle::expect_deprecated(chk_wnum(1)) expect_identical(chk_wnum(1), 1) expect_invisible(chk_wnum(1)) expect_chk_error(chk_wnum(TRUE), "^`TRUE` must be a whole numeric scalar[.]$") expect_chk_error(chk_wnum(TRUE, x_name = 1L), "^1 must be a whole numeric scalar[.]$") }) chk/tests/testthat/test-chk-all.R0000644000176200001440000000650214436206156016446 0ustar liggesuserstest_that("vld_all", { expect_true(vld_all(character(0), vld_true)) expect_true(vld_all(NULL, vld_null)) expect_false(vld_all(NULL, vld_not_null)) expect_false(vld_all(FALSE, vld_true)) expect_true(vld_all(FALSE, vld_false)) }) test_that("chk_all", { expect_identical(chk_all(character(0), chk_true), character(0), chk_true) expect_invisible(chk_all(character(0), chk_true)) expect_identical(chk_all(NULL, chk_null), NULL, chk_null) expect_invisible(chk_all(NULL, chk_null)) expect_identical(chk_all(TRUE, chk_true), TRUE, chk_true) expect_identical(chk_all(FALSE, chk_false), FALSE, chk_false) expect_identical(chk_all(c(TRUE, TRUE), chk_true), c(TRUE, TRUE), chk_true) expect_identical(chk_all(1.1, chk_gt, 1), 1.1, chk_gt, 1) expect_chk_error( chk_all(NULL, chk_flag), "^`NULL` must be a flag [(]TRUE or FALSE[)][.]$" ) expect_chk_error( chk_all(NULL, chk_flag, x_name = "NULL"), "^NULL must be a flag [(]TRUE or FALSE[)][.]$" ) expect_chk_error( chk_all(FALSE, chk_true), "^All elements of `FALSE` must be TRUE[.]$" ) expect_chk_error( chk_all(FALSE, chk_true, x_name = TRUE), "^All elements of TRUE must be TRUE[.]$" ) expect_chk_error( chk_all(1.1, chk_gt, 2), "^All elements of `1.1` must be greater than 2, not 1.1[.]$" ) }) test_that("vld_all_identical", { expect_true(vld_all_identical(NULL)) expect_true(vld_all_identical(character(0))) expect_true(vld_all_identical(1)) expect_true(vld_all_identical(c(TRUE, TRUE))) expect_true(vld_all_identical(c(NA, NA))) expect_false(vld_all_identical(c(1, 2))) }) test_that("chk_all_identical", { expect_identical(chk_all_identical(NULL), NULL) expect_invisible(chk_all_identical(NULL)) expect_chk_error(chk_all_identical(c(1, 2)), "^`c[(]1, 2[)]` must have identical elements[.]$") }) test_that("vld_all_equal", { expect_true(vld_all_equal(NULL)) expect_true(vld_all_equal(character(0))) expect_true(vld_all_equal(1)) expect_true(vld_all_equal(c(TRUE, TRUE))) expect_true(vld_all_equal(c(NA, NA))) expect_false(vld_all_equal(c(1, 2))) expect_false(vld_all_equal(c(1, 1.0000001), tolerance = 1.490116e-08)) expect_true(vld_all_equal(c(1, 1.00000001), tolerance = 1.490116e-08)) expect_true(vld_all_equal(list(c(x = 1), c(x = 1)))) expect_false(vld_all_equal(list(c(x = 1), c(y = 1)))) }) test_that("chk_all_equal", { expect_identical(chk_all_equal(NULL), NULL) expect_invisible(chk_all_equal(NULL), NULL) expect_chk_error(chk_all_equal(c(1, 2)), "^`c[(]1, 2[)]` must have equal elements[.]$") }) test_that("vld_all_equivalent", { expect_true(vld_all_equivalent(NULL)) expect_true(vld_all_equivalent(character(0))) expect_true(vld_all_equivalent(1)) expect_true(vld_all_equivalent(c(TRUE, TRUE))) expect_true(vld_all_equivalent(c(NA, NA))) expect_false(vld_all_equivalent(c(1, 2))) expect_false(vld_all_equivalent(c(1, 1.0000001), tolerance = 1.490116e-08)) expect_true(vld_all_equivalent(c(1, 1.00000001), tolerance = 1.490116e-08)) expect_true(vld_all_equivalent(list(c(x = 1), c(x = 1)))) expect_true(vld_all_equivalent(list(c(x = 1), c(y = 1)))) }) test_that("chk_all_equivalent", { expect_identical(chk_all_equivalent(NULL), NULL) expect_invisible(chk_all_equivalent(NULL)) expect_chk_error(chk_all_equivalent(c(1, 2)), "^`c[(]1, 2[)]` must have equivalent elements[.]$") }) chk/tests/testthat/test-chk-number.R0000644000176200001440000000120314436206156017157 0ustar liggesuserstest_that("vld_number", { expect_false(vld_number(numeric(0))) expect_false(vld_number(NA_integer_)) expect_true(vld_number(1)) expect_true(vld_number(1L)) expect_true(vld_number(1.1)) expect_true(vld_number(-1.1)) expect_true(vld_number(Inf)) expect_false(vld_number(c(1, 2))) expect_false(vld_number(TRUE)) }) test_that("chk_number", { expect_identical(chk_number(1), 1) expect_invisible(chk_number(1)) expect_chk_error(chk_number(TRUE), "^`TRUE` must be a number [(]non-missing numeric scalar[)][.]$") expect_chk_error(chk_number(TRUE, x_name = 1L), "^1 must be a number [(]non-missing numeric scalar[)][.]$") }) chk/tests/testthat/test-chk-compatible-lengths.R0000644000176200001440000000741514436206156021463 0ustar liggesusers# vld ----- test_that("validate true single vector passed", { x <- c(1, 3, 5) expect_true(vld_compatible_lengths(x)) }) test_that("validate true when vectors are all the same length", { x <- c(1, 3, 5) y <- c(2, 4, 6) expect_true(vld_compatible_lengths(x, y)) }) test_that("validate true when one vectors is length 1 and other vectors are the same length", { x <- c(1, 3, 5) y <- c(2, 4, 6) z <- c(1) expect_true(vld_compatible_lengths(x, y, z)) }) test_that("validate true when vector is length 0", { x <- NULL expect_true(vld_compatible_lengths(x)) }) test_that("validate true when nothing", { expect_true(vld_compatible_lengths()) }) test_that("validate false if one vectors is length 0", { x <- c(1, 3, 5) y <- c(2, 4, 6) z <- NULL expect_false(vld_compatible_lengths(x, y, z)) }) test_that("validate false when two vectors have multiple lengths", { x <- c(1, 3, 5) y <- c(2, 4) expect_false(vld_compatible_lengths(x, y)) }) test_that("validate false when vectors are multiple lengths", { v <- c(1, 3, 5) x <- c(2, 4) y <- c(1, 2, 3, 4) z <- c(8) expect_false(vld_compatible_lengths(v, x, y, z)) }) test_that("validate false if data frame of two lengths passed", { x <- data.frame(a = c(1, 2, 3), b = c(4, 5, 6)) y <- data.frame(a = c(1, 2), b = c(6, 7), c = c(8, 9)) expect_false(vld_compatible_lengths(x, y)) }) test_that("validate true when data frames passed", { x <- data.frame(a = c(1, 2, 3), b = c(4, 5, 6)) y <- data.frame(a = c(1, 2, 3)) expect_true(vld_compatible_lengths(x, y)) }) test_that("validate true if list passed", { x <- list(a = c(1, 2, 3), b = c(4, 5, 6)) expect_true(vld_compatible_lengths(x)) }) test_that("validate true if lists passed", { x <- list(a = c(1, 2, 3), b = c(4, 5, 6)) y <- list(e = c(1, 2, 3), f = c(4, 5, 6)) expect_true(vld_compatible_lengths(x, y)) }) # chk ----- test_that("passes when single value passed", { x <- 1 expect_null(chk_compatible_lengths(x)) expect_invisible(chk_compatible_lengths(x)) }) test_that("passes when single vector passed", { x <- c(1, 3, 5) expect_null(chk_compatible_lengths(x)) expect_invisible(chk_compatible_lengths(x)) }) test_that("passes when multiple vectors of same length passed", { x <- c(1, 3, 5) y <- c(2, 4, 6) z <- c(7, 8, 0) expect_null(chk_compatible_lengths(x, y, z)) expect_invisible(chk_compatible_lengths(x, y, z)) }) test_that("passes when multiple vectors of same length passed and vectors of length one passed", { x <- c(1, 3, 5) y <- c(2, 4, 6) z <- 7 expect_null(chk_compatible_lengths(x, y, z)) expect_invisible(chk_compatible_lengths(x, y, z)) }) test_that("passes when only vector of length zero passed", { x <- NULL expect_null(chk_compatible_lengths(x)) expect_invisible(chk_compatible_lengths(x)) }) test_that("throws error when vector of length zero and other length passed", { x <- NULL y <- c(1, 2, 3) expect_error( chk_compatible_lengths(x, y), regexp = paste0( "^... objects must be all zero length or the same length ", "with some of length of 1 but not lengths 0 and 3\\.$" ) ) }) test_that("throws error when vector have two different lengths", { x <- c(4, 5) y <- c(1, 2, 3) expect_error( chk_compatible_lengths(x, y), regexp = paste0( "^... objects must be all zero length or the same length ", "with some of length of 1 but not lengths 2 and 3\\.$" ) ) }) test_that("throws error when vector have three different lengths", { x <- c(4, 5) z <- c(6, 7, 8, 9) y <- c(1, 2, 3) expect_error( chk_compatible_lengths(x, z, y, x_name = "`test vectors`"), regexp = paste0( "^`test vectors` must be all zero length or the same length ", "with some of length of 1 but not lengths 2, 3 and 4\\.$" ) ) }) chk/tests/testthat/test-chk-whole-number.R0000644000176200001440000000130014436206156020271 0ustar liggesuserstest_that("vld_whole_number", { expect_chk_error(chk_whole_number(1.1), "^`1.1` must be a whole number [(]non-missing integer scalar or double equivalent[)][.]$") expect_chk_error(chk_whole_number(1.1, x_name = 1L), "^1 must be a whole number [(]non-missing integer scalar or double equivalent[)][.]$") }) test_that("chk_whole_number", { expect_identical(chk_whole_number(1), 1) expect_invisible(chk_whole_number(1)) expect_chk_error(chk_whole_number(1.1), "^`1.1` must be a whole number [(]non-missing integer scalar or double equivalent[)][.]$") expect_chk_error(chk_whole_number(1.1, x_name = 1L), "^1 must be a whole number [(]non-missing integer scalar or double equivalent[)][.]$") }) chk/tests/testthat/test-chk-null.R0000644000176200001440000000126514436206156016651 0ustar liggesuserstest_that("vld_null", { expect_true(vld_null(NULL)) expect_false(vld_null(1)) }) test_that("chk_null", { expect_identical(chk_null(NULL), NULL) expect_invisible(chk_null(NULL)) expect_chk_error(chk_null(1), "^`1` must be NULL[.]$") expect_chk_error(chk_null(1, x_name = "NULL"), "^NULL must be NULL[.]$") }) test_that("vld_not_null", { expect_true(vld_not_null(1)) expect_false(vld_not_null(NULL)) }) test_that("chk_not_null", { expect_identical(chk_not_null(1), 1) expect_invisible(chk_not_null(1)) expect_chk_error(chk_not_null(NULL), "^`NULL` must not be NULL[.]$") expect_chk_error(chk_not_null(NULL, x_name = "not NULL"), "^Not NULL must not be NULL[.]$") }) chk/tests/testthat/test-chk-environment.R0000644000176200001440000000077214436206156020245 0ustar liggesuserstest_that("vld_environment", { expect_false(vld_environment(1)) expect_false(vld_environment(list(1))) expect_true(vld_environment(.GlobalEnv)) expect_true(vld_environment(environment())) }) test_that("chk_environment", { expect_identical(chk_environment(.GlobalEnv), .GlobalEnv) expect_invisible(chk_environment(.GlobalEnv)) expect_chk_error(chk_environment(1), "^`1` must be an environment[.]$") expect_chk_error(chk_environment(list(1), x_name = 1), "^1 must be an environment[.]$") }) chk/tests/testthat/test-chk-is.R0000644000176200001440000000136714436206156016315 0ustar liggesuserstest_that("vld_is", { expect_true(vld_is(1, "numeric")) expect_false(vld_is(1L, "numeric")) expect_true(vld_is(1L, "integer")) x <- list() class(x) <- c("a", "b") expect_true(vld_is(x, "a")) expect_true(vld_is(x, "b")) }) test_that("chk_is", { expect_identical(chk_is(1L, "integer"), 1L, "integer") expect_invisible(chk_is(1L, "integer")) expect_chk_error(chk_is(1, "integer"), "^`1` must inherit from class 'integer'[.]$") expect_chk_error( chk_is(matrix(1), "numeric"), "`matrix[(]1[)]` must inherit from class 'numeric'[.]$" ) x <- list() class(x) <- c("a", "b") expect_chk_error(chk_is(x, "c"), "`x` must inherit from class 'c'") expect_chk_error(chk_is(x, "c", x_name = "c"), "C must inherit from class 'c'") }) chk/tests/testthat/test-internal.R0000644000176200001440000000033114436206156016741 0ustar liggesuserstest_that("test if incomparables implemented in anyDuplicated.data.frame", { expect_error( anyDuplicated(data.frame(), incomparables = NA), "^argument 'incomparables != FALSE' is not used [(]yet[)]$" ) }) chk/tests/testthat/test-p.R0000644000176200001440000000015614436206156015371 0ustar liggesuserstest_that("p", { expect_identical(p(), paste()) }) test_that("p0", { expect_identical(p0(), paste0()) }) chk/tests/testthat/test-check-length.R0000644000176200001440000000274114744734003017467 0ustar liggesuserstest_that("check_length length", { expect_identical(check_length(1), 1) expect_invisible(check_length(1)) expect_identical(check_length(integer(0)), integer(0)) expect_chk_error( check_length(integer(0), values = TRUE), "^`length[(]integer[(]0[)][)]` must be greater than 0, not 0[.]$" ) expect_chk_error( check_length(1, values = FALSE), "^`length[(]1[)]` must be equal to 0L[.]" ) expect_identical(check_length(2, values = 1), check_length(2, values = 1)) expect_chk_error( check_length(1, values = 2), "^`length[(]1[)]` must be equal to 2[.]" ) expect_chk_error( check_length(1, values = 2:3), "^`length[(]1[)]` must be between 2 and 3, not 1[.]" ) expect_chk_error( check_length(1, values = 3:2), "^`length[(]1[)]` must be between 2 and 3, not 1[.]" ) expect_identical(check_length(1:2, values = 2:3), check_length(1:2, values = 2:3)) expect_chk_error( check_length(2, values = c(2, 2)), "`length[(]2[)]` must be equal to 2[.]" ) expect_chk_error( check_length(2, values = c(2, 2, 2)), "`length[(]2[)]` must match 2, not 1[.]" ) expect_chk_error( check_length(2, values = c(3, 2, 2)), "`length[(]2[)]` must match 2 or 3, not 1[.]" ) expect_chk_error( check_length(1, values = 1.1), "^At least one of the following conditions must be met:\n[*] `values` must be a flag [(]TRUE or FALSE[)].\n[*] `values` must be a whole numeric vector \\(integer vector or double equivalent\\)\\.$" ) }) chk/tests/testthat/test-check-dirs.R0000644000176200001440000000252514436206156017150 0ustar liggesuserstest_that("check_dirs works", { expect_identical(check_dirs(character(0)), character(0)) expect_invisible(check_dirs(character(0))) expect_identical( check_dirs(character(0), exists = TRUE), check_dirs(character(0), exists = TRUE) ) expect_invisible(check_dirs(character(0), exists = TRUE)) tmp <- withr::local_tempfile() expect_identical(check_dirs(tmp, exists = FALSE), check_dirs(tmp, exists = FALSE)) expect_invisible(check_dirs(tmp, exists = FALSE)) tmp <- withr::local_tempdir() expect_identical(check_dirs(tmp, exists = TRUE), check_dirs(tmp, exists = TRUE)) expect_invisible(check_dirs(tmp, exists = TRUE)) }) test_that("check_dirs errors", { expect_chk_error(check_dirs(NA_character_)) tmp <- withr::local_tempfile() writeLines(tmp, text = "some test data") expect_chk_error( check_dirs(tmp), "^`tmp` must specify directories [(]'.*' is a file[)][.]$" ) expect_chk_error( check_dirs(tmp, exists = FALSE), "^`tmp` must specify directories [(]'.*' is a file[)][.]$" ) tmp <- withr::local_tempfile() expect_chk_error( check_dirs(tmp), "^`tmp` must specify existing directories [(]'.*' can't be found[)][.]$" ) tmp <- withr::local_tempdir() expect_chk_error( check_dirs(tmp, exists = FALSE), "^`tmp` must not specify existing directories [(]'.*' exists[)][.]$" ) }) chk/tests/testthat/test-chk-join.R0000644000176200001440000000416314643073326016637 0ustar liggesuserstest_that("vld_join", { expect_true(vld_join(data.frame(z = 1), data.frame(z = 1:2), by = "z")) expect_false(vld_join(data.frame(z = 1), data.frame(z = 2), by = "z")) expect_true(vld_join(data.frame(z = 1:2), data.frame(z = 1:2), by = "z")) }) test_that("vld_join with by = NULL", { expect_false(vld_join(data.frame(z = 1), data.frame(z = 1:2), by = NULL)) }) test_that("vld_join with names", { expect_true(vld_join(data.frame(z = 1), data.frame(a = 1:2), by = c(z = "a"))) expect_false(vld_join(data.frame(z = 1), data.frame(a = 2), by = c(z = "a"))) expect_error( vld_join(data.frame(z = 1), data.frame(a = 2), by = c(a = "z")), "undefined columns selected" ) expect_true(vld_join(data.frame(z = 1, z2 = 2), data.frame(z = 1:2, z2 = 2:1), by = "z")) expect_true(vld_join(data.frame(z = 1, z2 = 2), data.frame(z = 1:2, z2 = 2:1), by = c("z", "z2"))) expect_true(vld_join(data.frame(z = 1, z2 = 2), data.frame(z = 1:2, z2 = 1:2), by = "z")) expect_false(vld_join(data.frame(z = 1, z2 = 2), data.frame(z = 1:2, z2 = 1:2), by = c("z", "z2"))) }) test_that("vld_join with zero length", { expect_true(vld_join(data.frame(z = numeric(0)), data.frame(z = 2), by = c("z"))) expect_true(vld_join(data.frame(z = numeric(0)), data.frame(z = numeric(0)), by = c("z"))) expect_false(vld_join(data.frame(z = 1), data.frame(z = numeric(0)), by = c("z"))) }) test_that("vld_join with missing values", { expect_false(vld_join(data.frame(z = NA_integer_), data.frame(z = 2), by = c("z"))) expect_false(vld_join(data.frame(z = 2), data.frame(z = NA_integer_), by = c("z"))) expect_true(vld_join(data.frame(z = NA_integer_), data.frame(z = NA_integer_), by = c("z"))) }) test_that("chk_join", { expect_identical( chk_join(data.frame(z = 1), data.frame(z = 1), by = "z"), chk_join(data.frame(z = 1), data.frame(z = 1), by = "z") ) expect_invisible(chk_join(data.frame(z = 1), data.frame(z = 1), by = "z")) }) test_that("chk_join", { expect_chk_error( chk_join(data.frame(z = 1), data.frame(z = 2), by = "z"), "^All rows in `data.frame[(]z [=] 1[)]` must match at least one in the y object of class [.]" ) expect_chk_error( check_values(ordered(c(1, 3), levels = 1:3), ordered(c(1, 2), levels = 1:3)), "^`ordered[(]c[(]1, 3[)], levels = 1:3[)]` must have values between '1' and '2'[.]$" ) expect_chk_error( check_values(factor(1:2), factor(1:2, levels = 2:1)), "^`levels[(]factor[(]1:2[)][)]` must have [(]the first occurence of[)] each of the following elements in the following order: '2', '1'[.]$" ) expect_chk_error( check_values(ordered(1:2), ordered(1:2, levels = 2:1)), "^`levels[(]ordered[(]1:2[)][)]` must have [(]the first occurence of[)] each of the following elements in the following order: '2', '1'[.]$" ) }) chk/tests/testthat/test-chk-factor.R0000644000176200001440000000071214436206156017151 0ustar liggesuserstest_that("vld_factor", { expect_true(vld_factor(factor("1"))) expect_true(vld_factor(factor(0))) expect_true(vld_factor(factor(NA))) expect_false(vld_factor(NA_character_)) expect_false(vld_factor(1)) expect_false(vld_factor(TRUE)) }) test_that("chk_factor", { expect_identical(chk_factor(factor("1")), factor("1")) expect_invisible(chk_factor(factor("1"))) expect_chk_error( chk_factor(TRUE), "^`TRUE` must be factor[.]$" ) }) chk/tests/testthat/test-chk-identical.R0000644000176200001440000000563514506317154017637 0ustar liggesuserstest_that("vld_identical", { expect_true(vld_identical(1, 1)) expect_true(vld_identical(1L, 1L)) expect_false(vld_identical(1, 1L)) expect_false(vld_identical(1L, 1)) expect_true(vld_identical(c(1L), 1L)) expect_false(vld_identical(c(x = 1L), 1L)) expect_false(vld_identical(1L, c(x = 1L))) }) test_that("chk_identical", { expect_identical(chk_identical(1, 1), 1, 1) expect_invisible(chk_identical(1, 1)) expect_chk_error( chk_identical(1L, 2), "^`1L` must be identical to 2[.]\n" ) expect_chk_error(chk_identical(1, 1L), "^`1` must be identical to 1L[.]\n") expect_chk_error( chk_identical(1, 1:10), "^`1` must be identical to the y object of class [<]int[>][.]\n" ) expect_chk_error( chk_identical(1, 1:100), "^`1` must be identical to the y object of class [<]int[>][.]\n" ) expect_chk_error( chk_identical(1, c(1, 5, 1, 9)), "^`1` must be identical to the y object of class [<]dbl[>][.]\n" ) expect_chk_error( chk_identical(1, 2, x_name = 2), "^2 must be identical to 2[.]\n" ) }) test_that("vld_equal", { expect_true(vld_equal(1, 1)) expect_true(vld_equal(1L, 1L)) expect_true(vld_equal(1, 1L)) expect_true(vld_equal(1L, 1)) expect_true(vld_equal(c(1L), 1L)) expect_false(vld_equal(c(x = 1L), 1L)) expect_false(vld_equal(1L, c(x = 1L))) expect_true(vld_equal(1, 1.00000001)) expect_true(vld_equal(1, 1.001, 0.01)) expect_false(vld_equal(1, 1.001, 0.0001)) }) test_that("chk_equal", { expect_identical(chk_equal(1, 1), 1, 1) expect_invisible(chk_equal(1, 1)) expect_chk_error( chk_equal(c(x = 1L), 1L), "^`c[(]x = 1L[)]` must be equal to 1L[.]\n" ) expect_chk_error( chk_equal(1L, 2), "^`1L` must be equal to 2[.]\n" ) expect_chk_error( chk_equal(1, c(1, 5, 1, 9)), "^`1` must be equal to the y object of class [<]dbl[>][.]\n" ) expect_chk_error( chk_equal(1, 2, x_name = 2), "^2 must be equal to 2[.]\n" ) }) test_that("vld_equivalent", { expect_true(vld_equivalent(1, 1)) expect_true(vld_equivalent(1L, 1L)) expect_true(vld_equivalent(1, 1L)) expect_true(vld_equivalent(1L, 1)) expect_true(vld_equivalent(c(1L), 1L)) expect_true(vld_equivalent(c(x = 1L), 1L)) expect_true(vld_equivalent(c(x = 1L), 1L)) expect_true(vld_equivalent(1L, c(x = 1L))) expect_true(vld_equivalent(1L, c(x = 1L))) expect_true(vld_equivalent(1, 1.00000001)) expect_true(vld_equivalent(1, 1.001, 0.01)) expect_false(vld_equivalent(1, 1.001, 0.0001)) }) test_that("chk_equivalent", { expect_identical(chk_equivalent(1, 1), 1, 1) expect_invisible(chk_equivalent(1, 1)) expect_chk_error(chk_equivalent(1, 1.001, 0.0001), c("^`1` must be equivalent to 1[.]001[.]\n")) expect_chk_error( chk_equivalent(1, c(1, 5, 1, 9)), "^`1` must be equivalent to the y object of class [<]dbl[>][.]\n" ) expect_chk_error( chk_equivalent(1, 2, x_name = 2), "^2 must be equivalent to 2[.]\n" ) }) chk/tests/testthat/test-chk-string.R0000644000176200001440000000235014436206156017201 0ustar liggesuserstest_that("vld_string", { expect_false(vld_string(character(0))) expect_false(vld_string(NA_character_)) expect_true(vld_string("")) expect_true(vld_string("a")) expect_false(vld_string(c("a", "b"))) }) test_that("chk_string", { expect_identical(chk_string(""), "") expect_invisible(chk_string("")) expect_chk_error(chk_string(1), "^`1` must be a string [(]non-missing character scalar[)][.]$") expect_chk_error(chk_string(1, x_name = "''"), "^'' must be a string [(]non-missing character scalar[)][.]$") }) test_that("vld_match", { expect_true(vld_match(character(0))) expect_true(vld_match(1)) expect_true(vld_match("a")) expect_true(vld_match(NA)) expect_true(vld_match(c(NA, "b"), "b")) expect_false(vld_match("")) expect_true(vld_match(c("a", "b"))) }) test_that("chk_match", { expect_identical(chk_match("1"), "1") expect_invisible(chk_match("1")) expect_chk_error(chk_match(""), "^`\"\"` must match regular expression '.+'[.]$") expect_chk_error( chk_match(c("a", "b"), "b"), "`c[(]\"a\", \"b\"[)]` must have values matching regular expression 'b'[.]$" ) expect_chk_error( chk_match(c("a", "b"), "b"), "`c[(]\"a\", \"b\"[)]` must have values matching regular expression 'b'[.]$" ) }) chk/tests/testthat/test-chk-not-subset.R0000644000176200001440000000156014436206156020000 0ustar liggesuserstest_that("vld_not_subset", { expect_true(vld_not_subset(integer(0), 1)) expect_true(vld_not_subset(1, 2)) expect_false(vld_not_subset(1:3, 1:2)) expect_true(vld_not_subset(numeric(0), 1L)) expect_true(vld_not_subset(-1, c(0, 1, NA))) expect_true(vld_not_subset(1L, 0L)) expect_true(vld_not_subset(1, NA)) expect_false(vld_not_subset(c(NA, 1), 1)) expect_false(vld_not_subset(NA, NA)) expect_false(vld_not_subset(c(NA, 1), 1:2)) }) test_that("chk_not_subset", { expect_identical(chk_not_subset(integer(0), 1), integer(0), 1) expect_invisible(chk_not_subset(integer(0), 1)) expect_chk_error(chk_not_subset(1:3, c(0, 1, NA)), "`1:3` must not have any values matching 0, 1 or NA[.]$") expect_chk_error(chk_not_subset(1, c(0, 1, NA)), "^`1` must not match 1, 0 or NA[.]$") expect_chk_error(chk_not_subset(0L, 0L), c("^`0L` must not match 0[.]$")) }) chk/tests/testthat/test-chk-sorted.R0000644000176200001440000000102514436206156017171 0ustar liggesuserstest_that("vld_sorted", { expect_true(vld_sorted(TRUE)) expect_true(vld_sorted(1)) expect_true(vld_sorted(character(0))) expect_true(vld_sorted(NA)) expect_true(vld_sorted(1:2)) expect_false(vld_sorted(2:1)) expect_true(vld_sorted(c(1:2, NA))) expect_false(vld_sorted(c(2:1, NA))) }) test_that("chk_sorted", { expect_identical(chk_sorted(TRUE), TRUE) expect_invisible(chk_sorted(TRUE)) expect_identical(chk_sorted(c(x = TRUE)), c(x = TRUE)) expect_chk_error(chk_sorted(2:1), "^`2:1` must be sorted[.]$") }) chk/tests/testthat/test-expect-chk-error.R0000644000176200001440000000043314436206156020312 0ustar liggesuserstest_that("expect-chk-error", { expect_s3_class(expect_chk_error(chk_flag(1)), "chk_error") expect_error(expect_chk_error(chk_flag(TRUE)), "", class = "expectation_failure" ) expect_error(expect_chk_error(chk_flag(TRUE), class = "chk_error"), "`class` must be NULL.") }) chk/tests/testthat/test-chk-tz.R0000644000176200001440000000071714436206156016335 0ustar liggesuserstest_that("chk_tz", { expect_identical(chk_tz("UTC"), "UTC") expect_invisible(chk_tz("UTC")) expect_chk_error( chk_tz("TCU"), "^`\"TCU\"` must be a tz [(]non-missing scalar character of a recognized timezone[)][.]$" ) }) test_that("vld_tz", { expect_true(vld_tz("UTC")) expect_false(vld_tz("TCU")) expect_false(vld_tz(1)) expect_false(vld_tz(character(0))) expect_false(vld_tz(c("UTC", "UTC"))) expect_false(vld_tz(NA_character_)) }) chk/tests/testthat/test-chk-type.R0000644000176200001440000001064314436206156016660 0ustar liggesuserstest_that("vld_s3_class", { expect_true(vld_s3_class(1, "numeric")) expect_false(vld_s3_class(1L, "numeric")) expect_true(vld_s3_class(1L, "integer")) x <- list() class(x) <- c("a", "b") expect_true(vld_s3_class(x, "a")) expect_true(vld_s3_class(x, "b")) expect_false(vld_s3_class(getClass("MethodDefinition"), "classRepresentation")) }) test_that("chk_s3_class", { expect_identical(chk_s3_class(1L, "integer"), 1L, "integer") expect_invisible(chk_s3_class(1L, "integer")) expect_chk_error(chk_s3_class(1, "integer"), "^`1` must inherit from S3 class 'integer'[.]$") expect_chk_error( chk_s3_class(matrix(1), "numeric"), "`matrix[(]1[)]` must inherit from S3 class 'numeric'[.]$" ) x <- list() class(x) <- c("a", "b") expect_chk_error(chk_s3_class(x, "c"), "`x` must inherit from S3 class 'c'") expect_chk_error(chk_s3_class(x, "c", x_name = "c"), "C must inherit from S3 class 'c'") }) test_that("vld_s4_class", { expect_false(vld_s4_class(1, "numeric")) expect_true(vld_s4_class(getClass("MethodDefinition"), "classRepresentation")) }) test_that("chk_s4_class", { expect_identical( chk_s4_class(getClass("MethodDefinition"), "classRepresentation"), getClass("MethodDefinition"), "classRepresentation" ) expect_invisible(chk_s4_class(getClass("MethodDefinition"), "classRepresentation")) expect_chk_error(chk_s4_class(1, "integer"), "^`1` must inherit from S4 class 'integer'[.]$") expect_chk_error( chk_s4_class(matrix(1), "numeric"), "`matrix[(]1[)]` must inherit from S4 class 'numeric'[.]$" ) }) test_that("vld_whole_numeric", { expect_true(vld_whole_numeric(numeric(0))) expect_true(vld_whole_numeric(integer(0))) expect_false(vld_whole_numeric(logical(0))) expect_true(vld_whole_numeric(Inf)) expect_true(vld_whole_numeric(NA_integer_)) expect_true(vld_whole_numeric(NA_real_)) expect_false(vld_whole_numeric(NA)) expect_true(vld_whole_numeric(1)) expect_true(vld_whole_numeric(1L)) expect_false(vld_whole_numeric(1.1)) expect_false(vld_whole_numeric(-1.1)) expect_true(vld_whole_numeric(c(1, 2))) expect_false(vld_whole_numeric(TRUE)) }) test_that("chk_whole_numeric", { expect_identical(chk_whole_numeric(1L), 1L) expect_invisible(chk_whole_numeric(1L)) expect_identical(chk_whole_numeric(1), 1) expect_identical(chk_whole_numeric(Inf), Inf) expect_chk_error(chk_whole_numeric(TRUE), "^`TRUE` must be a whole numeric vector [(]integer vector or double equivalent[)][.]$") expect_chk_error(chk_whole_numeric(TRUE, x_name = "`c(1,2)`"), "^`c[(]1,2[)]` must be a whole numeric vector [(]integer vector or double equivalent[)][.]$") }) test_that("vld_list", { expect_true(vld_list(list())) expect_true(vld_list(list(1))) expect_true(vld_list(list(x = 1))) x <- list(x = 1) class(x) <- "nlist" expect_true(vld_list(x)) expect_false(vld_list(1)) }) test_that("chk_list", { expect_identical(chk_list(list()), list()) expect_invisible(chk_list(list())) expect_chk_error(chk_list(1), "^`1` must be a list[.]$") expect_chk_error(chk_list(1, x_name = "`list()`"), "^`list[(][)]` must be a list[.]$") }) test_that("vld_function", { expect_true(vld_function(c)) expect_true(vld_function(function() {})) expect_false(vld_function(1)) expect_true(vld_function(function() {}, formals = 0)) expect_false(vld_function(function() {}, formals = 1)) expect_true(vld_function(function(x = 1) {}, formals = 1)) expect_false(vld_function(function(x = 1, y = 3) {}, formals = 1)) }) test_that("chk_function", { expect_identical(chk_function(c), c) expect_invisible(chk_function(c)) expect_chk_error(chk_function(1), "^`1` must be a function[.]$") expect_chk_error(chk_function(1, x_name = "Function()"), "^Function[(][)] must be a function[.]$") expect_chk_error( chk_function(mean, formals = 3), "^`mean` must have 3 formal arguments [(]not 2[)][.]$" ) }) test_that("vld_scalar", { expect_true(vld_scalar(1)) expect_true(vld_scalar(NA)) expect_false(vld_scalar(integer(0))) expect_false(vld_scalar(1:2)) expect_false(vld_scalar(list())) expect_true(vld_scalar(list(x = 1))) expect_true(vld_scalar(matrix(1))) expect_false(vld_scalar(matrix(1:2))) expect_true(vld_scalar(data.frame(x = 1:10))) expect_false(vld_scalar(data.frame(x = 1, y = 2))) }) test_that("chk_scalar", { expect_identical(chk_scalar(1), 1) expect_invisible(chk_scalar(1)) expect_chk_error(chk_scalar(1:2), "^`1:2` must be a scalar [(]length 1[)][.]$") }) chk/tests/testthat/test-chk-dbl.R0000644000176200001440000000112714436206156016435 0ustar liggesuserstest_that("vld_dbl", { rlang::local_options(lifecycle_verbosity = "quiet") lifecycle::expect_deprecated(vld_dbl(1)) expect_true(vld_dbl(1)) expect_false(vld_dbl(matrix(c(1, 2)))) expect_true(vld_dbl(dbl(0))) expect_true(vld_dbl(NA_real_)) expect_false(vld_dbl(1L)) expect_false(vld_dbl(TRUE)) }) test_that("chk_dbl", { rlang::local_options(lifecycle_verbosity = "quiet") lifecycle::expect_deprecated(chk_dbl(1)) expect_identical(chk_dbl(1), 1) expect_invisible(chk_dbl(1)) expect_chk_error( chk_dbl(TRUE), "^`TRUE` must be double [(]real[)] scalar[.]$" ) }) chk/tests/testthat/test-chk-raw.R0000644000176200001440000000067414743771477016511 0ustar liggesuserstest_that("vld_raw", { expect_false(vld_raw(1L)) expect_false(vld_raw(matrix(1:4))) expect_true(vld_raw(raw(0))) expect_true(vld_raw(as.raw(1))) expect_true(vld_raw(as.raw(c(1,2)))) expect_false(vld_raw(1)) expect_false(vld_raw(TRUE)) }) test_that("chk_raw", { expect_identical(chk_raw(as.raw(1L)), as.raw(1L)) expect_invisible(chk_raw(as.raw(1L))) expect_chk_error( chk_raw(TRUE), "^`TRUE` must be raw[.]$" ) }) chk/tests/testthat/test-chk-integer.R0000644000176200001440000000066114436206156017333 0ustar liggesuserstest_that("vld_integer", { expect_true(vld_integer(1L)) expect_true(vld_integer(matrix(1:4))) expect_true(vld_integer(integer(0))) expect_true(vld_integer(NA_integer_)) expect_false(vld_integer(1)) expect_false(vld_integer(TRUE)) }) test_that("chk_integer", { expect_identical(chk_integer(1L), 1L) expect_invisible(chk_integer(1L)) expect_chk_error( chk_integer(TRUE), "^`TRUE` must be integer[.]$" ) }) chk/tests/testthat/test-chk-count.R0000644000176200001440000000116114436206156017022 0ustar liggesuserstest_that("vld_count", { expect_true(vld_count(1)) expect_true(vld_count(0)) expect_true(vld_count(100L)) expect_false(vld_count(0.5)) expect_false(vld_count(-1L)) expect_false(vld_count(NA_integer_)) expect_false(vld_count(integer(0))) }) test_that("chk_count", { expect_identical(chk_count(1), 1) expect_invisible(chk_count(1)) expect_chk_error(chk_count(1.1), "^`1.1` must be a count [(]non-negative non-missing integer scalar or double equivalent[)][.]$") expect_chk_error(chk_count(1.1, x_name = 1L), "^1 must be a count [(]non-negative non-missing integer scalar or double equivalent[)][.]$") }) chk/tests/testthat/test-chk-unique.R0000644000176200001440000000457714436206156017216 0ustar liggesuserstest_that("vld_unique", { expect_true(vld_unique(integer(0))) expect_true(vld_unique(NA)) expect_true(vld_unique(1)) expect_true(vld_unique(c(1, 2))) expect_true(vld_unique(c(1, NA))) expect_false(vld_unique(c(NA, NA))) expect_true(vld_unique(c(NA, NA), incomparables = NA)) expect_true(vld_unique(c(NA, NA, 1), incomparables = NA)) expect_false(vld_unique(c(1, 1))) expect_false(vld_unique(c(1, 2, 1))) }) test_that("chk_unique", { expect_identical(chk_unique(1), 1) expect_invisible(chk_unique(1)) expect_chk_error(chk_unique(c(1, 1)), "^`c[(]1, 1[)]` must be unique[.]$") expect_chk_error(chk_unique(c(1, 1), x_name = "unicorn"), "^Unicorn must be unique[.]$") }) test_that("vld_unique data frame", { data <- data.frame(x = 1:2) expect_true(vld_unique(data)) expect_true(vld_unique(data, incomparables = NA)) data <- data.frame(x = c(1, 1)) expect_false(vld_unique(data)) expect_false(vld_unique(data, incomparables = NA)) data <- data.frame(y = c(NA, NA)) expect_true(vld_unique(data, incomparables = NA)) data <- data.frame(x = 1:2, y = c(NA, NA)) expect_true(vld_unique(data)) expect_true(vld_unique(data, incomparables = NA)) data <- data.frame(x = c(1, 1), y = c(2, 2)) expect_true(vld_unique(data, incomparables = 2)) data <- data.frame(x = c(1, 1), y = c(NA, NA)) expect_true(vld_unique(data, incomparables = NA)) }) test_that("chk_unique data frame", { data <- data.frame(x = 1:2) expect_identical(chk_unique(data), data) expect_invisible(chk_unique(data)) data <- data.frame(y = c(NA, NA)) expect_chk_error(chk_unique(data), "^`data` must be unique[.]$") data <- data.frame(x = 1:2, y = c(NA, NA)) data <- data.frame(x = c(1, 1), y = c(2, 2)) expect_chk_error(chk_unique(data), "^`data` must be unique[.]$") data <- data.frame(x = c(1, 1), y = c(NA, NA)) expect_chk_error(chk_unique(data), "^`data` must be unique[.]$") }) test_that("vld_named", { expect_false(vld_named(list())) expect_false(vld_named(list(1))) expect_true(vld_named(list(x = 1))) expect_true(vld_named(list(x = 1)[-1])) expect_true(vld_named(c(x = 1))) expect_true(vld_named(c(x = 1)[-1])) }) test_that("chk_named", { expect_identical(chk_named(c(x = 1)), c(x = 1)) expect_invisible(chk_named(c(x = 1))) expect_chk_error(chk_named(1), "^`1` must be named[.]$") expect_chk_error(chk_named(1, x_name = "new born"), "^New born must be named[.]$") }) chk/tests/testthat/test-check-dim.R0000644000176200001440000000451514436206156016761 0ustar liggesuserstest_that("check_dim length", { expect_identical(check_dim(1), 1) expect_invisible(check_dim(1)) expect_chk_error( check_dim(1:2, dim = identity), "`dim[(]x[)]` must be a whole number [(]non-missing integer scalar or double equivalent[)][.]" ) expect_identical(check_dim(integer(0)), integer(0)) expect_chk_error( check_dim(integer(0), values = TRUE), "^`length[(]integer[(]0[)][)]` must be greater than 0, not 0[.]$" ) expect_chk_error( check_dim(1, values = FALSE), "^`length[(]1[)]` must be equal to 0L[.]" ) expect_identical(check_dim(2, values = 1), check_dim(2, values = 1)) expect_chk_error( check_dim(1, values = 2), "^`length[(]1[)]` must be equal to 2[.]" ) expect_chk_error( check_dim(1, values = 2:3), "^`length[(]1[)]` must be between 2 and 3, not 1[.]" ) expect_chk_error( check_dim(1, values = 3:2), "^`length[(]1[)]` must be between 2 and 3, not 1[.]" ) expect_identical(check_dim(1:2, values = 2:3), check_dim(1:2, values = 2:3)) expect_chk_error( check_dim(2, values = c(2, 2)), "`length[(]2[)]` must be equal to 2[.]" ) expect_chk_error( check_dim(2, values = c(2, 2, 2)), "`length[(]2[)]` must match 2, not 1[.]" ) expect_chk_error( check_dim(2, values = c(3, 2, 2)), "`length[(]2[)]` must match 2 or 3, not 1[.]" ) expect_chk_error( check_dim(1, values = 1.1), "^At least one of the following conditions must be met:\n[*] `values` must be a flag [(]TRUE or FALSE[)].\n[*] `values` must be a whole numeric vector \\(integer vector or double equivalent\\)\\.$" ) }) test_that("check_dim nrow", { expect_identical( check_dim(data.frame(x = 1), dim = nrow), check_dim(data.frame(x = 1), dim = nrow) ) expect_invisible(check_dim(data.frame(x = 1), dim = nrow)) expect_chk_error( check_dim(data.frame(x = integer(0)), values = TRUE, dim = nrow), "`nrow[(]data.frame[(]x = integer[(]0[)][)][)]` must be greater than 0, not 0[.]" ) expect_chk_error( check_dim(data.frame(x = integer(0)), dim = nrow, dim_name = "ncol", values = TRUE), "`ncol[(]data.frame[(]x = integer[(]0[)][)][)]` must be greater than 0, not 0[.]" ) expect_chk_error( check_dim(data.frame(x = integer(0)), dim = nrow, x_name = "y", dim_name = "ncol", values = TRUE), "`ncol[(]y[)]` must be greater than 0, not 0[.]" ) }) chk/tests/testthat/test-chk-array.R0000644000176200001440000000054314436206156017013 0ustar liggesuserstest_that("vld_array", { expect_false(vld_array(1)) expect_true(vld_array(array())) expect_true(vld_array(array(NA))) expect_true(vld_array(array(1))) }) test_that("chk_array", { expect_identical(chk_array(array(1)), array(1)) expect_invisible(chk_array(array(1))) expect_chk_error( chk_array(1), "^`1` must be an array[.]$" ) }) chk/tests/testthat/test-chk-vector.R0000644000176200001440000000110014436206156017165 0ustar liggesuserstest_that("vld_vector", { expect_true(vld_vector(1)) expect_true(vld_vector(NA)) expect_true(vld_vector(1:2)) expect_true(vld_vector(integer(0))) expect_true(vld_vector(list())) expect_true(vld_vector(list(x = 1))) x <- 1 attr(x, "oeu") <- 1 expect_true(vld_vector(x)) x <- list() class(x) <- "foo" expect_true(vld_vector(x)) expect_false(vld_vector(matrix(1))) }) test_that("chk_vector", { expect_identical(chk_vector(1), 1) expect_invisible(chk_vector(1)) expect_chk_error(chk_vector(matrix(1)), "^`matrix[(]1[)]` must be a vector[.]$") }) chk/tests/testthat/test-chk-double.R0000644000176200001440000000064214436206156017147 0ustar liggesuserstest_that("vld_double", { expect_true(vld_double(1)) expect_true(vld_double(matrix(c(1, 2)))) expect_true(vld_double(double(0))) expect_true(vld_double(NA_real_)) expect_false(vld_double(1L)) expect_false(vld_double(TRUE)) }) test_that("chk_double", { expect_identical(chk_double(1), 1) expect_invisible(chk_double(1)) expect_chk_error( chk_double(TRUE), "^`TRUE` must be double[.]$" ) }) chk/tests/testthat/test-chk-file.R0000644000176200001440000000637314436206156016623 0ustar liggesuserstest_that("vld_file", { expect_false(vld_file(character(0))) expect_false(vld_file(tempdir())) file <- withr::local_tempfile() expect_false(vld_file(file)) write.csv(data.frame(x = 1), file) expect_true(vld_file(file)) expect_false(vld_file(dirname(file))) }) test_that("chk_file", { expect_chk_error( chk_file(character(0)), "^`character[(]0[)]` must be a string [(]non-missing character scalar[)][.]$" ) expect_chk_error(chk_file(tempdir()), "`tempdir[(][)]` must specify a file [(]'.*' is a directory[)][.]$") file1 <- withr::local_tempfile(fileext = ".csv") expect_chk_error( chk_file(file1), "^`file1` must specify an existing file [(]'.*[.]csv' can't be found[)][.]$" ) write.csv(data.frame(x = 1), file1) expect_identical(chk_file(file1), file1) expect_invisible(chk_file(file1)) expect_identical(chk_all(character(0), chk_file), character(0), chk_file) expect_invisible(chk_all(character(0), chk_file)) expect_identical(chk_all(file1, chk_file), file1, chk_file) expect_invisible(chk_all(file1, chk_file)) expect_identical(chk_all(c(file1, file1), chk_file), c(file1, file1), chk_file) expect_invisible(chk_all(c(file1, file1), chk_file)) expect_chk_error( chk_all(c(file1, p0(file1, "b")), chk_file, x_name = "`vec`"), "^All elements of `vec` must specify an existing file [(]'.*[.]csvb' can't be found[)][.]$" ) }) test_that("vld_dir", { expect_false(vld_dir(character(0))) expect_true(vld_dir(tempdir())) expect_false(vld_dir(tempfile())) }) test_that("chk_dir", { expect_identical(chk_dir(tempdir()), tempdir()) expect_invisible(chk_dir(tempdir())) expect_chk_error( chk_dir(tempfile()), "^`tempfile[(][)]` must specify an existing directory [(]'.*' can't be found[)][.]$" ) file1 <- withr::local_tempfile(fileext = ".csv") write.csv(data.frame(x = 1), file1) expect_chk_error( chk_dir(file1), "^`file1` must specify a directory [(]'.*[.]csv' is a file[)][.]$" ) path <- withr::local_tempdir() unlink(path, recursive = TRUE) expect_chk_error(chk_dir(path), "^`path` must specify an existing directory [(]'.*' can't be found[)][.]$") expect_chk_error(chk_dir(1), "^`1` must be a string [(]non-missing character scalar[)][.]$") expect_invisible(chk_all(c(tempdir(), tempdir()), chk_dir)) expect_chk_error( chk_all(c(tempdir(), p0(tempdir(), "b")), chk_dir, x_name = "`vec`"), "^All elements of `vec` must specify an existing directory [(]'.*b' can't be found[)][.]$" ) }) test_that("vld_ext", { expect_false(vld_ext(character(0))) expect_false(vld_ext("file.pdf", "PDF")) expect_false(vld_ext(c("file.pdf", "file.pdf"), "pdf")) expect_true(vld_ext("file.pdf", "pdf")) expect_true(vld_ext("file.png", c("pdf", "png"))) }) test_that("chk_ext", { expect_chk_error( chk_ext(character(0)), "^`character[(]0[)]` must be a string [(]non-missing character scalar[)][.]$" ) expect_chk_error( chk_ext("file.pdf", "png"), "^`\"file.pdf\"` must have extension 'png' [(]not 'pdf'[)][.]$" ) expect_chk_error( chk_ext("file.pdf", c("png", "PDF")), "^`\"file.pdf\"` must have extension 'png' or 'PDF' [(]not 'pdf'[)][.]$" ) expect_identical(chk_ext("file.pdf", "pdf"), "file.pdf", "pdf") expect_invisible(chk_ext("file.pdf", "pdf")) }) chk/tests/testthat/test-chk-valid-name.R0000644000176200001440000000123514436206156017711 0ustar liggesuserstest_that("vld_valid_name", { expect_true(vld_valid_name(numeric(0))) expect_true(vld_valid_name(NA)) expect_true(vld_valid_name("name")) expect_true(vld_valid_name(c("name", NA))) expect_true(vld_valid_name(c("name", "name"))) expect_true(vld_valid_name(".")) expect_false(vld_valid_name(".1")) expect_false(vld_valid_name("1")) expect_false(vld_valid_name(c("1", NA))) }) test_that("chk_valid_name", { expect_identical(chk_valid_name("x"), "x") expect_invisible(chk_valid_name("x")) expect_chk_error(chk_valid_name(".1"), '^`".1"` must be valid name\\.$') expect_chk_error(chk_valid_name(".1", x_name = 1L), "^1 must be valid name\\.$") }) chk/tests/testthat/test-err.R0000644000176200001440000000614714436206156015730 0ustar liggesuserstest_that("message_chk", { expect_match(message_chk(), "^[.]$") expect_match(message_chk("", ""), "^[.]$") expect_match(message_chk("a"), "^A[.]$") expect_match(message_chk("`a`"), "^`a`[.]$") expect_match(message_chk("a", "b"), "^Ab[.]$") expect_match(message_chk(" a", " b"), "^ a b[.]$") expect_match(message_chk(" A", "b"), "^ Ab[.]$") expect_match(message_chk("Ab", "b"), "^Abb[.]$") expect_match(message_chk("Ab.", "b."), "^Ab[.]b[.]$") expect_match(message_chk("a"), "^A[.]$") expect_match(message_chk("a."), "^A[.]$") expect_match(message_chk("a!"), "^A!$") expect_match(message_chk("a?"), "^A[?]$") expect_match( message_chk("there %r %n problem director%y%s", n = 1), "There is 1 problem directory[.]$" ) expect_match( message_chk("there %r %n problem director%y%s", n = 2), "There are 2 problem directories[.]$" ) expect_match( message_chk("there %r %n problem director%y%s", n = 1.5), "There are 1.5 problem directories[.]$" ) expect_match( message_chk("there %r %n problem director%y%s", n = 0), "There are 0 problem directories[.]$" ) expect_match( message_chk("there %r %n problem director%y%s", n = 0, tidy = FALSE), "there are 0 problem directories$" ) }) test_that("err", { expect_error(err(), "^[.]$") expect_error(err("this", "is"), "^Thisis[.]$") expect_error( err("There %r %n problem value%s"), "There %r %n problem value%s[.]$" ) expect_error( err("there %r %n problem value%s", n = 2), "There are 2 problem values[.]$" ) expect_error( err("there %r %n problem value%s", n = 0, tidy = FALSE), "there are 0 problem values$" ) }) test_that("err .subclass deprecated", { lifecycle::expect_deprecated(expect_s3_class(expect_error(err(.subclass = "xx"), "^[.]$"), "xx")) expect_s3_class(expect_error(err(class = "xx"), "^[.]$"), "xx") }) test_that("msg", { expect_message(msg(), "^[.]") expect_message(msg("this", "is"), "^Thisis[.]") expect_message( msg("There %r %n problem value%s"), "^There %r %n problem value%s[.]" ) expect_message( msg("there %r %n problem value%s", n = 2), "^There are 2 problem values[.]" ) expect_message( msg("there %r %n problem value%s", n = 0, tidy = FALSE), "there are 0 problem values" ) }) test_that("msg .subclass deprecated", { lifecycle::expect_deprecated(expect_s3_class(expect_message(msg(.subclass = "xx"), "^[.]$"), "xx")) expect_s3_class(expect_message(msg(class = "xx"), "^[.]$"), "xx") }) test_that("wrn", { expect_warning(wrn(), "^[.]$") expect_warning(wrn("this", "is"), "^Thisis[.]$") expect_warning( wrn("there %r %n problem value%s"), "^There %r %n problem value%s." ) expect_warning( wrn("there %r %n problem value%s", n = 2), "^There are 2 problem values[.]$" ) expect_warning( wrn("there %r %n problem value%s", n = 0, tidy = FALSE), "there are 0 problem values$" ) }) test_that("wrn .subclass deprecated", { lifecycle::expect_deprecated(expect_s3_class(expect_warning(wrn(.subclass = "xx"), "^[.]$"), "xx")) expect_s3_class(expect_warning(wrn(class = "xx"), "^[.]$"), "xx") }) chk/tests/testthat/test-chk-lgl.R0000644000176200001440000000115614743771477016472 0ustar liggesuserstest_that("vld_lgl", { rlang::local_options(lifecycle_verbosity = "quiet") expect_true(vld_lgl(TRUE)) expect_true(vld_lgl(FALSE)) expect_false(vld_lgl(NA_real_)) expect_false(vld_lgl(logical(0))) expect_false(vld_flag(c(FALSE, TRUE))) expect_false(vld_lgl(1)) }) test_that("chk_lgl", { rlang::local_options(lifecycle_verbosity = "quiet") expect_identical(chk_lgl(NA), NA) expect_invisible(chk_lgl(NA)) expect_chk_error(chk_lgl(1), "^`1` must be a logical scalar [(]TRUE, FALSE or NA[)][.]$") expect_chk_error(chk_lgl(1, x_name = 2), "^2 must be a logical scalar [(]TRUE, FALSE or NA[)][.]$") }) chk/tests/testthat/test-chk-logical.R0000644000176200001440000000065614436206156017314 0ustar liggesuserstest_that("vld_logical", { expect_true(vld_logical(TRUE)) expect_true(vld_logical(matrix(TRUE))) expect_true(vld_logical(logical(0))) expect_true(vld_logical(NA)) expect_false(vld_logical(1)) expect_false(vld_logical("TRUE")) }) test_that("chk_logical", { expect_identical(chk_logical(TRUE), TRUE) expect_invisible(chk_logical(FALSE)) expect_chk_error( chk_logical(1), "^`1` must be logical[.]$" ) }) chk/tests/testthat/test-chk-not-empty.R0000644000176200001440000000140614436206156017630 0ustar liggesuserstest_that("vld_not_empty", { expect_true(vld_not_empty(1)) expect_true(vld_not_empty(matrix(1:3))) expect_true(vld_not_empty(NA)) expect_true(vld_not_empty(list(1))) expect_true(vld_not_empty(matrix(1))) expect_true(vld_not_empty(data.frame(x = 1))) expect_false(vld_not_empty(NULL)) expect_false(vld_not_empty(integer(0))) expect_false(vld_not_empty(list())) expect_false(vld_not_empty(matrix(integer(0)))) expect_false(vld_not_empty(data.frame())) }) test_that("chk_not_empty", { expect_identical(chk_not_empty(1), 1) expect_invisible(chk_not_empty(1)) expect_chk_error(chk_not_empty(NULL), "^`NULL` must not be empty [(]zero length[)][.]$") expect_chk_error(chk_not_empty(NULL, x_name = 1), "^1 must not be empty [(]zero length[)][.]$") }) chk/tests/testthat/test-chk-character-or-factor.R0000644000176200001440000000120014436206156021512 0ustar liggesuserstest_that("vld_character_or_factor", { expect_true(vld_character_or_factor("1")) expect_true(vld_character_or_factor(matrix("a"))) expect_true(vld_character_or_factor(character(0))) expect_true(vld_character_or_factor(NA_character_)) expect_false(vld_character_or_factor(1)) expect_false(vld_character_or_factor(TRUE)) expect_true(vld_character_or_factor(factor("text"))) }) test_that("chk_character_or_factor", { expect_identical(chk_character_or_factor("1"), "1") expect_invisible(chk_character_or_factor("1")) expect_chk_error( chk_character_or_factor(TRUE), "^`TRUE` must be character or factor[.]$" ) }) chk/tests/testthat/test-chk-subset.R0000644000176200001440000000301214436206156017174 0ustar liggesuserstest_that("vld_subset", { expect_true(vld_subset(integer(0), 1)) expect_false(vld_subset(1:3, 1:2)) expect_true(vld_subset(numeric(0), 1L)) expect_false(vld_subset(-1, c(0, 1, NA))) expect_false(vld_subset(1L, 0L)) expect_false(vld_subset(1, NA)) expect_false(vld_subset(c(NA, 1), 1)) expect_true(vld_subset(NA, NA)) expect_true(vld_subset(c(NA, 1), c(1, NA))) expect_false(vld_subset(c(NA, 1), 1:2)) }) test_that("chk_subset", { expect_identical(chk_subset(integer(0), 1), integer(0), 1) expect_invisible(chk_subset(integer(0), 1)) expect_chk_error(chk_subset(NA, c(0, Inf)), "^`NA` must match 0 or Inf, not NA[.]$") expect_chk_error(chk_subset(1:3, c(0, 1, NA)), "`1:3` must have values matching 0, 1 or NA[.]$") expect_chk_error(chk_subset(-1, c(0, 1, NA)), "^`-1` must match 0, 1 or NA, not -1[.]$") expect_chk_error(chk_subset(c(1L, 1L), 0L), c("^`c[(]1L, 1L[)]` must have values matching 0[.]$")) expect_chk_error(chk_subset(1, ""), "^`1` must match '', not 1[.]$") expect_chk_error( chk_subset(1, NA), "^`1` must match NA, not 1[.]$" ) expect_chk_error( chk_subset(c(NA, 1), 1), "^`c[(]NA, 1[)]` must have values matching 1[.]$" ) expect_chk_error( chk_subset(c(NA, 1), 1:2), "^`c[(]NA, 1[)]` must have values matching 1 or 2[.]$" ) expect_chk_error( chk_subset(3L, values = c(1L, 1L, 7L)), "^`3L` must match 1 or 7, not 3[.]$" ) expect_chk_error( chk_subset(3L, values = c(1L, 1L, 7L), x_name = "1"), "^1 must match 1 or 7, not 3[.]$" ) }) chk/tests/testthat.R0000644000176200001440000000060214654734236014160 0ustar liggesusers# This file is part of the standard setup for testthat. # It is recommended that you do not modify it. # # Where should you do additional test configuration? # Learn more about the roles of various files in: # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview # * https://testthat.r-lib.org/articles/special-files.html library(testthat) library(chk) test_check("chk") chk/MD50000644000176200001440000003707014745002005011333 0ustar liggesusers9bd22a0efe735ab9f59df8ef89484834 *DESCRIPTION 651b3ae388422e70e597ff8b28e846ef *LICENSE 2fd8fe87627f724ffc48326ba1f4da61 *NAMESPACE 4fabcc0ff78345318ac9132f69a94c0f *NEWS.md 2f60ab26870a6ffbab25701efc7612cf *R/aaa.R aaf379c56bfec2e8dd260b1a630bbb5c *R/cc.R 5d2b835b4691a17220ce35b4376bdff2 *R/check-data.R e9c9b3a20c9d5d6937fc8d9f02b26723 *R/check-dim.R 97994bf0fc864c4a99cde05965e7379d *R/check-dirs.R f2b8d638d6fbda916c8507e098bf3ca6 *R/check-files.R d2b591a70cf92ad38f264dd3f84a37bf *R/check-key.R 65d4619a812c06945cf51eb55fe5b0e1 *R/check-length.R 25a2438a2bce93f3e7fd7134442485bc *R/check-names.R 86e782f45b344cfc059e1cf7fb9832f8 *R/check-values.R 020b72db8cbbcabe9f9250cc65100ac0 *R/chk-all-equal.R 121258d3fd8865e0dfa14114987d9de3 *R/chk-all-equivalent.R 74245b3ea3c00344e07c80c419b1a723 *R/chk-all-identical.R f169f8cbcd6f58df280615fd308efe27 *R/chk-all.R b6fd59d10f2baf82426e770ab15f62b3 *R/chk-array.R 2fd1a9263625c1dc82669ad7d38f97fa *R/chk-atomic.R 5d86be605dd06b40b5758badba84106d *R/chk-character-or-factor.R 699c4993d072a241a7ae5f7e4ac9e65f *R/chk-character.R 0bc4f75d9f6b6018c14f0d2cc37876b2 *R/chk-chr.R 16d47529fcdf96fddfb9b8e129439e46 *R/chk-compatible-lengths.R 92761dd5a4a654d47690d0bb3b138e5a *R/chk-complex-number.R 2f5621aa7b300898c51c7ac7df27a824 *R/chk-complex.R da1a91f34a72667132d9839406cac3e7 *R/chk-count.R 20e00a35b906fd611411ebfce140b07b *R/chk-data.R c5a5b196e58e2a1359695b9c6a95b661 *R/chk-date.R 858d0937dadabf38cb1b36e3df01f826 *R/chk-datetime.R 89a8e5251530f605f0b0e34a70d95ec8 *R/chk-dbl.R a36f5a6a04ddc5f54cd3e737f8efda02 *R/chk-dir.R 9c223d3bc5a6644367b6f99c5f90617a *R/chk-double.R cba140330167dd20a7a24336d66306a0 *R/chk-environment.R 02cae4af18b7d161aebc3a56b807c076 *R/chk-equal.R 8ffb9fa16e139f6b96b367e328b59439 *R/chk-equivalent.R 63cd354da887e3209d9f69b0655fde20 *R/chk-ext.R c04ceeac630b309de5ac7dde01c532a4 *R/chk-factor.R a502cf3b6f6bc4055afa4a7d63bedf88 *R/chk-false.R d8e5bd442bbb8f1d694cabe11ab617e4 *R/chk-file.R 6b124b13a6443a6221e3f93b61f37446 *R/chk-flag.R 1da0194009631780023bd6f1266d5cc2 *R/chk-function.R c585c3fba121dbdb6d898abdc2776658 *R/chk-gt.R d7696f5674d6b741a568fca646db437e *R/chk-gte.R 9060b19decd5c2431a3f268233463cbd *R/chk-identical.R af82dbed58d5d59a02b765aa70ed8c88 *R/chk-integer.R a36b97652a92ed68520d8d8044707703 *R/chk-is.R 95c28e34efef596d4142606bc55a5200 *R/chk-join.R efe41274d6068980463d0fde1ff0d366 *R/chk-length.R 68a6d6e25d86188a622df7feb26c2f08 *R/chk-lgl.R 38cbdcabf64d14d7542288d839ec83b4 *R/chk-list.R 47b5292f101c61bc36e1d896e9fc4c3b *R/chk-logical.R 655bfd26342fc9b8602b953d8da5bdad *R/chk-lt.R 0f46c74771773e6f9ad1215966f90270 *R/chk-lte.R f7cc04a4009d8bb5df80dde58da4c66a *R/chk-match.R 156a8dc93243a4ea728a42eb6068b5a5 *R/chk-matrix.R b93e4b404981672689a8dd9f2d2f37c9 *R/chk-missing.R 68b61e991de5361c9fd5b5db295a4400 *R/chk-named.R 757a572c8c1438dcbc70f87b1610870a *R/chk-not-any-na.R f3981b2212b05cd3da30aadaaf9d57b9 *R/chk-not-empty.R b721bfa6e6193741eb221f4600c561f0 *R/chk-not-missing.R 6c18efab834cb0564a9b2d4c78bc4828 *R/chk-not-null.R c9c6472369fec2a929a9b373f617b31c *R/chk-not-subset.R bba8fee4122901bd92ddeda719a1e777 *R/chk-null-or.R 02fc80821f8fe6300815f704f5f94118 *R/chk-null.R b7edc89106cb3aea5a89744f7fbd40a1 *R/chk-number.R 668a2263fb23147c9f6cadb27fdf1605 *R/chk-numeric.R f93094f21c2ddaeccd078f59f343e7c3 *R/chk-orderset.R a44f65d8b1e7c7c45fb4454e76587cc5 *R/chk-package.R 15033fbd8318c01c25268f090efd5bfc *R/chk-range.R b051afb846531affd6fec55471a84838 *R/chk-raw.R af64f23003b2e59e461ff92d1b38c6dc *R/chk-s3-class.R bf57f4ebb671812214cd8e60a00a2272 *R/chk-s4-class.R f1fc44edd4307c06af7ad25a4e049f5c *R/chk-scalar.R d43e0055822c1a300484568fcfb71e0a *R/chk-setequal.R 65aca420994974c1e2fd5255d5b9c8e8 *R/chk-sorted.R 333776e1078fdbd262326d3059f6642d *R/chk-string.R 9df7dffa5c504da4c198046996f75473 *R/chk-subset.R 5661f5a81dedc64a192823502a20bca0 *R/chk-superset.R 42784cb95e750e8c474d261ad88be738 *R/chk-true.R 22ead4c001a2c949e31ba417f9c45214 *R/chk-tz.R 63e3af7712ee083399a7fed9d34f01ca *R/chk-unique.R 8c1a30527fcec14b4169092187193be4 *R/chk-unused.R 9b6f62519d7a842986095793ec93d539 *R/chk-used.R 4b23a81597418c5a3712426335577a22 *R/chk-valid-name.R 7bbf65bbbee483a0095027020f1e67a2 *R/chk-vector.R 8fa181ffa82643e636b336b1f9873c4e *R/chk-whole-number.R c7eb0b31ad6079bfae12b30a4d7c1240 *R/chk-whole-numeric.R 2237661129db033bd95d598f1fdc46bd *R/chk-wnum.R 2b661c584b0b66c9b36acfa5ae8166d1 *R/chkor-vld.R 12feeb7a8c74d05d919f87b7f14d166c *R/chkor.R 43f215a8f950d8d18caf9fffc3c48654 *R/deprecated.R 5cd9d80acc496cc7656a23acef38e2e3 *R/err.R 622cef554a0294e49ff731e9e374b8c8 *R/expect-chk-error.R 54ac5ce556c3b51dc0d206414e9770f7 *R/internal.R d4955d8ee62a67701119837f50ddfd80 *R/new-duplicated.R b79a003118d8484187973979086c6846 *R/p.R 5b7b692ef7a484808b60091718e4153f *R/params.R 71f75efab674af3a1a7d512229b8a2d9 *R/utils.R 74e3b723a5c8565a70366eb4e5a0a175 *README.md ab475bd02dd388bb7c907a643a8bde7c *build/vignette.rds 2d046451026ccd6b2aa8a9b9ef415b23 *inst/WORDLIST ce1970c8ae58cd06fe4fdb655da06602 *inst/doc/chk-families.R cbd9d27dae0b20dabe7892b229c320d8 *inst/doc/chk-families.Rmd aebbd8e74904858dc98abd1721d38157 *inst/doc/chk-families.html caa3ee823b156c83abc664f8cb282fda *inst/doc/chk.R 427c073d0ce4102d7c7c474b5491621d *inst/doc/chk.Rmd dfef6d68628fe02c97ff70c78b34addb *inst/doc/chk.html 4077d064b840cf5dd3d258388889dd98 *man/aaa.Rd cb807f1dfeba45a3bd724b1b746d380a *man/abort_chk.Rd daf6e076be681eb661f3fc39ade56770 *man/cc.Rd ae4d36a430c7f7e96ecddca18bcfeb16 *man/check_data.Rd 3390522e06f7b36ebeb81de95d30e030 *man/check_dim.Rd 2186bd70ab2fa9cf05cfc35f6a4c27f8 *man/check_dirs.Rd 83a8900690b605f1d7e887f82725bbb1 *man/check_files.Rd 930845c7daff0a84a1cccc6b9d58e5e3 *man/check_key.Rd 0fcd442aadafd9b83a9fde5560cfd485 *man/check_length.Rd b1bd44dfd7c8891327fe9d1fd1704126 *man/check_names.Rd 4236c8b2830515b3a8adac52788264d2 *man/check_values.Rd 22d0a6c579a34859afec8df7770c83d9 *man/chk-package.Rd 1459becd5b678480be256ec92cc7549b *man/chk_all.Rd 19a782e94641057d2fadf4f2adb4387e *man/chk_all_equal.Rd 40c746fe05a466aa085630704135cd2a *man/chk_all_equivalent.Rd caf7c4a8861172beae16b0be32112f2c *man/chk_all_identical.Rd fc9d8666a32bfc3845ae2111485a0925 *man/chk_array.Rd 369d7735f89a549bc8ed6a079c83521d *man/chk_atomic.Rd 49090587c79996c09985a5235fdf2c90 *man/chk_character.Rd 540d059771eab9574acc93ec7ee2a69e *man/chk_character_or_factor.Rd c15e039cc5b43162ed082c89a946726d *man/chk_chr.Rd 0f981bd6c28a0514f720dcb2d64c0513 *man/chk_compatible_lengths.Rd 61fb45367ecd23fa0abd5907d8fbb07d *man/chk_complex.Rd 20f7bf671839db643219da22c94508a9 *man/chk_complex_number.Rd 42129d18214f58d62de7e906589d2bc7 *man/chk_count.Rd 06f492d91b54d4f88bbf7d33f796048b *man/chk_data.Rd 1683a600d25ca6d64fa6c31af0c357aa *man/chk_date.Rd 9ab5a159d617d7f6b751c3ec6d7a51aa *man/chk_date_time.Rd 3585badc9b448df85a63d3550d26b543 *man/chk_dbl.Rd 1e2bc952c9809599f2cadf6f1dcfe3f5 *man/chk_deprecated.Rd d8262c26e2eee1ea4407ac1973622fea *man/chk_dir.Rd 07bd57e8d6773a379afd7aa58d08821c *man/chk_double.Rd b0f1cccd7f0535d9d77fd1de48315cd2 *man/chk_environment.Rd 62a397f561cac973b39b3c28ab7d26e1 *man/chk_equal.Rd 953546198e434acec30f5b0a4e3d9b23 *man/chk_equivalent.Rd 6cfcbf03fc5a0becad45a68feae54f50 *man/chk_ext.Rd afd4795c1aba41978a3aa3e0e1e059ee *man/chk_factor.Rd f00f82216496442ad7ee66b6e21c004c *man/chk_false.Rd d57902f631f9a9a46d781def06f64d80 *man/chk_file.Rd b4b0761b345f1d1e336e79c5f889ef87 *man/chk_flag.Rd a61f73a34c321988f753b75e2c0f833d *man/chk_function.Rd 79d9fdf75c0c229a377becec2a63c9c4 *man/chk_gt.Rd d6c9ec50f4535c241291b89c5b09249e *man/chk_gte.Rd e5bede8274cf43f36cce7ffd4785b28a *man/chk_identical.Rd 8cbbf6bb3d8a927e14e37c65a1208f6f *man/chk_integer.Rd 8538b6c967be4ab387f68dae8d58b345 *man/chk_is.Rd 880e42209c97bf35035569b7b992c0e9 *man/chk_join.Rd 8c25748276bdfcc5fc3567451e41904a *man/chk_length.Rd 5f7fae44fad3257f6e1f5d826c68f344 *man/chk_lgl.Rd f7704a691023a62d638003cd4db17d9f *man/chk_list.Rd 083ed38ce775d5704b94f52d6f406b73 *man/chk_logical.Rd ff521ad7a06dc2fd290ee92181fdb788 *man/chk_lt.Rd 3cfbc6399f6180e05b854523a526e146 *man/chk_lte.Rd 8bc6ae050ce2d81ef8a1554252ca70c0 *man/chk_match.Rd c7a8e9cb10fc9ea88b6bc2d3145eecfe *man/chk_matrix.Rd e727cdd4488b9332309715ff5bda6952 *man/chk_missing.Rd fb6b611dfb8e7e88880218542bac8207 *man/chk_named.Rd 38ec3636be922cab636d5adbaf56661d *man/chk_not_any_na.Rd a20cc10e27ed70cc6ce866feacde08ed *man/chk_not_empty.Rd f11af29a479bf93f50f93fc5678a74c0 *man/chk_not_missing.Rd b33f7ea67911322ba6b2e1d9c227b65c *man/chk_not_null.Rd 26e196b12c4f0ac2defb43cf949455ee *man/chk_not_subset.Rd 1863bcee19a5b7324bc441afb0b52714 *man/chk_null.Rd 0ba059f91b3165f2ad368082f0f1ff82 *man/chk_null_or.Rd 861511e730eeeba4419aaa8c86e8f4b4 *man/chk_number.Rd 2ac2e9103b8e9ffcac123cb3ce264287 *man/chk_numeric.Rd b176c17a9a7327d817803608ff48d387 *man/chk_orderset.Rd 4e780f12509bdda9030f674cd8e4db53 *man/chk_range.Rd 3faec66cf938cbed207e79679b9b32f6 *man/chk_raw.Rd da0c92da6818a261e6778acf4bc15e74 *man/chk_s3_class.Rd 09062ce0f20b54951230dc788604f70a *man/chk_s4_class.Rd 0d2027a232c499482b281821c04d7ca1 *man/chk_scalar.Rd a258b565b0d76b9db507d20c6262b0d6 *man/chk_setequal.Rd edb0b8fd833531d1df669c3b14dfa3db *man/chk_sorted.Rd 1eb9645e8af7056a25b44b8b17222603 *man/chk_string.Rd afda2b8fbd942e4cbcd4dd1a70cd8e87 *man/chk_subset.Rd 735b96c44a5be2be99402aa8480c7469 *man/chk_superset.Rd 6c6fc373894a1ddec1dd049c59c24982 *man/chk_true.Rd eb17bd1e4583b2279583ba676d256cd2 *man/chk_tz.Rd 232bf21d120cf28680304f51a2e79f06 *man/chk_unique.Rd 122167c89d3096c32e8409ad63642969 *man/chk_unused.Rd 8b1971f5861a27df517be89d4167d9f4 *man/chk_used.Rd 29052c64df85f461ee56af3e0ec59859 *man/chk_valid_name.Rd 74fb76f2e9ec2979ce64d5ac6432420a *man/chk_vector.Rd 74687e4d77583473f4904d2a840c9eb2 *man/chk_whole_number.Rd 15f8cd97ebe3dec453188144886b2762 *man/chk_whole_numeric.Rd 199845f2a9973e0237ccab86cdfe1cc0 *man/chk_wnum.Rd 387f8af6733f8acc43e216243cd793c8 *man/chkor.Rd 917eb8344acb62c12b45bac8771c8e0a *man/chkor_vld.Rd 47c6624c05f887cdb6ea34fc66a630a6 *man/deparse_backtick_chk.Rd 15483e80c71c29a10bbf1098c1cf1561 *man/err.Rd 6cbbb6d3f257be4d3af85432c0a0dddd *man/expect_chk_error.Rd cb1e46f469cfbbbde29c8b5113e1d789 *man/figures/lifecycle-archived.svg c0d2e5a54f1fa4ff02bf9533079dd1f7 *man/figures/lifecycle-defunct.svg 391f696f961e28914508628a7af31b74 *man/figures/lifecycle-deprecated.svg 691b1eb2aec9e1bec96b79d11ba5e631 *man/figures/lifecycle-experimental.svg 952b59dc07b171b97d5d982924244f61 *man/figures/lifecycle-maturing.svg 27b879bf3677ea76e3991d56ab324081 *man/figures/lifecycle-questioning.svg 46de21252239c5a23d400eae83ec6b2d *man/figures/lifecycle-retired.svg 6902bbfaf963fbc4ed98b86bda80caa2 *man/figures/lifecycle-soft-deprecated.svg ed42e3fbd7cc30bc6ca8fa9b658e24a8 *man/figures/lifecycle-stable.svg bf2f1ad432ecccee3400afe533404113 *man/figures/lifecycle-superseded.svg f3228000acce2b335e491936761be066 *man/figures/logo.png 234ffa92864020b0e354b6ca6ada68cf *man/message_chk.Rd 793528ca3e4a112dc64fe9805c90dc4c *man/p.Rd 36b4b9255e952c73c81024c342c5c71d *man/params.Rd f4f8b6eca375307b4088a537462173e0 *tests/testthat.R faa70dcfb76b2b66fe4974365efc01a2 *tests/testthat/test-aaa-deprecated.R d06c605bfceac9d7595d9de9c286aab4 *tests/testthat/test-cc.R e924162fffefc20d6bdd69406de9d54d *tests/testthat/test-check-data.R ab7d62e383db690c752aba28beae8b42 *tests/testthat/test-check-dim.R af9c7fc2787b92f0648bb408ace3352f *tests/testthat/test-check-dirs.R 96b7366c0de010c6bb59dfdb79e20233 *tests/testthat/test-check-files.R 5c9c9337b686616fc74c2d621a1ba10a *tests/testthat/test-check-key.R 2bf342bdd4feb484c8ecd7d66ae34db1 *tests/testthat/test-check-length.R c486beea4ac704bb916e194db36cbe16 *tests/testthat/test-check-names.R 465973144ed198f58d80d0346ecdccad *tests/testthat/test-check-values.R 93e7eb7a9797be141fdbedd735fa7cc6 *tests/testthat/test-chk-all.R ba277d3e7859b919891d9b53e6b572e0 *tests/testthat/test-chk-array.R 4262fd4eba9fae9ad41823181e40567f *tests/testthat/test-chk-atomic.R ac829640bfd8634cfacfbc5c6be8fd16 *tests/testthat/test-chk-character-or-factor.R cbbdf655b6440c13ef42abb8262f98bc *tests/testthat/test-chk-character.R 029cfdd0b2d014cbcc1385b1e48235cf *tests/testthat/test-chk-chr.R a35901619c71e717551955f101dbe64c *tests/testthat/test-chk-compatible-lengths.R d5378e5d5284cd09ddd898d75ab45334 *tests/testthat/test-chk-complex-number.R b72e79cf0106cc1e23c143ca77f53f6e *tests/testthat/test-chk-complex.R 5d93f8ce7cdd3773e7c3f9a54f702747 *tests/testthat/test-chk-count.R c8ef3c253f70fd202a0651a62c6eb342 *tests/testthat/test-chk-data.R a15c2dc19d96a278d67fef992c9377aa *tests/testthat/test-chk-date-time.R f33fdb6cee1dbc1bff93aee79518b149 *tests/testthat/test-chk-date.R 0a400c4c42c3ae22d8dd476d2c79c79b *tests/testthat/test-chk-dbl.R fdbced5985f6f8e21badee23e12c364a *tests/testthat/test-chk-double.R 12420a406f92e9299f2bd5c2b1b15563 *tests/testthat/test-chk-environment.R d0c6e9f7ee73a6e38b6c9a3055d9a35b *tests/testthat/test-chk-factor.R 24a34c32e2e6811711ca878141c274f3 *tests/testthat/test-chk-file.R 6520e33b870d2833206177a0679fdfc8 *tests/testthat/test-chk-identical.R 439f7ce62adae02d5d1d5b2674c73f20 *tests/testthat/test-chk-integer.R 4eed3d7b30df6b7411e573d8cfbb388b *tests/testthat/test-chk-is.R ec29639891ee30fe008e561edec8c9a8 *tests/testthat/test-chk-join.R 03d284804ba3f046e962eb883d298782 *tests/testthat/test-chk-length.R fec972a1efcf633a49bdde440de9194f *tests/testthat/test-chk-lgl.R cffe683ff70160a7c7d8714ecd4df045 *tests/testthat/test-chk-logical.R 2589a7e018123f6d3e06006b2a316299 *tests/testthat/test-chk-matrix.R d5cef7f74c9e12760e692abd9452f126 *tests/testthat/test-chk-missing.R e221f7fc64362d6dfe37170f685e3964 *tests/testthat/test-chk-not-any-na.R 6a406482c2a4169a76a14b9433f7ae08 *tests/testthat/test-chk-not-empty.R a9d6f8c89616158499c1942e22aad2ba *tests/testthat/test-chk-not-missing.R 3aaec2924a239bf5ce3cc216b2e09b1c *tests/testthat/test-chk-not-subset.R 1a2e4dfefc616d91ac18a560cf44f100 *tests/testthat/test-chk-null-or.R 355b1a8f2c4ef197f76216c3afe9e367 *tests/testthat/test-chk-null.R 1f77dc602af78ea057b320e5b17d0d4e *tests/testthat/test-chk-number.R 6ff252b473d6f417910e2366cad6083b *tests/testthat/test-chk-numeric.R 479e051ac792eac885fb08e6e9e86961 *tests/testthat/test-chk-orderset.R 3b8785becd2fb7ae9bc1eff7e812453e *tests/testthat/test-chk-range.R f4313f25235761d3d6965da7057426ee *tests/testthat/test-chk-raw.R cb36179ee86207d6b22208256045275b *tests/testthat/test-chk-setequal.R a07e120c0e6ee5e504ccf33a2dd6cdd6 *tests/testthat/test-chk-sorted.R 82ee871d72f58e3ca95b3da3ef69afc5 *tests/testthat/test-chk-string.R 0ab8e0eb11a9a87583cac877b2328e34 *tests/testthat/test-chk-subset.R 68654aaedd474be8b9a6b8c7aff00ab8 *tests/testthat/test-chk-superset.R 46eb76a5623b69c61ecddad0b7c90564 *tests/testthat/test-chk-true.R e2f5201847f49aef138bf04846937ae3 *tests/testthat/test-chk-type.R f7b809a0967702ae4778c92d327d499d *tests/testthat/test-chk-tz.R 0dfcddce1cdfa2f91dcc91659e1291d9 *tests/testthat/test-chk-unique.R 989bfe9b913a4a8d4f42689d15705d8e *tests/testthat/test-chk-unused.R 44100ffdf20b04c7c0ff5041d29fee51 *tests/testthat/test-chk-valid-name.R 07700895a1a156eccf0aeb1d754e0381 *tests/testthat/test-chk-vector.R 548271a38b86200b706acdef0bb557a6 *tests/testthat/test-chk-whole-number.R 91b5d9becf07e44280ddeb8d17680f90 *tests/testthat/test-chk-wnum.R 4fae5a25c15d64131939cb45663dac8e *tests/testthat/test-chkor-vld.R 95be74be917c1e6921f981830e3c423d *tests/testthat/test-chkor.R 83f337a58216a9ac8076a812bb694705 *tests/testthat/test-err.R d8bec539742826d8075c1932425f2ea8 *tests/testthat/test-expect-chk-error.R af2e6bf7d567d6bb0f1239cca2ea33a6 *tests/testthat/test-internal.R 24dbf5cd15c22f55560ffac92f4f045d *tests/testthat/test-p.R 5bfe8ce69e6e3f29036fa1cc55ad55d9 *tests/testthat/test-utils.R cbd9d27dae0b20dabe7892b229c320d8 *vignettes/chk-families.Rmd 427c073d0ce4102d7c7c474b5491621d *vignettes/chk.Rmd 7521cfa57509a47d8800d54f8706353d *vignettes/chk_diagram_II.png chk/R/0000755000176200001440000000000014744734003011226 5ustar liggesuserschk/R/chk-superset.R0000644000176200001440000000215114743771477014004 0ustar liggesusers#' Check Superset #' #' @description #' Checks if includes all values using #' #' `all(values %in% x)` #' #' Pay attention to the order of the arguments `value` and `x` #' in this function compared to [chk_subset()] #' #' @inheritParams params #' @inherit params return #' #' @family set_checkers #' #' @seealso [all()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_superset #' chk_superset(1:3, 1) #' try(chk_superset(1:3, 4)) #' @export chk_superset <- function(x, values, x_name = NULL) { if (vld_superset(x, values)) { return(invisible(x)) } values <- sort(unique(values), na.last = TRUE) if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) values <- values[!values %in% x] abort_chk(x_name, " must include ", cc(values, " and "), x = x, values = values) } #' @describeIn chk_superset Validates Superset #' #' @examples #' # vld_superset #' vld_superset(1:3, 1) #' vld_superset(1:3, 4) #' vld_superset(integer(0), integer(0)) #' @export vld_superset <- function(x, values) all(values %in% x) chk/R/new-duplicated.R0000644000176200001440000000461614436206156014266 0ustar liggesusers# from https://stevenmortimer.com/the-unfinished-duplicated-function/ new_duplicated <- function(x, incomparables = FALSE, fromLast = FALSE, ...) { if (!identical(incomparables, FALSE)) { n <- ncol(x) nmx <- names(x) nmincomparables <- names(incomparables) lincomparables <- length(incomparables) if (is.null(nmincomparables)) { if (lincomparables < n) { # pad any incomparables lists with the default value if list is shorter than the number columns in the supplied data.frame tmp <- c(incomparables, as.list(rep_len(FALSE, n - lincomparables))) names(tmp) <- nmx incomparables <- tmp } if (lincomparables > n) { # if the list is unnamed and there are more elements in the list than there are columns, then only first n elements warning(paste("more columns in 'incomparables' than x, only using the first", n, "elements")) incomparables <- incomparables[1:n] } } else { # for named lists, find match, else default value tmp <- as.list(rep_len(FALSE, n)) names(tmp) <- nmx i <- match(nmincomparables, nmx, 0L) if (any(i <= 0L)) { warning("not all columns named in 'incomparables' exist") } tmp[i[i > 0L]] <- incomparables[i > 0L] incomparables <- tmp[nmx] } # first determine duplicates, then override when an incomparable value is found in a row since the existence of even 1 incomparable value in a row means it cannot be a duplicate res <- duplicated(do.call("paste", c(x, sep = "\r")), fromLast = fromLast) # for better performance only bother with the columns that have incomparable values not set to the default: !identical(x, FALSE) run_incomp_check <- sapply(incomparables, FUN = function(x) { !identical(x, FALSE) }) if (sum(run_incomp_check) > 0L) { incomp_check <- mapply(FUN = function(column, incomparables) { match(column, incomparables) }, x[run_incomp_check], incomparables[run_incomp_check]) # any rows with an incomparable match means, TRUE, it can override the duplicated result overwrite <- apply(data.frame(incomp_check), 1, function(x) { any(!is.na(x)) }) res[overwrite] <- FALSE } return(res) } else if (length(x) != 1L) { duplicated(do.call("paste", c(x, sep = "\r")), fromLast = fromLast) } else { duplicated(x[[1L]], fromLast = fromLast, ...) } } chk/R/chk-chr.R0000644000176200001440000000223014436206156012666 0ustar liggesusers#' Check Character Scalar #' #' @description #' Checks if character scalar using #' #' `is.character(x) && length(x) == 1L` #' #' `r lifecycle::badge("deprecated")` #' #' @family deprecated #' #' @inheritParams params #' @inherit params return #' #' @family chk_character #' #' @examples #' chk_chr("a") #' try(chk_chr(1)) #' @export chk_chr <- function(x, x_name = NULL) { if (vld_chr(x)) { return(invisible(x)) } deprecate_soft( "0.6.1", what = "chk::chk_chr()", details = "Please use `chk::chk_scalar(x);` `chk::chk_character(x)` instead", id = "chk_chr" ) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be a character scalar", x = x) } #' @describeIn chk_chr Validate Character Scalar #' #' `r lifecycle::badge("deprecated")` #' #' @examples #' # vld_chr #' vld_chr("") #' vld_chr("a") #' vld_chr(NA_character_) #' vld_chr(c("a", "b")) #' vld_chr(1) #' @export vld_chr <- function(x) { deprecate_soft( "0.6.1", what = "chk::chk_chr()", details = "Please use `chk::chk_scalar(x);` `chk::chk_character(x)` instead", id = "chk_chr" ) is.character(x) && length(x) == 1L } chk/R/chk-integer.R0000644000176200001440000000161214743771477013570 0ustar liggesusers#' Check Integer #' #' @description #' Checks if integer using #' #' `is.integer(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.integer()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_integer #' chk_integer(1L) #' try(chk_integer(1)) #' @export chk_integer <- function(x, x_name = NULL) { if (vld_integer(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be integer", x = x) } #' @describeIn chk_integer Validate Integer #' #' @examples #' # vld_integer #' vld_integer(1L) #' vld_integer(matrix(1:4, nrow = 2L)) #' vld_integer(integer(0)) #' vld_integer(NA_integer_) #' vld_integer(1) #' vld_integer(TRUE) #' @export vld_integer <- function(x) is.integer(x) chk/R/chk-range.R0000644000176200001440000000345714743771477013240 0ustar liggesusers#' Checks range of non-missing values #' #' @description #' Checks all non-missing values fall within range using #' #' If inclusive #' #' `all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])` #' #' else #' #' `all(x[!is.na(x)] > range[1] & x[!is.na(x)] < range[2])` #' #' @inheritParams params #' @inherit params return #' #' @family range_checkers #' #' @seealso [all()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_range #' chk_range(0) #' try(chk_range(-0.1)) #' @export chk_range <- function(x, range = c(0, 1), inclusive = TRUE, x_name = NULL) { if (vld_range(x, range, inclusive)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { if (inclusive && range[1] == range[2]) { abort_chk(x_name, " must be ", cc(range[1]), ", not ", cc(x), x = x, range = range) } abort_chk( x_name, " must be between ", cc(range, " and "), ifelse(isTRUE(inclusive), "", " exclusive"), ", not ", cc(x) ) } if (inclusive && range[1] == range[2]) { abort_chk(x_name, " must have values of ", cc(range[1]), x = x, range = range) } abort_chk(x_name, " must have values between ", cc(range, " and "), ifelse(isTRUE(inclusive), "", " exclusive"), x = x, range = range ) } #' @describeIn chk_range Validate Range #' #' @examples #' # vld_range #' vld_range(numeric(0)) #' vld_range(0) #' vld_range(-0.1) #' vld_range(c(0.1, 0.2, NA)) #' vld_range(c(0.1, 0.2, NA), range = c(0, 1)) #' @export vld_range <- function(x, range = c(0, 1), inclusive = TRUE) { if (isTRUE(inclusive)) { return(all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])) } all(x[!is.na(x)] > range[1] & x[!is.na(x)] < range[2]) } chk/R/chk-orderset.R0000644000176200001440000000262214743771477013764 0ustar liggesusers#' Check Set Ordered #' #' @description #' Checks if the first occurrence of each shared element #' in x is equivalent to the first occurrence of each shared element in values using #' `vld_equivalent(unique(x[x %in% values]), values[values %in% x])`. #' #' @inheritParams params #' @return #' The `chk_` function throws an informative error if the test fails. #' #' The `vld_` function returns a flag indicating whether the test was met. #' #' @family set_checkers #' #' @seealso [vld_equivalent()] #' @seealso [unique()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' @export #' #' @examples #' #' # chk_orderset #' chk_orderset(1:2, 1:2) #' try(chk_orderset(2:1, 1:2)) chk_orderset <- function(x, values, x_name = NULL) { if (vld_orderset(x, values)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) values <- values[values %in% x] abort_chk(x_name, " must have (the first occurence of) each of the following elements in the following order: ", cc(values), x = x, values = values) } #' @describeIn chk_setequal Validate Set Ordered #' #' @export #' #' @examples #' #' # vld_orderset #' vld_orderset(1, 1) #' vld_orderset(1:2, 2:1) #' vld_orderset(1, 2:1) #' vld_orderset(1:2, 2) vld_orderset <- function(x, values) { vld_equivalent(unique(x[x %in% values]), values[values %in% x]) } chk/R/chk-not-any-na.R0000644000176200001440000000201514743771477014112 0ustar liggesusers#' Check Not Any Missing Values #' #' @description #' Checks if not any missing values using #' #' `!anyNA(x)` #' #' **Pass**: `1`, `1:2`, `"1"`, `logical(0)`. #' #' **Fail**: `NA`, `c(1, NA)`. #' #' @inheritParams params #' @inherit params return #' #' @family misc_checkers #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_not_any_na #' chk_not_any_na(1) #' try(chk_not_any_na(NA)) #' @export chk_not_any_na <- function(x, x_name = NULL) { if (vld_not_any_na(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must not have any missing values", x = x) } #' @describeIn chk_not_any_na Validate Not Any Missing Values #' #' @examples #' # vld_not_any_na #' vld_not_any_na(1) #' vld_not_any_na(1:2) #' vld_not_any_na(NA_real_) #' vld_not_any_na(integer(0)) #' vld_not_any_na(c(NA, 1)) #' vld_not_any_na(TRUE) #' @export vld_not_any_na <- function(x) !anyNA(x) chk/R/internal.R0000644000176200001440000000121114643320172013154 0ustar liggesusers# necessary hack because for data frames # argument 'incomparables != FALSE' is not used (yet) .anyDuplicated <- function(x, incomparables = FALSE) { if (vld_false(incomparables) || is.null(incomparables) || !length(incomparables)) { return(anyDuplicated(x)) } if (!is.data.frame(x)) { return(anyDuplicated(x, incomparables = incomparables)) } y <- as.data.frame(lapply(x, function(col, y) col %in% y, y = incomparables)) y <- apply(y, 1, any) x <- x[!y, , drop = FALSE] anyDuplicated(x) } # remove when no longer support R < 3.6.0 str2lang <- function(text) { ex <- parse(text = text, keep.source = FALSE) ex[[1L]] } chk/R/chk-wnum.R0000644000176200001440000000243314436206156013105 0ustar liggesusers#' Check Whole Numeric Scalar #' #' @description #' Checks if whole numeric scalar using #' #' `is.numeric(x) && length(x) == 1L && (is.integer(x) || vld_true(all.equal(x, trunc(x))))` #' #' `r lifecycle::badge("deprecated")` #' #' @inheritParams params #' @inherit params return #' #' #' @family deprecated #' #' @examples #' # chk_wnum #' chk_wnum(1) #' try(chk_wnum(1.1)) #' @export chk_wnum <- function(x, x_name = NULL) { if (vld_wnum(x)) { return(invisible(x)) } deprecate_soft( "0.6.1", what = "chk::chk_wnum()", details = "Please use `chk::chk_scalar(x);` `chk::chk_whole_numeric(x)` instead", id = "chk_wnum" ) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be a whole numeric scalar", x = x) } #' @describeIn chk_wnum Validate Whole Numeric Scalar #' #' `r lifecycle::badge("deprecated")` #' #' @examples #' # vld_wnum #' vld_wnum(1) #' vld_wnum(double(0)) #' vld_wnum(NA_real_) #' vld_wnum(c(1, 1)) #' vld_wnum(1L) #' @export vld_wnum <- function(x) { deprecate_soft( "0.6.1", what = "chk::chk_wnum()", details = "Please use `chk::chk_scalar(x);` `chk::chk_whole_numeric(x)` instead", id = "chk_wnum" ) is.numeric(x) && length(x) == 1L && (is.integer(x) || vld_true(all.equal(x, trunc(x)))) } chk/R/err.R0000644000176200001440000000673614507602140012146 0ustar liggesusers#' Construct Tidyverse Style Message #' #' If `tidy = TRUE` constructs a tidyverse style message by #' #' \itemize{ #' \item Capitalizing the first character if possible. #' \item Adding a trailing . if missing. #' } #' #' Also if `n != NULL` replaces the recognized `sprintf`-like types. #' #' @section `sprintf`-like types: #' #' The following recognized `sprintf`-like types can be used in a message: #' #' \describe{ #' \item{`n`}{The value of n.} #' \item{`s`}{'' if n == 1 otherwise 's'} #' \item{`r`}{'is' if n == 1 otherwise 'are'} #' \item{`y`}{'y' if n == 1 otherwise 'ie'} #' } #' #' @param ... Multiple objects that are converted to a string using #' `paste0(..., collapse = '')`. #' @param n The value of n for converting `sprintf`-like types. #' @param tidy A flag specifying whether capitalize the first character and add a missing period. #' #' @return A string of the message. #' @export #' #' @examples #' message_chk("there %r %n", " problem director%y%s") #' message_chk("there %r %n", " problem director%y%s", n = 1) #' message_chk("There %r %n", " problem director%y%s.", n = 3) message_chk <- function(..., n = NULL, tidy = TRUE) { string <- p0(..., collapse = "") if (!is.null(n)) { string <- gsub("%r", if (n == 1) "is" else "are", string, fixed = TRUE) string <- gsub("%s", if (n == 1) "" else "s", string, fixed = TRUE) string <- gsub("%y", if (n == 1) "y" else "ie", string, fixed = TRUE) string <- gsub("%n", n, string, fixed = TRUE) } if (vld_true(tidy)) { if (!grepl("([.]|[?]|[!])$", string)) string <- p0(string, ".") string <- p0(toupper(substr(string, 1, 1)), substr(string, 2, nchar(string))) } string } #' Stop, Warning and Message Messages #' #' The functions call [message_chk()] to process #' the message and then #' [rlang::abort()], [rlang::warn()] and #' [rlang::inform()], respectively. #' #' The user can set the subclass. #' @param .subclass A string of the class of the error message. #' @inheritParams base::stop #' @inheritParams rlang::abort #' @inheritParams message_chk #' @name err NULL #' @describeIn err Error #' #' @export #' #' @examples #' #' # err #' try(err("there %r %n problem value%s", n = 2)) err <- function(..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL, call = rlang::caller_call(3)) { if (!is.null(.subclass)) { deprecate_soft("0.8.1", "err(.subclass)", "err(class)") class <- .subclass } args <- list2(...) named <- (names2(args) != "") msg <- exec(p0, !!!args[!named], collapse = "") msg <- message_chk(msg, n = n, tidy = tidy) if (!is.null(args$y)) { msg <- paste0( msg, "\nUse `rlang::last_error()$y` to show the object compared to." ) } rlang::abort( msg, class = class, !!!args[named], call = call ) } #' @describeIn err Warning #' #' @export #' #' @examples #' #' # wrn #' wrn("there %r %n problem value%s", n = 2) wrn <- function(..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL) { if (!is.null(.subclass)) { deprecate_soft("0.8.1", "wrn(.subclass)", "wrn(class)") class <- .subclass } warn(message_chk(..., n = n, tidy = tidy), class = class) } #' @describeIn err Message #' #' @export #' #' @examples #' #' # msg #' msg("there %r %n problem value%s", n = 2) msg <- function(..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL) { if (!is.null(.subclass)) { deprecate_soft("0.8.1", "msg(.subclass)", "msg(class)") class <- .subclass } inform(message_chk(..., n = n, tidy = tidy), class = class) } chk/R/p.R0000644000176200001440000000076314436206156011617 0ustar liggesusers#' Concatenate Strings #' #' A wrapper on [base::paste()]. #' #' @inheritParams base::paste #' #' @return A character vector. #' @export #' #' @examples #' p("a", "b") #' p(c("a", "b"), collapse = " ") p <- function(..., sep = " ", collapse = NULL) { paste(..., sep = sep, collapse = collapse) } #' @describeIn p A wrapper on [base::paste0()] #' @export #' #' @examples #' p0("a", "b") #' p0(c("a", "b"), collapse = "") p0 <- function(..., collapse = NULL) { paste0(..., collapse = collapse) } chk/R/chk-complex.R0000644000176200001440000000163714743771477013611 0ustar liggesusers#' Check Complex #' #' @description #' Checks if complex using #' #' `is.complex(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.complex()] #' @seealso For more details about the use of this function, #' please read the article #' \href{https://poissonconsulting.github.io/chk/articles/chk-families.html}{chk families}. #' #' @examples #' # chk_complex #' chk_complex(1i) #' try(chk_complex(1)) #' @export chk_complex <- function(x, x_name = NULL) { if (vld_complex(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be complex", x = x) } #' @describeIn chk_complex Validate Complex #' #' @examples #' # vld_complex #' vld_complex(1i) #' vld_complex(complex()) #' vld_complex(NA_complex_) #' vld_complex(1) #' vld_complex(TRUE) #' @export vld_complex <- function(x) is.complex(x) chk/R/chk-complex-number.R0000644000176200001440000000215514743771477015073 0ustar liggesusers#' Check Complex Number #' #' @description #' Checks if non-missing complex scalar using #' #' `is.complex(x) && length(x) == 1L && !anyNA(x)` #' #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checker #' #' @seealso [is.integer()] #' @seealso [vld_true()] #' @seealso [vld_number()] #' #' @seealso For more details about the use of this function, #' please read the article #' \href{https://poissonconsulting.github.io/chk/articles/chk-families.html}{chk families}. #' #' @examples #' # chk_complex_number #' chk_complex_number(as.complex(1.1)) #' try(chk_complex_number(1.1)) #' @export chk_complex_number <- function(x, x_name = NULL) { if (vld_complex_number(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk( x_name, " must be a complex number (non-missing complex scalar)", x = x ) } #' @describeIn chk_complex_number Validate Complex Number #' #' @examples #' # vld_complex_number #' vld_complex_number(as.complex(2)) #' @export vld_complex_number <- function(x) { is.complex(x) && length(x) == 1L && !anyNA(x) } chk/R/chk-logical.R0000644000176200001440000000206414743771477013547 0ustar liggesusers#' Check Logical #' #' @description #' Checks if logical using #' #' `is.logical(x)` #' #' If you want to check if it is a scalar, #' meaning that in addition to being of logical type, #' it has `length(x) == 1`, you should use [chk_lgl()] #' #' @inheritParams params #' @inherit params return #' #' @family logical_checkers #' @family data_type_checkers #' #' @seealso [is.logical()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_logical #' chk_logical(TRUE) #' try(chk_logical(1)) #' @export chk_logical <- function(x, x_name = NULL) { if (vld_logical(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be logical", x = x) } #' @describeIn chk_logical Validate Logical #' #' @examples #' # vld_logical #' vld_logical(TRUE) #' vld_logical(matrix(TRUE)) #' vld_logical(logical(0)) #' vld_logical(NA) #' vld_logical(1) #' vld_logical("TRUE") #' @export vld_logical <- function(x) is.logical(x) chk/R/chk-named.R0000644000176200001440000000162114743771477013217 0ustar liggesusers#' Check Named #' #' @description #' Checks if is named using #' #' `!is.null(names(x))` #' #' @inheritParams params #' @inherit params return #' #' @family name_checkers #' #' @seealso [names()] #' @seealso [is.null()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_named #' chk_named(c(x = 1)) #' try(chk_named(list(1))) #' @export chk_named <- function(x, x_name = NULL) { if (vld_named(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be named", x = x) } #' @describeIn chk_named Validate Named #' #' @examples #' # vld_named #' vld_named(c(x = 1)) #' vld_named(list(x = 1)) #' vld_named(c(x = 1)[-1]) #' vld_named(list(x = 1)[-1]) #' vld_named(1) #' vld_named(list(1)) #' @export vld_named <- function(x) !is.null(names(x)) chk/R/chk-compatible-lengths.R0000644000176200001440000000465014743771477015721 0ustar liggesusers#' Check Compatible Lengths #' #' Checks objects (including vectors) have lengths that could be 'strictly #' recycled'. That is to say they must all be either zero length or the same #' length with some of length 1. #' #' @inheritParams params #' @param ... The objects to check for compatible lengths. #' @return The `chk_` function throws an informative error if the test fails. #' @details This function helps to check vectors could be 'strictly recycled.' #' For example the function will error if you had a vector of length 2 and #' length 4, even though the vector of length 2 could be 'loosely recycled' to #' match up to the vector of length 4 when combined. #' #' The intent of the function is to check that only strict recycling is #' occurring. #' #' @family length_checkers #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_compatible_lengths #' #' a <- integer(0) #' b <- numeric(0) #' chk_compatible_lengths(a, b) #' #' a <- 1 #' b <- 2 #' chk_compatible_lengths(a, b) #' #' a <- 1:3 #' b <- 1:3 #' chk_compatible_lengths(a, b) #' #' b <- 1 #' chk_compatible_lengths(a, b) #' #' b <- 1:2 #' try(chk_compatible_lengths(a, b)) #' #' b <- 1:6 #' try(chk_compatible_lengths(a, b)) #' @export chk_compatible_lengths <- function(..., x_name = NULL) { if (vld_compatible_lengths(...)) { return(invisible()) } if (is.null(x_name)) { x_name <- "... objects" } chk_string(x_name) vec_lengths <- lengths(list(...)) length_set <- sort(unique(vec_lengths)) abort_chk( x_name, paste0( " must be all zero length or the same length with some of length of 1 ", "but not lengths " ), cc(length_set, conj = " and ") ) } #' @describeIn chk_compatible_lengths Validate Compatible Lengths #' @export #' @examples #' # vld_compatible_lengths #' #' a <- integer(0) #' b <- numeric(0) #' vld_compatible_lengths(a, b) #' #' a <- 1 #' b <- 2 #' vld_compatible_lengths(a, b) #' #' a <- 1:3 #' b <- 1:3 #' vld_compatible_lengths(a, b) #' #' b <- 1 #' vld_compatible_lengths(a, b) #' #' b <- 1:2 #' vld_compatible_lengths(a, b) #' #' b <- 1:6 #' vld_compatible_lengths(a, b) vld_compatible_lengths <- function(...) { vec_lengths <- lengths(list(...)) length_set <- unique(vec_lengths) if (length(length_set) <= 1) { return(TRUE) } if (length(length_set) >= 3) { return(FALSE) } min(length_set) == 1 } chk/R/chk-factor.R0000644000176200001440000000154214743771477013413 0ustar liggesusers#' Check Factor #' #' @description #' Checks if factor using #' #' `is.factor(x)` #' #' @inheritParams params #' @inherit params return #' #' @family factor_checkers #' @family data-type_checkers #' #' @seealso [is.factor()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_factor #' chk_factor(factor("1")) #' try(chk_factor("1")) #' @export chk_factor <- function(x, x_name = NULL) { if (vld_factor(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be factor", x = x) } #' @describeIn chk_factor Validate Factor #' #' @examples #' # vld_factor #' vld_factor(factor("1")) #' vld_factor(factor(0)) #' vld_factor("1") #' vld_factor(1L) #' @export vld_factor <- function(x) is.factor(x) chk/R/chkor-vld.R0000644000176200001440000000337714736037052013255 0ustar liggesuserstry_chk <- function(quo) { catch_cnd(eval_tidy(quo), classes = "error") } try_msg <- function(x) { # FIXME: Tests fail when the code below is changed to conditionMessage(x) # because rlang implements conditionMessage.rlang_error() . # Does that output look satisfactory? conditionMessage.condition(x) } chkor_quos <- function(quos) { n <- length(quos) if (n == 0L) { return(invisible()) } msg <- character(n) for (i in seq_len(n)) { try <- try_chk(quos[[i]]) if (is.null(try)) { return(invisible()) } msg[[i]] <- try_msg(try) } msg <- unique(msg) if (length(msg) > 1) { msg <- p0(msg, collapse = "\n* ") msg <- p0("At least one of the following conditions must be met:\n* ", msg) } abort_chk(msg) } vld__to_chk_ <- function(quo) { str <- deparse(quo) str <- sub("^vld_", "chk_", str) str2lang(str) } #' Chk OR #' #' @param ... Multiple `vld_` calls. #' #' A common mistake is to pass `chk_` calls. #' #' `chkor_vld()` is relatively slow. #' If at all possible use [chk_null_or()] or first test using the individual #' `vld_` functions and then call `chkor_vld()` to generate an informative #' error message. #' #' @return An informative error if the test fails. #' #' @seealso [chk_null_or()] #' #' @export #' #' @examples #' chkor_vld() #' chkor_vld(vld_flag(TRUE)) #' try(chkor_vld(vld_flag(1))) #' try(chkor_vld(vld_flag(1), vld_flag(2))) #' chkor_vld(vld_flag(1), vld_flag(TRUE)) chkor_vld <- function(...) { quos <- enquos(...) n <- length(quos) if (n == 0L) { return(invisible()) } for (quo in quos) { if (eval_tidy(quo)) { return(invisible()) } } for (i in seq_len(n)) { quos[[i]] <- quo_set_expr(quos[[i]], vld__to_chk_(quo_get_expr(quos[[i]]))) } chkor_quos(quos) } chk/R/check-values.R0000644000176200001440000000501014436206156013720 0ustar liggesusers#' Check Values and Class #' #' @description #' Checks values and S3 class of an atomic object. #' #' @details #' To check the class simply pass a vector of the desired class. #' #' To check that x does not include missing values pass #' a single non-missing value (of the correct class). #' #' To allow it to include missing values include a missing value. #' #' To check that it only includes missing values only pass #' a missing value (of the correct class). #' #' To check the range of the values in x pass two non-missing values #' (as well as the missing value if required). #' #' To check that x only includes specific values #' pass three or more non-missing values. #' #' In the case of a factor ensure values has two levels to #' check that the levels of x are an ordered superset of the levels of value #' and three or more levels to check that they are identical. #' #' @inheritParams params #' @param values An atomic vector specifying the S3 class and possible values. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' check_values(1, numeric(0)) #' check_values(1, 2) #' try(check_values(1, 1L)) #' try(check_values(NA_real_, 1)) #' @export check_values <- function(x, values, x_name = NULL) { if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) chk_atomic(x, x_name = x_name) chk_vector(values) chk_atomic(values) class <- class(values)[1] chk_s3_class(x, class, x_name = x_name) if (is.factor(values) && nlevels(values) > 1) { x_name_levels <- backtick_chk(p0("levels(", unbacktick_chk(x_name), ")")) if (nlevels(values) > 2) { chk_identical(levels(x), levels(values), x_name = x_name_levels) } else { chk_superset(levels(x), levels(values), x_name = x_name_levels) chk_orderset(levels(x), levels(values), x_name = x_name_levels) } } if (!length(x) || !length(values)) { return(invisible(x)) } if (vld_not_any_na(values)) chk_not_any_na(x, x_name = x_name) x <- x[!is.na(x)] values <- values[!is.na(values)] if (!length(x) || length(values) < 2) { return(invisible(x)) } if (identical(length(values), 2L)) { values <- sort(unique(values)) if (identical(length(values), 1L)) { return(chk_all(x, chk_equal, values, x_name = x_name)) } if (is.factor(values) && (nlevels(values) < 3 || !is.ordered(values))) { return(invisible()) } return(chk_range(x, values, x_name = x_name)) } chk_subset(x, sort(unique(values)), x_name = x_name) } chk/R/aaa.R0000644000176200001440000000055514436206156012101 0ustar liggesusers#' Workaround: Avoid backtraces in examples #' #' This example will run first and set the option for the process that builds #' the example. #' (By default, pkgdown builds in a separate process.) #' This also produces a help page that isn't linked from anywhere. #' #' @name aaa #' @keywords internal #' @examples #' options(rlang_backtrace_on_error = "none") NULL chk/R/deprecated.R0000644000176200001440000001004314436206156013450 0ustar liggesusers#' Deprecated functions #' #' #' Deprecated `chk_()` functions. #' #' @family deprecated #' #' @inheritParams chk_flag #' @keywords internal #' @name chk_deprecated NULL #' @describeIn chk_deprecated Check Directories Exist #' #' `r lifecycle::badge("deprecated")` #' #' Replace with `[chk_all](x, [chk_dir])` #' #' @export chk_dirs <- function(x) { deprecate_warn("0.2.0", what = "chk::chk_dirs()", details = "Please use `chk_all(x, chk_dir)` instead" ) chk_all(x, chk_dir) } #' @describeIn chk_deprecated Check Files Exist #' #' `r lifecycle::badge("deprecated")` #' #' Replace with `[chk_all](x, [chk_file])` #' #' @export chk_files <- function(x) { deprecate_warn("0.2.0", what = "chk::chk_files()", details = "Please use `chk_all(x, chk_file)` instead" ) chk_all(x, chk_file) } #' @describeIn chk_deprecated Check Has #' #' `r lifecycle::badge("deprecated")` #' #' Replace by [chk_superset()] #' #' @export chk_has <- function(x, values, x_name = NULL) { if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_superset(x, values, x_name = x_name) deprecate_warn("0.2.0", what = "chk::chk_has()", with = "chk::chk_superset()" ) invisible() } #' @describeIn chk_deprecated Check In #' #' `r lifecycle::badge("deprecated")` #' #' Replace by [chk_subset()] #' #' @export chk_in <- function(x, values, x_name = NULL) { if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_subset(x, values, x_name = x_name) deprecate_warn("0.2.0", what = "chk::chk_in()", with = "chk::chk_subset()" ) invisible() } #' @describeIn chk_deprecated Check No Missing Values #' #' `r lifecycle::badge("deprecated")` #' #' Replace with [chk_not_any_na()] #' #' @export chk_no_missing <- function(x, x_name = NULL) { deprecate_warn("0.2.0", what = "chk::chk_no_missing()", with = "chk::chk_not_any_na()", id = "chk_no_missing" ) if (vld_no_missing(x)) { return(invisible()) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must not have missing values", x = x) } #' @describeIn chk_deprecated Validate No Missing Values #' #' `r lifecycle::badge("deprecated")` #' #' Replace with [vld_not_any_na()] #' #' @export vld_no_missing <- function(x) { deprecate_warn("0.2.0", what = "chk::vld_no_missing()", with = "chk::vld_not_any_na()", id = "chk_no_missing" ) !anyNA(x) } #' @describeIn chk_deprecated Turns checking off #' #' `r lifecycle::badge("deprecated")` #' #' This approach is no longer recommended #' #' @export chk_off <- function() { deprecate_stop("0.2.0", what = "chk::chk_off()", details = "This approach is no longer recommended" ) options(chk.on = FALSE) } #' @describeIn chk_deprecated Turns checking on #' #' `r lifecycle::badge("deprecated")` #' #' This approach is no longer recommended #' #' @export chk_on <- function() { deprecate_stop("0.2.0", what = "chk::chk_on()", details = "This approach is no longer recommended" ) options(chk.on = TRUE) } #' @describeIn chk_deprecated Tests checking on #' #' `r lifecycle::badge("deprecated")` #' #' This approach is no longer recommended #' #' @export is_chk_on <- function() { deprecate_stop("0.2.0", what = "chk::is_chk_on()", details = "This approach is no longer recommended" ) getOption("chk.on", TRUE) } #' @describeIn chk_deprecated Check Proportion #' #' `r lifecycle::badge("deprecated")` #' #' Replace by `[chk_number](x); [chk_range](x)` #' #' @export chk_proportion <- function(x, x_name = NULL) { deprecate_warn("0.2.0", what = "chk::chk_proportion()", details = "Please use `chk_number(x)` or `chk_range(x)` instead" ) if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_number(x) chk_range(x) } #' @describeIn chk_deprecated Deparse Backtick #' #' `r lifecycle::badge("deprecated")` #' #' Replace with [deparse_backtick_chk()] #' #' @export deparse_backtick <- function(x) { deprecate_warn("0.2.0", what = "chk::deparse_backtick()", with = "chk::deparse_backtick_chk()" ) deparse_backtick_chk(x) } chk/R/check-dirs.R0000644000176200001440000000211314436206156013363 0ustar liggesusers#' Check Directories Exist #' #' @description #' Checks if all directories exist (or if exists = FALSE do not exist as directories or files). #' #' @inheritParams params #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' check_dirs(tempdir()) #' try(check_dirs(tempdir(), exists = FALSE)) #' @export check_dirs <- function(x, exists = TRUE, x_name = NULL) { if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) chk_character(x, x_name = x_name) chk_vector(x, x_name = x_name) chk_not_any_na(x, x_name = x_name) chk_flag(exists) dirs <- vapply(x, vld_file, TRUE) if (any(dirs)) { abort_chk(x_name, " must specify directories ('", x[dirs][1], "' is a file)", x = x) } x <- x[vapply(x, vld_dir, TRUE) != exists] if (!length(x)) { return(invisible(x)) } x <- x[1] if (exists) { abort_chk(x_name, " must specify existing directories ('", x, "' can't be found)", x = x) } abort_chk(x_name, " must not specify existing directories ('", x, "' exists)", x = x) } chk/R/chk-whole-number.R0000644000176200001440000000233114743771477014536 0ustar liggesusers#' Check Whole Number #' #' @description #' Checks if non-missing integer scalar or double equivalent using #' #' `vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x))))` #' #' **Pass**: `1`, `2L`, `1e10`, `-Inf` #' #' **Fail**: `"a"`, `1:3`, `NA_integer_`, `log(10)` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checker #' @family whole_number_checkers #' #' @seealso [is.integer()] #' @seealso [vld_true()] #' @seealso [vld_number()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_whole_number #' chk_whole_number(2) #' try(chk_whole_number(1.1)) #' @export chk_whole_number <- function(x, x_name = NULL) { if (vld_whole_number(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk( x_name, " must be a whole number (non-missing integer scalar or double equivalent)", x = x ) } #' @describeIn chk_whole_number Validate Whole Number #' #' @examples #' # vld_whole_number #' vld_whole_number(2) #' @export vld_whole_number <- function(x) { vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x)))) } chk/R/chk-lt.R0000644000176200001440000000216214743771477012553 0ustar liggesusers#' Check Less Than #' #' @description #' Checks if all non-missing values are less than value using #' #' `all(x[!is.na(x)] < value)` #' #' @inheritParams params #' @inherit params return #' #' @family range_checkers #' #' @seealso [all()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_lt #' chk_lt(-0.1) #' try(chk_lt(c(-0.1, 0.2))) #' @export chk_lt <- function(x, value = 0, x_name = NULL) { if (vld_lt(x, value)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk(x_name, " must be less than ", cc(value), ", not ", cc(x), x = x, value = value) } abort_chk(x_name, " must have values less than ", cc(value), x = x, value = value) } #' @describeIn chk_lt Validate Less Than #' #' @examples #' # vld_lt #' vld_lt(numeric(0)) #' vld_lt(0) #' vld_lt(-0.1) #' vld_lt(c(-0.1, -0.2, NA)) #' vld_lt(c(-0.1, 0.2)) #' vld_lt(c(-0.1, 0.2), value = 1) #' vld_lt("a", value = "b") #' @export vld_lt <- function(x, value = 0) all(x[!is.na(x)] < value) chk/R/chk-is.R0000644000176200001440000000156614743771477012556 0ustar liggesusers#' Check Class #' #' @description #' Checks inherits from class using #' #' `inherits(x, class)` #' #' @inheritParams params #' @inherit params return #' #' @family id_checkers #' #' @seealso [inherits()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' chk_is(1, "numeric") #' try(chk_is(1L, "double")) #' @export chk_is <- function(x, class, x_name = NULL) { if (vld_is(x, class)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) .class <- class abort_chk(x_name, " must inherit from class '", .class, "'", x = x, .class = .class) } #' @describeIn chk_is Validate Inherits from Class #' #' @examples #' #' # vld_is #' vld_is(numeric(0), "numeric") #' vld_is(1L, "double") #' @export vld_is <- function(x, class) { inherits(x, class) } chk/R/chk-null.R0000644000176200001440000000134414743771477013107 0ustar liggesusers#' Check NULL #' #' @description #' Checks if NULL using #' #' `is.null(x)` #' #' @inheritParams params #' @inherit params return #' #' @family null_checkers #' #' @seealso [is.null()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_null #' try(chk_null(1)) #' chk_null(NULL) #' @export chk_null <- function(x, x_name = NULL) { if (vld_null(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be NULL", x = x) } #' @describeIn chk_null Validate NULL #' #' @examples #' # vld_null #' vld_null(NULL) #' vld_null(1) #' @export vld_null <- function(x) is.null(x) chk/R/chk-datetime.R0000644000176200001440000000357714743771477013743 0ustar liggesusers#' Check Date Time #' #' @description #' Checks if non-missing POSIXct scalar using #' #' `inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x)` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checkers #' @family datetime_checkers #' #' @seealso [inherits()], [length()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_date_time #' chk_date_time(as.POSIXct("2001-01-02")) #' try(chk_date_time(1)) #' @export chk_date_time <- function(x, x_name = NULL) { if (vld_date_time(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a date time (non-missing POSIXct scalar)", x = x) } #' @describeIn chk_date_time Check Date Time (Deprecated) #' #' `r lifecycle::badge("deprecated")` #' #' @export chk_datetime <- function(x, x_name = NULL) { deprecate_warn("0.4.1", what = "chk::chk_datetime()", with = "chk::chk_date_time()", id = "chk_datetime" ) if (vld_date_time(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a date time (non-missing POSIXct scalar)", x = x) } #' @describeIn chk_date_time Validate Date Time #' #' @examples #' # vld_date_time #' vld_date_time(as.POSIXct("2001-01-02")) #' vld_date_time(Sys.time()) #' vld_date_time(1) #' vld_date_time("2001-01-02") #' vld_date_time(c(Sys.time(), Sys.time())) #' @export vld_date_time <- function(x) { inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x) } #' @describeIn chk_date_time Validate Date Time (Deprecated) #' #' `r lifecycle::badge("deprecated")` #' #' @export vld_datetime <- function(x) { deprecate_warn("0.4.1", what = "chk::vld_datetime()", with = "chk::vld_date_time()", id = "chk_datetime" ) vld_date_time(x) } chk/R/chk-vector.R0000644000176200001440000000207314743771477013437 0ustar liggesusers#' Check Vector #' #' @description #' Checks if is a vector using #' #' `(is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x)` #' #' @details #' `is.vector(x)` is not reliable because it returns TRUE only #' if the object is a vector with no attributes apart from names. #' #' @inheritParams params #' @inherit params return #' #' @family data_structure_checkers #' #' @seealso [is.atomic()], [is.matrix()], [is.array()], [is.list()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_vector #' chk_vector(1) #' chk_vector(list()) #' try(chk_vector(matrix(1))) #' @export chk_vector <- function(x, x_name = NULL) { if (vld_vector(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a vector", x = x) } #' @describeIn chk_vector Validate Vector #' #' @examples #' # vld_vector #' vld_vector(1) #' @export vld_vector <- function(x) (is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x) chk/R/chk-character.R0000644000176200001440000000172014743771477014067 0ustar liggesusers#' Check Character #' #' @description #' Checks if character using #' #' `is.character(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.character()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_character #' chk_character("1") #' try(chk_character(1)) #' @export chk_character <- function(x, x_name = NULL) { if (vld_character(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be character", x = x) } #' @describeIn chk_character Validate Character #' #' @examples #' # vld_character #' vld_character("1") #' vld_character(matrix("a")) #' vld_character(character(0)) #' vld_character(NA_character_) #' vld_character(1) #' vld_character(TRUE) #' vld_character(factor("text")) #' @export vld_character <- function(x) is.character(x) chk/R/chk-missing.R0000644000176200001440000000171514743771477013610 0ustar liggesusers#' Check Missing Argument #' #' @description #' Checks argument missing using #' #' `missing(x)` #' #' @details #' Currently only checks if value is available #' (as opposed to whether it was specified). #' #' @inheritParams params #' @inherit params return #' #' @family missing_checkers #' #' @seealso [missing()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_missing #' fun <- function(x) { #' chk_missing(x) #' } #' fun() #' try(fun(1)) #' @export chk_missing <- function(x, x_name = NULL) { if (vld_missing(x)) { return(invisible(NULL)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be missing") } #' @describeIn chk_missing Validate Missing Argument #' #' @examples #' # vld_missing #' fun <- function(x) { #' vld_missing(x) #' } #' fun() #' fun(1) #' @export vld_missing <- function(x) { missing(x) } chk/R/chk-matrix.R0000644000176200001440000000144614743771477013444 0ustar liggesusers#' Check Matrix #' #' @description #' Checks if is a matrix using #' #' `is.matrix(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_structure_checkers #' #' @seealso [is.matrix()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_matrix #' chk_matrix(matrix(1)) #' try(chk_matrix(array(1))) #' @export chk_matrix <- function(x, x_name = NULL) { if (vld_matrix(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be an matrix", x = x) } #' @describeIn chk_matrix Validate Matrix #' #' @examples #' # vld_matrix #' vld_matrix(1) #' vld_matrix(matrix(1)) #' @export vld_matrix <- function(x) is.matrix(x) chk/R/chk-setequal.R0000644000176200001440000000165014743771477013760 0ustar liggesusers#' Check Set Equal #' #' @description #' Checks if equal set using #' #' `setequal(x, values)` #' #' @inheritParams params #' @inherit params return #' #' @family set_checkers #' #' @seealso [setequal()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_setequal #' chk_setequal(1:2, 2:1) #' try(chk_setequal(1, 1:2)) #' @export chk_setequal <- function(x, values, x_name = NULL) { if (vld_setequal(x, values)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must equal set: ", cc(values), x = x, values = values) } #' @describeIn chk_setequal Validate Set Equal #' #' @examples #' # vld_setequal #' vld_setequal(1, 1) #' vld_setequal(1:2, 2:1) #' vld_setequal(1, 2:1) #' vld_setequal(1:2, 2) #' @export vld_setequal <- function(x, values) setequal(x, values) chk/R/expect-chk-error.R0000644000176200001440000000125714436206156014541 0ustar liggesusers#' Expect Chk Error #' #' [expect_chk_error()] checks that code throws an error #' of class `"chk_error"` with a message that matches regexp. #' See below for more details. #' #' @inherit testthat::expect_error #' @param class Must be NULL. #' @export #' #' @examples #' expect_chk_error(chk_true(FALSE)) #' try(expect_chk_error(chk_false(FALSE))) expect_chk_error <- function(object, regexp = NULL, ..., info = NULL, label = NULL, class = NULL) { if (!is_installed("testthat")) { stop("`testhat` must be installed.") } if (!is.null(class)) stop("`class` must be NULL.") testthat::expect_error(object, regexp = regexp, class = "chk_error", ..., info = info, label = label) } chk/R/chk-character-or-factor.R0000644000176200001440000000240114743771477015756 0ustar liggesusers#' Check Character or Factor #' #' @description #' Checks if character or factor using #' #' `is.character(x) || is.factor(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' @family factor_checkers #' #' @seealso [is.character()] #' @seealso [is.factor()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_character_or_factor #' chk_character_or_factor("1") #' chk_character_or_factor(factor("1")) #' try(chk_character(1)) #' @export chk_character_or_factor <- function(x, x_name = NULL) { if (vld_character_or_factor(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be character or factor", x = x) } #' @describeIn chk_character_or_factor Validate Character or Factor #' #' @examples #' # vld_character_or_factor #' vld_character_or_factor("1") #' vld_character_or_factor(matrix("a")) #' vld_character_or_factor(character(0)) #' vld_character_or_factor(NA_character_) #' vld_character_or_factor(1) #' vld_character_or_factor(TRUE) #' vld_character_or_factor(factor("text")) #' @export vld_character_or_factor <- function(x) is.character(x) || is.factor(x) chk/R/chk-whole-numeric.R0000644000176200001440000000242514743771477014714 0ustar liggesusers#' Check Whole Numeric #' #' @description #' Checks if integer vector or double equivalent using #' #' `is.integer(x) || (is.double(x) && vld_true(all.equal(x, as.integer(x))))` #' #' @inheritParams params #' @inherit params return #' #' @family whole_number_checkers #' #' @seealso [is.integer()] #' @seealso [is.double()] #' @seealso [vld_true()] #' @seealso [all.equal()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_whole_numeric #' chk_whole_numeric(1) #' try(chk_whole_numeric(1.1)) #' @export chk_whole_numeric <- function(x, x_name = NULL) { if (vld_whole_numeric(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk( x_name, " must be a whole numeric vector (integer vector or double equivalent)", x = x ) } #' @describeIn chk_whole_numeric Validate Whole Numeric #' #' @examples #' # vld_whole_numeric #' vld_whole_numeric(1) #' vld_whole_numeric(NA_real_) #' vld_whole_numeric(1:2) #' vld_whole_numeric(double(0)) #' vld_whole_numeric(TRUE) #' vld_whole_numeric(1.5) #' @export vld_whole_numeric <- function(x) { is.integer(x) || (is.double(x) && vld_true(all.equal(x[!is.na(x)], trunc(x[!is.na(x)])))) } chk/R/chk-data.R0000644000176200001440000000173014743771477013045 0ustar liggesusers#' Check Data #' #' @description #' Checks data.frame using #' #' `inherits(x, "data.frame")` #' #' Note that there is a similar function, [check_data()], which checks #' the column names, values, number of rows, and keys of a data.frame. #' #' @inheritParams params #' @inherit params return #' #' @family id_checkers #' #' @seealso [inherits()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_data #' chk_data(data.frame(x = 1)) #' try(chk_data(1)) #' @export chk_data <- function(x, x_name = NULL) { if (vld_data(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a data.frame", x = x) } #' @describeIn chk_data Validate Data #' #' @examples #' # vld_data #' vld_data(data.frame()) #' vld_data(data.frame(x = 1)) #' vld_data(c(x = 1)) #' @export vld_data <- function(x) inherits(x, "data.frame") chk/R/chk-gt.R0000644000176200001440000000217314743771477012550 0ustar liggesusers#' Check Greater Than #' #' @description #' Checks if all non-missing values are greater than value using #' #' `all(x[!is.na(x)] > value)` #' #' @inheritParams params #' @inherit params return #' #' @family range_checkers #' #' @seealso [all()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_gt #' chk_gt(0.1) #' try(chk_gt(c(0.1, -0.2))) #' @export chk_gt <- function(x, value = 0, x_name = NULL) { if (vld_gt(x, value)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk(x_name, " must be greater than ", cc(value), ", not ", cc(x), x = x, value = value) } abort_chk(x_name, " must have values greater than ", cc(value), x = x, value = value) } #' @describeIn chk_gt Validate Greater Than #' #' @examples #' # vld_gt #' vld_gt(numeric(0)) #' vld_gt(0) #' vld_gt(0.1) #' vld_gt(c(0.1, 0.2, NA)) #' vld_gt(c(0.1, -0.2)) #' vld_gt(c(-0.1, 0.2), value = -1) #' vld_gt("b", value = "a") #' @export vld_gt <- function(x, value = 0) all(x[!is.na(x)] > value) chk/R/chk-list.R0000644000176200001440000000146614743771477013115 0ustar liggesusers#' Check List #' #' @description #' Checks if is a list using #' #' `is.list(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_structure_checkers #' #' @seealso [is.list()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_list #' chk_list(list()) #' try(chk_list(1)) #' @export chk_list <- function(x, x_name = NULL) { if (vld_list(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a list", x = x) } #' @describeIn chk_list Validate List #' #' @examples #' # vld_list #' vld_list(list()) #' vld_list(list(x = 1)) #' vld_list(mtcars) #' vld_list(1) #' vld_list(NULL) #' @export vld_list <- function(x) is.list(x) chk/R/chk-unique.R0000644000176200001440000000216114743771477013441 0ustar liggesusers#' Check Unique #' #' @description #' Checks if unique using #' #' `!anyDuplicated(x, incomparables = incomparables)` #' #' @inheritParams params #' @inherit params return #' #' @family misc_checkers #' #' @seealso [anyDuplicated()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_unique #' chk_unique(c(NA, 2)) #' try(chk_unique(c(NA, NA, 2))) #' chk_unique(c(NA, NA, 2), incomparables = NA) #' @export chk_unique <- function(x, incomparables = FALSE, x_name = NULL) { if (vld_unique(x, incomparables = incomparables)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be unique", x = x, incomparables = incomparables) } #' @describeIn chk_unique Validate Unique #' #' @examples #' # vld_unique #' vld_unique(NULL) #' vld_unique(numeric(0)) #' vld_unique(c(NA, 2)) #' vld_unique(c(NA, NA, 2)) #' vld_unique(c(NA, NA, 2), incomparables = NA) #' @export vld_unique <- function(x, incomparables = FALSE) { !.anyDuplicated(x, incomparables = incomparables) } chk/R/check-names.R0000644000176200001440000000325314436206156013533 0ustar liggesusers#' Check Names #' #' @description #' Checks the names of an object. #' #' @inheritParams params #' @param names A character vector of the required names. #' @param exclusive A flag specifying whether x must only contain the required names. #' @param order A flag specifying whether the order of the required names in x must match the order in names. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' x <- c(x = 1, y = 2) #' check_names(x, c("y", "x")) #' try(check_names(x, c("y", "x"), order = TRUE)) #' try(check_names(x, "x", exclusive = TRUE)) #' @export check_names <- function(x, names = character(0), exclusive = FALSE, order = FALSE, x_name = NULL) { chk_s3_class(names, "character") chk_unique(names) chk_not_any_na(names) chk_flag(exclusive) chk_flag(order) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) chk_named(x, x_name = x_name) x_names <- names(x) if (!length(names)) { if (exclusive && length(x_names)) { abort_chk(x_name, " must not have any elements") } return(invisible(x)) } x_name <- backtick_chk(p0("names(", unbacktick_chk(x_name), ")")) if (length(setdiff(names, x_names))) { abort_chk(x_name, " must include ", cc(setdiff(names, x_names), conj = " and ")) } if (exclusive && length(setdiff(x_names, names))) { abort_chk(x_name, " must not include ", cc(setdiff(x_names, names), conj = " or ")) } if (order && !identical(intersect(names, x_names), intersect(x_names, names))) { abort_chk(x_name, " must include ", cc(names, conj = " and "), " in that order") } invisible(x) } chk/R/chk-raw.R0000644000176200001440000000140514743771477012724 0ustar liggesusers#' Check Raw #' #' @description #' Checks if raw using #' #' `is.raw(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.raw()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_raw #' chk_raw(as.raw(1)) #' try(chk_raw(1)) #' @export chk_raw <- function(x, x_name = NULL) { if (vld_raw(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be raw", x = x) } #' @describeIn chk_raw Validate Raw #' #' @examples #' # vld_raw #' vld_raw(as.raw(1)) #' vld_raw(raw(0)) #' vld_raw(1) #' vld_raw(TRUE) #' @export vld_raw <- function(x) is.raw(x) chk/R/chk-double.R0000644000176200001440000000162514743771477013411 0ustar liggesusers#' Check Double #' #' @description #' Checks if double using #' #' `is.double(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.double()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_double #' chk_double(1) #' try(chk_double(1L)) #' @export chk_double <- function(x, x_name = NULL) { if (vld_double(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be double", x = x) } #' @describeIn chk_double Validate Double #' #' @examples #' # vld_double #' vld_double(1) #' vld_double(matrix(c(1, 2, 3, 4), nrow = 2L)) #' vld_double(double(0)) #' vld_double(numeric(0)) #' vld_double(NA_real_) #' vld_double(1L) #' vld_double(TRUE) #' @export vld_double <- function(x) is.double(x) chk/R/chk-unused.R0000644000176200001440000000157414743771477013445 0ustar liggesusers#' Check ... Unused #' #' @description #' Checks if ... is unused #' #' `length(list(...)) == 0L` #' #' @inheritParams params #' @inherit params return #' @return The `chk_` function throws an informative error if the test fails. #' #' @family ellipsis_checkers #' #' @seealso [length()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_unused #' fun <- function(x, ...) { #' chk_unused(...) #' x #' } #' fun(1) #' try(fun(1, 2)) #' @export chk_unused <- function(...) { if (!length(list(...))) { return(invisible()) } abort_chk("`...` must be unused") } #' @describeIn chk_unused Validate ... Unused #' #' @examples #' # vld_unused #' fun <- function(x, ...) { #' vld_unused(...) #' } #' fun(1) #' try(fun(1, 2)) #' @export vld_unused <- function(...) length(list(...)) == 0L chk/R/chk-not-subset.R0000644000176200001440000000226714743771477014245 0ustar liggesusers#' Check Not Subset #' #' @description #' Checks if not all values in values using #' #' `!any(x %in% values) || !length(x)` #' #' @inheritParams params #' @inherit params return #' #' @family set_checkers #' #' @seealso [any()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_not_subset #' chk_not_subset(11, 1:10) #' try(chk_not_subset(1, 1:10)) #' @export chk_not_subset <- function(x, values, x_name = NULL) { if (vld_not_subset(x, values)) { return(invisible(x)) } values <- sort(unique(values), na.last = TRUE) if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk(x_name, " must not match ", cc(unique(c(x, values)), " or "), x = x, values = values) } abort_chk(x_name, " must not have any values matching ", cc(values, " or "), x = x, values = values) } #' @describeIn chk_subset Validate Not Subset #' #' @examples #' # vld_not_subset #' vld_not_subset(numeric(0), 1:10) #' vld_not_subset(1, 1:10) #' vld_not_subset(11, 1:10) #' @export vld_not_subset <- function(x, values) !any(x %in% values) || !length(x) chk/R/chk-all-equivalent.R0000644000176200001440000000250214743771477015055 0ustar liggesusers#' Check All Equivalent #' #' @description #' Checks all elements in x equivalent using #' #' `length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance))` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' @family all_checkers #' #' @seealso [length()] #' @seealso [vld_equivalent()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_all_equivalent #' chk_all_equivalent(c(1, 1.00000001)) #' try(chk_all_equivalent(c(1, 1.0000001))) #' chk_all_equivalent(list(c(x = 1), c(x = 1))) #' chk_all_equivalent(list(c(x = 1), c(y = 1))) #' @export chk_all_equivalent <- function(x, tolerance = sqrt(.Machine$double.eps), x_name = NULL) { if (vld_all_equivalent(x, tolerance = tolerance)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must have equivalent elements", x = x, tolerance = tolerance) } #' @describeIn chk_all_equivalent Validate All Equivalent #' #' @examples #' # vld_all_equivalent #' vld_all_equivalent(c(x = 1, y = 1)) #' @export vld_all_equivalent <- function(x, tolerance = sqrt(.Machine$double.eps)) { length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance)) } chk/R/chk-date.R0000644000176200001440000000167214743771477013056 0ustar liggesusers#' Check Date #' #' @description #' Checks non-missing Date scalar using #' #' `inherits(x, "Date") && length(x) == 1L && !anyNA(x)` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checkers #' @family datetime_checkers #' #' @seealso [inherits()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_date #' chk_date(Sys.Date()) #' try(chk_date(1)) #' @export chk_date <- function(x, x_name = NULL) { if (vld_date(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a date (non-missing Date scalar)", x = x) } #' @describeIn chk_date Validate Date #' #' @examples #' # vld_date #' vld_date(Sys.Date()) #' vld_date(Sys.time()) #' vld_date(1) #' @export vld_date <- function(x) inherits(x, "Date") && length(x) == 1L && !anyNA(x) chk/R/chk-all-identical.R0000644000176200001440000000216014743771477014634 0ustar liggesusers#' Check All Identical #' #' @description #' Checks all elements in x identical using #' #' `length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]]))` #' #' #' **Pass**: `c(1, 1, 1)`, `list(1, 1)` #' #' **Fail**: `c(1, 1.0000001)`, `list(1, NA)` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' @family all_checkers #' #' @seealso [length()] #' @seealso [vld_identical()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_all_identical #' chk_all_identical(c(1, 1)) #' try(chk_all_identical(c(1, 1.1))) #' @export chk_all_identical <- function(x, x_name = NULL) { if (vld_all_identical(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must have identical elements", x = x) } #' @describeIn chk_all_identical Validate All Identical #' #' @examples #' # vld_all_identical #' vld_all_identical(c(1, 1)) #' @export vld_all_identical <- function(x) { length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]])) } chk/R/chk-all.R0000644000176200001440000000227614743771477012712 0ustar liggesusers#' Check All #' #' @description #' Checks all elements using #' #' `all(vapply(x, chk_fun, TRUE, ...))` #' #' @inheritParams params #' @inherit params return #' #' @family all_checkers #' #' @seealso [all()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_all #' chk_all(TRUE, chk_lgl) #' # FIXME try(chk_all(1, chk_lgl)) #' chk_all(c(TRUE, NA), chk_lgl) #' @export chk_all <- function(x, chk_fun, ..., x_name = NULL) { if (is.null(x)) { if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) return(chk_fun(x, ..., x_name = x_name)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) x_name <- paste0("all elements of ", x_name) args <- list(...) args$X <- x args$FUN <- chk_fun args$x_name <- x_name do.call("lapply", args) invisible(x) } #' @describeIn chk_all Validate All #' #' @examples #' # vld_all #' vld_all(c(TRUE, NA), vld_lgl) #' @export vld_all <- function(x, vld_fun, ...) { if (is.null(x)) { return(vld_fun(x, ...)) } args <- list(...) args$X <- x args$FUN <- vld_fun args$FUN.VALUE <- TRUE all(do.call("vapply", args)) } chk/R/chk-subset.R0000644000176200001440000000227214743771477013443 0ustar liggesusers#' Check Subset #' #' @description #' Checks if all values in values using #' #' `all(x %in% values)` #' #' Pay attention to the order of the arguments `value` and `x` #' in this function compared to [chk_superset()] #' #' #' @inheritParams params #' @inherit params return #' #' @family set_checkers #' #' @seealso [all()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_subset #' chk_subset(1, 1:10) #' try(chk_subset(11, 1:10)) #' @export chk_subset <- function(x, values, x_name = NULL) { if (vld_subset(x, values)) { return(invisible(x)) } values <- sort(unique(values), na.last = TRUE) if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk(x_name, " must match ", cc(values, " or "), ", not ", cc(x), x = x, values = values) } abort_chk(x_name, " must have values matching ", cc(values, " or "), x = x, values = values) } #' @describeIn chk_subset Validate Subset #' #' @examples #' # vld_subset #' vld_subset(numeric(0), 1:10) #' vld_subset(1, 1:10) #' vld_subset(11, 1:10) #' @export vld_subset <- function(x, values) all(x %in% values) chk/R/chk-number.R0000644000176200001440000000176114743771477013430 0ustar liggesusers#' Check Number #' #' @description #' Checks if non-missing numeric scalar using #' #' `is.numeric(x) && length(x) == 1L && !anyNA(x)` #' #' **Pass**: `1`, `2L`, `log(10)`, `-Inf` #' #' **Fail**: `"a"`, `1:3`, `NA_real_` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers scalar_checkers #' #' @seealso [is.numeric()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_number #' chk_number(1.1) #' try(chk_number(TRUE)) #' @export chk_number <- function(x, x_name = NULL) { if (vld_number(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a number (non-missing numeric scalar)", x = x) } #' @describeIn chk_number Validate Number #' #' @examples #' # vld_number #' vld_number(1.1) #' @export vld_number <- function(x) { is.numeric(x) && length(x) == 1L && !anyNA(x) } chk/R/cc.R0000644000176200001440000000276314436206156011747 0ustar liggesusers#' Concatenate with Commas #' #' Concatenates object values into a string with each value separated by a comma #' and the last value separated by a conjunction. #' #' By default, if x has more than 10 values an ellipsis is used #' to ensure only 10 values are displayed (including the ellipsis). #' #' @param x The object to concatenate. #' @param conj A string of the conjunction to separate the last value by. #' @param sep A string of the separator. #' @param brac A string to brac the values by. #' @param ellipsis A numeric scalar of the maximum number of values to display #' before using an ellipsis. #' @param chk A flag specifying whether to check the other parameters. #' #' @return A string. #' @export #' #' @examples #' cc(1:2) #' cc(1:2, conj = " or") #' cc(3:1, brac = "'") #' cc(1:11) #' cc(as.character(1:2)) cc <- function(x, conj = ", ", sep = ", ", brac = if (is.character(x) || is.factor(x)) "'" else "", ellipsis = 10L, chk = TRUE) { if (chk) { chk_string(conj) chk_string(sep) chk_s3_class(brac, "character") chk_range(length(brac), 1:2) chk_whole_number(ellipsis) chk_gte(ellipsis, 3) } if (!length(x)) { return(character(0)) } x <- p0(brac[1], x, brac[length(brac)]) n <- length(x) if (n == 1L) { return(x) } if (n == 2L) { return(p(x, collapse = conj)) } if (n > ellipsis) { x <- c(x[1:(ellipsis - 2)], "...", x[n]) n <- ellipsis } p(c(p0(x[1:(n - 1)], collapse = sep), x[n]), collapse = conj) } chk/R/chk-numeric.R0000644000176200001440000000175214743771477013602 0ustar liggesusers#' Check Numeric #' #' @description #' Checks if numeric using #' #' `is.numeric(x)` #' #' **Pass**: `1`, `1:2`, `NA_real_`, `integer(0)`, `matrix(1:3)`. #' #' **Fail**: `TRUE`, `"1"`, `NA`, `NULL`. #' #' @inheritParams chk_flag #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.numeric()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_numeric #' chk_numeric(1) #' try(chk_numeric("1")) #' @export chk_numeric <- function(x, x_name = NULL) { if (vld_numeric(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be numeric", x = x) } #' @describeIn chk_numeric Validate Numeric #' #' @examples #' # vld_numeric #' vld_numeric(1) #' vld_numeric(1:2) #' vld_numeric(NA_real_) #' vld_numeric(integer(0)) #' vld_numeric("1") #' vld_numeric(TRUE) #' @export vld_numeric <- function(x) is.numeric(x) chk/R/chk-atomic.R0000644000176200001440000000154014743771477013407 0ustar liggesusers#' Check Atomic #' #' @description #' Checks if atomic using #' #' `is.atomic(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_structure_checkers #' #' @seealso [is.atomic()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_atomic #' chk_atomic(1) #' try(chk_atomic(list(1))) #' @export chk_atomic <- function(x, x_name = NULL) { if (vld_atomic(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be atomic", x = x) } #' @describeIn chk_atomic Validate Atomic #' #' @examples #' # vld_atomic #' vld_atomic(1) #' vld_atomic(matrix(1:3)) #' vld_atomic(character(0)) #' vld_atomic(list(1)) #' vld_atomic(NULL) #' @export vld_atomic <- function(x) is.atomic(x) chk/R/chk-flag.R0000644000176200001440000000215414743771477013046 0ustar liggesusers#' Check Flag #' #' @description #' Checks if non-missing logical scalar using #' #' `is.logical(x) && length(x) == 1L && !anyNA(x)` #' #' **Pass**: `TRUE`, `FALSE`. #' #' **Fail**: `logical(0)`, `c(TRUE, TRUE)`, `"TRUE"`, `1`, `NA`. #' #' Do not confuse this function with [chk_lgl()], #' which also checks for logical scalars of `length(x) == 1` #' but can include `NA`s. #' #' @inheritParams params #' @inherit params return #' #' @family logical_checkers #' @family scalar_checkers #' #' @seealso [is.logical()] [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_flag #' chk_flag(TRUE) #' try(vld_flag(1)) #' @export chk_flag <- function(x, x_name = NULL) { if (vld_flag(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a flag (TRUE or FALSE)", x = x) } #' @describeIn chk_flag Validate Flag #' #' @examples #' # vld_flag #' vld_flag(TRUE) #' vld_flag(1) #' @export vld_flag <- function(x) is.logical(x) && length(x) == 1L && !anyNA(x) chk/R/chk-valid-name.R0000644000176200001440000000166614743771477014161 0ustar liggesusers#' Check Valid Name #' #' @description #' Checks if valid name using #' #' `identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)]))` #' #' @inheritParams params #' @inherit params return #' #' @family name_checkers #' #' @seealso [identical()] #' @seealso [make.names()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_valid_name #' chk_valid_name("text") #' try(chk_valid_name(".1")) #' @export chk_valid_name <- function(x, x_name = NULL) { if (vld_valid_name(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be valid name%s", n = length(x)) } #' @describeIn chk_valid_name Validate Valid Name #' #' @examples #' # vld_valid_name #' vld_valid_name(".1") #' @export vld_valid_name <- function(x) identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)])) chk/R/check-files.R0000644000176200001440000000215314436206156013530 0ustar liggesusers#' Check Files Exist #' #' @description #' Checks if all files exist (or if exists = FALSE do not exist as files or directories). #' #' @inheritParams params #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' check_files(tempfile("unlikely-that-exists-chk"), exists = FALSE) #' try(check_files(tempfile("unlikely-that-exists-chk"))) #' @export check_files <- function(x, exists = TRUE, x_name = NULL) { if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) chk_character(x, x_name = x_name) chk_vector(x, x_name = x_name) chk_not_any_na(x, x_name = x_name) chk_flag(exists) dirs <- vapply(x, vld_dir, TRUE) if (any(dirs)) { abort_chk(x_name, " must specify files ('", x[dirs][1], "' is a directory)", x = x) } x <- x[vapply(x, vld_file, TRUE) != exists] if (!length(x)) { return(invisible(x)) } x <- x[1] if (exists) { abort_chk(x_name, " must specify existing files ('", x, "' can't be found)", x = x) } abort_chk(x_name, " must not specify existing files ('", x, "' exists)", x = x) } chk/R/utils.R0000644000176200001440000000254714743771477012540 0ustar liggesusers#' Abort Check #' #' A wrapper on [err()] that sets the subclass to be `'chk_error'`. #' #' It is exported to allow users to easily construct their own `chk_` functions. #' #' @inheritParams message_chk #' @inheritParams rlang::abort #' @return Throws an error of class `'chk_error'`. #' @seealso [err()] #' @export #' #' @examples #' try(abort_chk("x must be NULL")) #' try(abort_chk("`x` must be NULL")) #' try(abort_chk("there %r %n problem value%s", n = 1)) #' try(abort_chk("there %r %n problem value%s", n = 1.5)) abort_chk <- function(..., n = NULL, tidy = TRUE, call = rlang::caller_call(2)) { err(..., n = n, tidy = tidy, class = "chk_error", call = call) } #' Deparse Backtick #' #' `deparse_backtick_chk` is a wrapper on [deparse()] #' and `backtick_chk`. #' #' It is exported to allow users to easily construct their own `chk_` functions. #' #' @param x A substituted object to deparse. #' #' @return A string of the backticked substituted object. #' @seealso [deparse()] #' @export #' #' @examples #' #' # deparse_backtick_chk #' deparse_backtick_chk(2) #' deparse_backtick_chk(2^2) deparse_backtick_chk <- function(x) backtick_chk(deparse(x)) #' @describeIn deparse_backtick_chk Backtick #' @export backtick_chk <- function(x) p0("`", unbacktick_chk(x), "`") #' @describeIn deparse_backtick_chk Unbacktick #' @export unbacktick_chk <- function(x) gsub("`", "", x) chk/R/chk-array.R0000644000176200001440000000143014743771477013247 0ustar liggesusers#' Check Array #' #' @description #' Checks if is an array using #' #' `is.array(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_structure_checkers #' #' @seealso [is.array()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_array #' chk_array(array(1)) #' try(chk_array(matrix(1))) #' @export chk_array <- function(x, x_name = NULL) { if (vld_array(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be an array", x = x) } #' @describeIn chk_array Validate Array #' #' @examples #' #' # vld_array #' vld_array(1) #' vld_array(array(1)) #' @export vld_array <- function(x) is.array(x) chk/R/chk-not-missing.R0000644000176200001440000000171214743771477014403 0ustar liggesusers#' Check Not Missing Argument #' #' @description #' Checks argument not missing using #' #' `!missing(x)` #' #' @details #' Currently only checks if value is available #' (as opposed to whether it was specified). #' #' @inheritParams params #' @inherit params return #' #' @family missing_checkers #' #' @seealso [missing()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_not_missing #' fun <- function(x) { #' chk_not_missing(x) #' } #' fun(1) #' try(fun()) #' @export chk_not_missing <- function(x, x_name = "`x`") { if (vld_not_missing(x)) { return(invisible(x)) } abort_chk(x_name, " must not be missing.", tidy = FALSE) } #' @describeIn chk_not_missing Validate Not Missing Argument #' #' @examples #' # vld_not_missing #' fun <- function(x) { #' vld_not_missing(x) #' } #' fun() #' fun(1) #' @export vld_not_missing <- function(x) { !missing(x) } chk/R/chk-all-equal.R0000644000176200001440000000234414743771477014013 0ustar liggesusers#' Check All Equal #' #' @description #' Checks all elements in x equal using #' #' `length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance))` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' @family all_checkers #' @seealso [length()] #' @seealso [vld_equal()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_all_equal #' chk_all_equal(c(1, 1.00000001)) #' try(chk_all_equal(c(1, 1.0000001))) #' chk_all_equal(list(c(x = 1), c(x = 1))) #' try(chk_all_equal(list(c(x = 1), c(y = 1)))) #' @export chk_all_equal <- function(x, tolerance = sqrt(.Machine$double.eps), x_name = NULL) { if (vld_all_equal(x, tolerance = tolerance)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must have equal elements", x = x, tolerance = tolerance) } #' @describeIn chk_all_equal Validate All Equal #' #' @examples #' # vld_all_equal #' vld_all_equal(c(1, 1L)) #' @export vld_all_equal <- function(x, tolerance = sqrt(.Machine$double.eps)) { length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance)) } chk/R/chk-scalar.R0000644000176200001440000000143414743771477013402 0ustar liggesusers#' Check Scalar #' #' @description #' Checks if is a vector using #' #' `length(x) == 1L` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checkers #' #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_scalar #' chk_scalar(1) #' chk_scalar(list(1)) #' try(chk_scalar(1:2)) #' @export chk_scalar <- function(x, x_name = NULL) { if (vld_scalar(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a scalar (length 1)", x = x) } #' @describeIn chk_scalar Validate Scalar #' #' @examples #' # vld_scalar #' vld_scalar(1) #' @export vld_scalar <- function(x) length(x) == 1L chk/R/chk-match.R0000644000176200001440000000225414743771477013232 0ustar liggesusers#' Check Matches #' #' @description #' Checks if all values match regular expression using #' #' `all(grepl(regexp, x[!is.na(x)]))` #' #' @inheritParams params #' @inherit params return #' #' @family regex_checkers #' #' @seealso [all()] #' @seealso [grepl()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_match #' chk_match("1") #' try(chk_match("1", regexp = "2")) #' @export chk_match <- function(x, regexp = ".+", x_name = NULL) { if (vld_match(x, regexp)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk(x_name, " must match regular expression '", regexp, "'", x = x, regexp = regexp) } abort_chk(x_name, " must have values matching regular expression '", regexp, "'", x = x, regexp = regexp) } #' @describeIn chk_match Validate Matches #' #' @examples #' # vld_match #' vld_match("1") #' vld_match("a", regexp = "a") #' vld_match("") #' vld_match("1", regexp = "2") #' vld_match(NA_character_, regexp = ".*") #' @export vld_match <- function(x, regexp = ".+") all(grepl(regexp, x[!is.na(x)])) chk/R/chk-used.R0000644000176200001440000000153714743771477013101 0ustar liggesusers#' Check ... Used #' #' @description #' Checks if is ... used using #' #' `length(list(...)) != 0L` #' #' @inheritParams params #' @inherit params return #' @return The `chk_` function throws an informative error if the test fails. #' #' @family ellipsis_checkers #' #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_used #' fun <- function(x, ...) { #' chk_used(...) #' x #' } #' try(fun(1)) #' fun(1, 2) #' @export chk_used <- function(...) { if (vld_used(...)) { return(invisible()) } abort_chk("`...` must be used") } #' @describeIn chk_used Validate ... Used #' #' @examples #' # vld_used #' fun <- function(x, ...) { #' vld_used(...) #' } #' fun(1) #' fun(1, 2) #' @export vld_used <- function(...) length(list(...)) != 0L chk/R/chk-identical.R0000644000176200001440000000175114743771477014073 0ustar liggesusers#' Check Identical #' #' @description #' Checks if is identical to y using #' #' `identical(x, y)` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' #' @seealso [identical()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_identical #' chk_identical(1, 1) #' try(chk_identical(1, 1L)) #' chk_identical(c(1, 1), c(1, 1)) #' try(chk_identical(1, c(1, 1))) #' @export chk_identical <- function(x, y, x_name = NULL) { if (identical(x, y)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) y_name <- as_label(y) obj_of <- if (grepl("^<", y_name)) "the y object of class " else NULL abort_chk(x_name, " must be identical to ", obj_of, y_name, x = x, y = y ) } #' @describeIn chk_identical Validate Identical #' #' @examples #' vld_identical(1, 1) #' @export vld_identical <- function(x, y) identical(x, y) chk/R/chk-true.R0000644000176200001440000000164714743771477013122 0ustar liggesusers#' Check TRUE #' #' @description #' Checks if TRUE using #' #' `is.logical(x) && length(x) == 1L && !anyNA(x) && x` #' #' @inheritParams params #' @inherit params return #' #' @family logical_checkers #' @family scalar_checkers #' #' @seealso [is.logical()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_true #' chk_true(TRUE) #' try(chk_true(1)) #' @export chk_true <- function(x, x_name = NULL) { if (vld_true(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be TRUE", x = x) } #' @describeIn chk_true Validate TRUE #' #' @examples #' # vld_true #' vld_true(TRUE) #' vld_true(FALSE) #' vld_true(NA) #' vld_true(0) #' vld_true(c(TRUE, TRUE)) #' @export vld_true <- function(x) is.logical(x) && length(x) == 1L && !anyNA(x) && x chk/R/chk-null-or.R0000644000176200001440000000256714506142666013522 0ustar liggesusers#' Check NULL Or #' #' @description #' Checks if NULL or passes test. #' #' @inheritParams params #' @param chk A chk function. Soft-deprecated for vld. `r lifecycle::badge("deprecated")` #' @param vld A vld function. #' @param ... Arguments passed to chk. #' #' @return An informative error if the test fails. #' @export #' #' @examples #' chk_null_or(NULL, chk_number) #' chk_null_or(1, chk_number) #' try(chk_null_or("1", chk_number)) chk_null_or <- function(x, chk, ..., vld, x_name = NULL) { if (!missing(chk)) { lifecycle::deprecate_soft("0.6.1", "chk_null_or(chk)", "chk_null_or(vld)") } if (is.null(x)) { return(invisible(x)) } if (missing(vld)) { try <- try_chk(chk(x, ...)) if (is.null(try)) { return(invisible(x)) } if (is.null(x_name)) { x_name <- deparse_backtick_chk(substitute(x)) try <- try_chk(chk(x, ..., x_name = x_name)) } msg <- try_msg(try) msg <- sub("[.]$", " or NULL.", msg) abort_chk(msg, x = x) } if (vld(x, ...)) { return(invisible(x)) } if (is.null(x_name)) { x_name <- deparse_backtick_chk(substitute(x)) } chk <- deparse(substitute(vld)) chk <- sub("^(chk::){0,1}vld_", "chk_", chk) chk <- paste0(chk, "(x, ..., x_name = x_name)") chk <- parse(text = chk) try <- try_chk(eval(chk)) msg <- try_msg(try) msg <- sub("[.]$", " or NULL.", msg) abort_chk(msg, x = x) } chk/R/chk-ext.R0000644000176200001440000000214514743771477012735 0ustar liggesusers#' Check File Extension #' #' @description #' Checks extension using #' #' `vld_string(x) && vld_subset(tools::file_ext(x), ext)` #' #' The user may want to use [toupper()] or [tolower()] #' to ensure the case matches. #' #' @inheritParams params #' @inherit params return #' #' @family file_checkers #' #' @seealso [vld_string()] #' @seealso [vld_subset()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_ext #' try(chk_ext("file1.pdf", "png")) #' @export chk_ext <- function(x, ext, x_name = NULL) { if (vld_ext(x, ext)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_string(x, x_name = x_name) abort_chk( x_name, " must have extension ", cc(ext, " or "), " (not '", tools::file_ext(x), "')", x = x, ext = ext ) } #' @describeIn chk_ext Validate File Extension #' #' @examples #' # vld_ext #' vld_ext("oeu.pdf", "pdf") #' vld_ext(toupper("oeu.pdf"), "PDF") #' @export vld_ext <- function(x, ext) vld_string(x) && vld_subset(tools::file_ext(x), ext) chk/R/check-length.R0000644000176200001440000000114414744734003013705 0ustar liggesusers#' Check Length #' #' @description #' Checks length of an object. #' #' @inheritParams params #' @param values A flag or a whole numeric vector of the value, value range or possible values. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' check_length(1) #' try(check_length(1, values = FALSE)) #' try(check_length(1, values = c(10, 2))) #' @export check_length <- function(x, values = numeric(0), x_name = NULL) { if (is.null(x_name)) x_name <- deparse((substitute(x))) check_dim(x, values = values, x_name = x_name, dim_name = "length") } chk/R/chk-equivalent.R0000644000176200001440000000245314743771477014314 0ustar liggesusers#' Check Equivalent #' #' @description #' Checks if is equivalent (equal ignoring attributes) to y using #' #' `vld_true(all.equal(x, y, tolerance, check.attributes = FALSE))` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' #' @seealso [vld_true()] #' @seealso [all.equal()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_equivalent #' chk_equivalent(1, 1.00000001) #' try(chk_equivalent(1, 1.0000001)) #' chk_equivalent(1, 1L) #' chk_equivalent(c(x = 1), c(y = 1)) #' @export chk_equivalent <- function(x, y, tolerance = sqrt(.Machine$double.eps), x_name = NULL) { if (vld_equivalent(x, y, tolerance = tolerance)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) y_name <- as_label(y) obj_of <- if (grepl("^<", y_name)) "the y object of class " else NULL abort_chk(x_name, " must be equivalent to ", obj_of, y_name, x = x, y = y ) } #' @describeIn chk_equivalent Validate Equivalent #' #' @examples #' vld_equivalent(c(x = 1), c(y = 1L)) #' @export vld_equivalent <- function(x, y, tolerance = sqrt(.Machine$double.eps)) { vld_true(all.equal(x, y, tolerance, check.attributes = FALSE)) } chk/R/chk-dir.R0000644000176200001440000000205114743771477012707 0ustar liggesusers#' Check Directory Exists #' #' @description #' Checks if directory exists using #' #' `vld_string(x) && dir.exists(x)` #' #' @inheritParams params #' @inherit params return #' #' @family file_checkers #' #' @seealso [vld_string()] #' @seealso [dir.exists()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_dir #' chk_dir(tempdir()) #' try(chk_dir(tempfile())) #' @export chk_dir <- function(x, x_name = NULL) { if (vld_dir(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_string(x, x_name = x_name) if (file.exists(x)) { abort_chk(x_name, " must specify a directory ('", x, "' is a file)", x = x) } abort_chk(x_name, " must specify an existing directory ('", x, "' can't be found)", x = x) } #' @describeIn chk_dir Validate Directory Exists #' #' @examples #' # vld_dir #' vld_dir(1) #' vld_dir(tempdir()) #' vld_dir(tempfile()) #' @export vld_dir <- function(x) vld_string(x) && dir.exists(x) chk/R/chk-environment.R0000644000176200001440000000165714743771477014510 0ustar liggesusers#' Check Environment #' #' @description #' Checks if environment using #' #' `is.environment(x)` #' #' @inheritParams params #' @inherit params return #' #' @family data_type_checkers #' #' @seealso [is.environment()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_environment #' chk_environment(.GlobalEnv) #' try(chk_environment(1)) #' @export chk_environment <- function(x, x_name = NULL) { if (vld_environment(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be an environment", x = x) } #' @describeIn chk_environment Validate Environment #' #' @examples #' # vld_environment #' vld_environment(1) #' vld_environment(list(1)) #' vld_environment(.GlobalEnv) #' vld_environment(environment()) #' @export vld_environment <- function(x) is.environment(x) chk/R/chk-false.R0000644000176200001440000000167414743771477013235 0ustar liggesusers#' Check FALSE #' #' @description #' Check if FALSE using #' #' `is.logical(x) && length(x) == 1L && !anyNA(x) && !x` #' #' @inheritParams params #' @inherit params return #' #' @family logical_checkers #' @family scalar_checkers #' #' @seealso [is.logical()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_false #' chk_false(FALSE) #' try(chk_false(0)) #' @export chk_false <- function(x, x_name = NULL) { if (vld_false(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be FALSE", x = x) } #' @describeIn chk_false Validate FALSE #' #' @examples #' # vld_false #' vld_false(TRUE) #' vld_false(FALSE) #' vld_false(NA) #' vld_false(0) #' vld_false(c(FALSE, FALSE)) #' @export vld_false <- function(x) is.logical(x) && length(x) == 1L && !anyNA(x) && !x chk/R/chk-sorted.R0000644000176200001440000000145514743771477013440 0ustar liggesusers#' Check Sorted #' #' @description #' Checks if is sorted using #' #' `is.unsorted(x, na.rm = TRUE)` #' #' @inheritParams params #' @inherit params return #' #' @family sorted_checkers #' #' @seealso [is.unsorted()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_sorted #' chk_sorted(1:2) #' try(chk_sorted(2:1)) #' @export chk_sorted <- function(x, x_name = NULL) { if (vld_sorted(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be sorted", x = x) } #' @describeIn chk_sorted Validate Sorted #' #' @examples #' # vld_sorted #' vld_sorted(1:2) #' vld_sorted(2:1) #' @export vld_sorted <- function(x) !is.unsorted(x, na.rm = TRUE) chk/R/chk-lgl.R0000644000176200001440000000233314743771477012712 0ustar liggesusers#' Check Logical Scalar #' #' @description #' Checks if logical scalar using #' #' `is.logical(x) && length(x) == 1L` #' #' If you only want to check the data type (not whether `length(x) == 1`), #' you should use the [chk_logical()] function. #' #' @inheritParams params #' @inherit params return #' #' @family logical_checkers #' @family scalar_checkers #' #' @seealso [is.logical()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_lgl #' chk_lgl(NA) #' try(chk_lgl(1)) #' @export chk_lgl <- function(x, x_name = NULL) { if (vld_lgl(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be a logical scalar (TRUE, FALSE or NA)", x = x) } #' @describeIn chk_lgl Validate Logical Scalar #' #' @examples #' # vld_lgl #' vld_lgl(TRUE) #' vld_lgl(FALSE) #' vld_lgl(NA) #' vld_lgl(1) #' vld_lgl(c(TRUE, TRUE)) #' @export vld_lgl <- function(x) { deprecate_soft( "0.9.3", what = "chk::chk_lgl()", details = "Please use `chk::chk_scalar(x);` `chk::chk_logical(x)` instead", id = "chk_lgl" ) is.logical(x) && length(x) == 1L } chk/R/chk-not-null.R0000644000176200001440000000143614743771477013707 0ustar liggesusers#' Check not NULL #' #' @description #' Checks if not NULL using #' #' `!is.null(x)` #' #' @inheritParams params #' @inherit params return #' #' @family null_checkers #' #' @seealso [is.null()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_not_null #' try(chk_not_null(NULL)) #' chk_not_null(1) #' @export chk_not_null <- function(x, x_name = NULL) { if (vld_not_null(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must not be NULL", x = x) } #' @describeIn chk_not_null Validate Not NULL #' #' @examples #' # vld_not_null #' vld_not_null(1) #' vld_not_null(NULL) #' @export vld_not_null <- function(x) !is.null(x) chk/R/check-data.R0000644000176200001440000000261514436206156013342 0ustar liggesusers#' Check Data #' #' @description #' Checks column names, values, number of rows and key for a data.frame. #' #' @inheritParams params #' @param values A uniquely named list of atomic vectors of the column values. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @export #' @examples #' check_data(data.frame()) #' check_data(data.frame(x = 2), list(x = 1)) #' try(check_data(data.frame(x = 2), list(y = 1L))) #' try(check_data(data.frame(x = 2), list(y = 1))) #' try(check_data(data.frame(x = 2), nrow = 2)) check_data <- function(x, values = NULL, exclusive = FALSE, order = FALSE, nrow = numeric(0), key = character(0), x_name = NULL) { chk_data(x, "data.frame") if (is.null(values)) values <- structure(list(), .Names = character(0)) chk_list(values) chk_named(values) chk_unique(names(values)) chk_all(values, chk_fun = chk_atomic) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) check_dim(x, dim = base::nrow, values = nrow, x_name = x_name, dim_name = "nrow" ) check_names(x, names = names(values), exclusive = exclusive, order = order, x_name = x_name ) lapply(names(values), function(name) { check_values(x[[name]], values[[name]], x_name = backtick_chk(p0(unbacktick_chk(x_name), "$", name)) ) }) check_key(x, key = key, x_name = x_name) invisible(x) } chk/R/chk-gte.R0000644000176200001440000000223714743771477012716 0ustar liggesusers#' Check Greater Than or Equal To #' #' @description #' Checks if all non-missing values are greater than or equal to y using #' #' `all(x[!is.na(x)] >= value)` #' #' @inheritParams params #' @inherit params return #' #' @family range_checkers #' #' @seealso [all()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_gte #' chk_gte(0) #' try(chk_gte(-0.1)) #' @export chk_gte <- function(x, value = 0, x_name = NULL) { if (vld_gte(x, value)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk( x_name, " must be greater than or equal to ", cc(value), ", not ", cc(x), x = x, value = value ) } abort_chk(x_name, " must have values greater than or equal to ", cc(value), x = x, value = value) } #' @describeIn chk_gte Validate Greater Than or Equal To #' #' @examples #' # vld_gte #' vld_gte(numeric(0)) #' vld_gte(0) #' vld_gte(-0.1) #' vld_gte(c(0.1, 0.2, NA)) #' vld_gte(c(0.1, 0.2, NA), value = 1) #' @export vld_gte <- function(x, value = 0) all(x[!is.na(x)] >= value) chk/R/chkor.R0000644000176200001440000000107714436206156012465 0ustar liggesusers#' Check OR #' #' The `chkor()` function has been deprecated for the faster `chkor_vld()`. #' #' `r lifecycle::badge("deprecated")` #' #' @param ... Multiple `chk_` functions. #' #' @return An informative error if the test fails. #' #' @seealso [chk_null_or()] #' #' @export #' #' @examples #' chkor() #' chkor(chk_flag(TRUE)) #' try(chkor(chk_flag(1))) #' try(chkor(chk_flag(1), chk_flag(2))) #' chkor(chk_flag(1), chk_flag(TRUE)) chkor <- function(...) { lifecycle::deprecate_soft("0.6.1", "chkor()", "chkor_vld()") quos <- enquos(...) invisible(chkor_quos(quos)) } chk/R/chk-lte.R0000644000176200001440000000217314743771477012722 0ustar liggesusers#' Check Less Than or Equal To #' #' @description #' Checks if all non-missing values are less than or equal to y using #' #' `all(x[!is.na(x)] <= value)` #' #' @inheritParams params #' @inherit params return #' #' @family range_checkers #' #' @seealso [all()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_lte #' chk_lte(0) #' try(chk_lte(0.1)) #' @export chk_lte <- function(x, value = 0, x_name = NULL) { if (vld_lte(x, value)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length(x) == 1L) { abort_chk( x_name, " must be less than or equal to ", cc(value), ", not ", cc(x), "" ) } abort_chk(x_name, " must have values less than or equal to ", cc(value), x = x, value = value) } #' @describeIn chk_lte Validate Less Than or Equal To #' #' @examples #' # vld_lte #' vld_lte(numeric(0)) #' vld_lte(0) #' vld_lte(0.1) #' vld_lte(c(-0.1, -0.2, NA)) #' vld_lte(c(-0.1, -0.2, NA), value = -1) #' @export vld_lte <- function(x, value = 0) all(x[!is.na(x)] <= value) chk/R/chk-count.R0000644000176200001440000000172514743771477013270 0ustar liggesusers#' Check Count #' #' @description #' Checks if non-negative whole number using #' #' `vld_whole_number(x) && x >= 0` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checkers #' @family whole_number_checkers #' #' @seealso [vld_whole_number()] #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_count #' chk_count(1) #' try(chk_count(1.5)) #' @export chk_count <- function(x, x_name = NULL) { if (vld_count(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be a count (non-negative non-missing integer scalar or double equivalent)", x = x) } #' @describeIn chk_count Validate Count #' #' @examples #' # vld_count #' vld_count(1) #' vld_count(0L) #' vld_count(-1) #' vld_count(0.5) #' @export vld_count <- function(x) { vld_whole_number(x) && x >= 0 } chk/R/chk-join.R0000644000176200001440000000270214743771477013073 0ustar liggesusers#' Check Join #' #' @description #' Checks if all rows in x match at least one in y. #' #' @inheritParams params #' @param y A data.frame with columns in by. #' @inherit params return #' #' @family misc_checkers #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_join #' chk_join(data.frame(z = 1), data.frame(z = 1:2), by = "z") #' try(chk_join(data.frame(z = 1), data.frame(z = 2), by = "z")) #' @export chk_join <- function(x, y, by, x_name = NULL) { if (vld_join(x, y, by)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) y_name <- as_label(y) obj_of <- if (grepl("^<", y_name)) "the y object of class " else NULL abort_chk("All rows in ", x_name, " must match at least one in ", obj_of, y_name, x = x, y = y, by = by ) } #' @describeIn chk_join Validate Join #' #' @examples #' # vld_join #' vld_join(data.frame(z = 1), data.frame(z = 1:2), by = "z") #' vld_join(data.frame(z = 1), data.frame(z = 2), by = "z") #' vld_join(data.frame(z = 1), data.frame(a = 1:2), by = c(z = "a")) #' vld_join(data.frame(z = 1), data.frame(a = 2), by = c(z = "a")) #' @export vld_join <- function(x, y, by) { if (is.null(by)) { return(FALSE) } identical( nrow(x), nrow(merge(as.data.frame(x), unique(as.data.frame(y)[by]), by.x = if (is.null(names(by))) by else names(by), by.y = by )) ) } chk/R/check-key.R0000644000176200001440000000223614555540507013223 0ustar liggesusers#' Check Key #' #' @description #' Checks if columns have unique rows. #' #' @inheritParams params #' @param key A character vector of the columns that represent a unique key. #' @param na_distinct A flag specifying whether missing values should be considered distinct. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' x <- data.frame(x = c(1, 2), y = c(1, 1)) #' check_key(x) #' try(check_key(x, "y")) #' @export check_key <- function(x, key = character(0), na_distinct = FALSE, x_name = NULL) { chk_data(x) chk_s3_class(key, "character") if (!length(key)) { return(invisible(x)) } chk_unique(key) chk_not_any_na(key) chk_flag(na_distinct) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) chk_string(x_name) check_names(x, key, x_name = x_name) # to ensure not tripped up by sf objects. x2 <- as.data.frame(x) incomparables <- if (na_distinct) NA else FALSE if (any(new_duplicated(x2[key], incomparables = incomparables))) { abort_chk("Column%s ", cc(key, conj = " and "), " in ", x_name, " must be a unique key.", n = length(key)) } invisible(x) } chk/R/check-dim.R0000644000176200001440000000315414744727670013214 0ustar liggesusers#' Check Dimension #' #' @description #' Checks dimension of an object. #' #' @inheritParams params #' @param dim A function returning a non-negative whole number of the dimension. #' @param values A flag or a whole numeric vector of the value, value range or possible values. #' @param dim_name A string of the name of the dim function. #' @return An informative error if the test fails or an invisible copy of x. #' #' @family check #' #' @examples #' check_dim(1) #' try(check_dim(1, values = FALSE)) #' try(check_dim(1, values = c(10, 2))) #' try(check_dim(data.frame(x = 1), dim = nrow, values = c(10, 10, 2))) #' @export check_dim <- function(x, dim = length, values = numeric(0), x_name = NULL, dim_name = NULL) { chk_function(dim) if (!vld_flag(values) && !vld_whole_numeric(values)) { chkor_vld(vld_flag(values), vld_whole_numeric(values)) } chk_whole_number(dim(x)) chk_gte(dim(x)) if (is.null(x_name)) x_name <- deparse((substitute(x))) chk_string(x_name) if (is.null(dim_name)) dim_name <- deparse((substitute(dim))) chk_string(dim_name) x_name <- backtick_chk(p0(dim_name, "(", x_name, ")")) if (!length(values)) { return(invisible(x)) } if (vld_true(values)) { return(chk_gt(dim(x), x_name = x_name)) } if (vld_false(values)) values <- 0L if (identical(length(values), 2L)) { if (!identical(values[1], values[2])) { return(chk_range(dim(x), sort(values), x_name = x_name)) } values <- unique(values) } if (identical(length(values), 1L)) { return(chk_equal(dim(x), values, x_name = x_name)) } chk_subset(dim(x), sort(unique(values)), x_name = x_name) } chk/R/chk-equal.R0000644000176200001440000000231714743771477013245 0ustar liggesusers#' Check Equal #' #' @description #' Checks if is equal (identical within tolerance) to y using #' #' `vld_true(all.equal(x, y, tolerance))` #' #' @inheritParams params #' @inherit params return #' #' @family equal_checkers #' #' @seealso [vld_true()] #' @seealso [all.equal()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_equal #' chk_equal(1, 1.00000001) #' try(chk_equal(1, 1.0000001)) #' chk_equal(1, 1L) #' chk_equal(c(x = 1), c(x = 1L)) #' try(chk_equal(c(x = 1), c(y = 1L))) #' @export chk_equal <- function(x, y, tolerance = sqrt(.Machine$double.eps), x_name = NULL) { if (vld_equal(x, y, tolerance = tolerance)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) y_name <- as_label(y) obj_of <- if (grepl("^<", y_name)) "the y object of class " else NULL abort_chk(x_name, " must be equal to ", obj_of, y_name, x = x, y = y ) } #' @describeIn chk_equal Validate Equal #' #' @examples #' vld_equal(1, 1.00000001) #' @export vld_equal <- function(x, y, tolerance = sqrt(.Machine$double.eps)) { vld_true(all.equal(x, y, tolerance)) } chk/R/chk-s4-class.R0000644000176200001440000000207414743771477013567 0ustar liggesusers#' Check Inherits from S4 Class #' #' @description #' Checks inherits from S4 class using #' #' `isS4(x) && methods::is(x, class)` #' #' @inheritParams params #' @inherit params return #' #' @family id_checkers #' #' @seealso [methods::is()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_s4_class #' try(chk_s4_class(1, "numeric")) #' chk_s4_class(getClass("MethodDefinition"), "classRepresentation") #' @export chk_s4_class <- function(x, class, x_name = NULL) { if (vld_s4_class(x, class)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) .class <- class abort_chk(x_name, " must inherit from S4 class '", .class, "'", x = x, .class = .class) } #' @describeIn chk_s4_class Validate Inherits from S4 Class #' #' @examples #' # vld_s4_class #' vld_s4_class(numeric(0), "numeric") #' vld_s4_class(getClass("MethodDefinition"), "classRepresentation") #' @export vld_s4_class <- function(x, class) isS4(x) && methods::is(x, class) chk/R/chk-function.R0000644000176200001440000000235414743771477013764 0ustar liggesusers#' Check Function #' #' @description #' Checks if is a function using #' #' `is.function(x) && (is.null(formals) || length(formals(x)) == formals)` #' #' @inheritParams params #' @inherit params return #' #' @family function_checkers #' @family ellpisis_checkers #' @family missing_checkers #' #' @seealso [is.function()] [formals()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_function #' chk_function(mean) #' try(chk_function(1)) #' @export chk_function <- function(x, formals = NULL, x_name = NULL) { if (vld_function(x, formals)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (!is.function(x)) abort_chk(x_name, " must be a function", x = x, formals = formals) abort_chk(x_name, " must have ", formals, " formal arguments (not ", length(formals(x)), ")", x = x, formals = formals) } #' @describeIn chk_function Validate Function #' #' @examples #' # vld_function #' vld_function(mean) #' vld_function(function(x) x) #' vld_function(1) #' vld_function(list(1)) #' @export vld_function <- function(x, formals = NULL) { is.function(x) && (is.null(formals) || length(formals(x)) == formals) } chk/R/chk-not-empty.R0000644000176200001440000000210714743771477014067 0ustar liggesusers#' Check Not Empty #' #' @description #' Checks if not empty using #' #' `length(x) != 0L` #' #' **Pass**: `1`, `1:2`, `NA`, `matrix(1:3)`, `list(1)`, `data.frame(x = 1)`. #' #' **Fail**: `NULL`, `logical(0)`, `list()`, `data.frame()`. #' #' @inheritParams params #' @inherit params return #' #' @family misc_checkers #' #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_not_empty #' chk_not_empty(1) #' try(chk_not_empty(numeric(0))) #' @export chk_not_empty <- function(x, x_name = NULL) { if (vld_not_empty(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must not be empty (zero length)", x = x) } #' @describeIn chk_not_empty Validate Not Empty #' #' @examples #' # vld_not_empty #' vld_not_empty(1) #' vld_not_empty(matrix(1:3)) #' vld_not_empty(character(0)) #' vld_not_empty(list(1)) #' vld_not_empty(NULL) #' vld_not_empty(list()) #' @export vld_not_empty <- function(x) length(x) != 0L chk/R/chk-dbl.R0000644000176200001440000000215314436206156012657 0ustar liggesusers#' Check Double Scalar #' #' @description #' Checks if double scalar using #' #' `is.double(x) && length(x) == 1L` #' #' `r lifecycle::badge("deprecated")` #' #' @inheritParams params #' @inherit params return #' #' @family deprecated #' #' @examples #' # chk_dbl #' chk_dbl(1) #' try(chk_dbl(1L)) #' @export chk_dbl <- function(x, x_name = NULL) { if (vld_dbl(x)) { return(invisible(x)) } deprecate_soft( "0.6.1", what = "chk::chk_dbl()", details = "Please use `chk::chk_scalar(x);` `chk::chk_double(x)` instead", id = "chk_dbl" ) if (is.null(x_name)) x_name <- deparse_backtick_chk((substitute(x))) abort_chk(x_name, " must be double (real) scalar", x = x) } #' @describeIn chk_dbl Validate Double #' #' `r lifecycle::badge("deprecated")` #' #' @examples #' # vld_dbl #' vld_dbl(1) #' vld_dbl(double(0)) #' vld_dbl(NA_real_) #' vld_dbl(c(1, 1)) #' vld_dbl(1L) #' @export vld_dbl <- function(x) { deprecate_soft( "0.6.1", what = "chk::chk_dbl()", details = "Please use `chk::chk_scalar(x);` `chk::chk_double(x)` instead", id = "chk_dbl" ) is.double(x) && length(x) == 1L } chk/R/chk-package.R0000644000176200001440000000023414654734236013516 0ustar liggesusers#' @keywords internal "_PACKAGE" ## usethis namespace: start #' @import rlang lifecycle #' @importFrom lifecycle deprecated ## usethis namespace: end NULL chk/R/chk-length.R0000644000176200001440000000224414744734003013377 0ustar liggesusers#' Check Length #' #' @description #' Checks length is a particular value or range using #' #' `length(x) >= length && length(x) <= upper` #' #' @inheritParams params #' @inherit params return #' #' @family length_checkers #' #' @seealso [length()], [check_length()], [check_dim()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_length #' chk_length("text") #' try(vld_length("text", length = 2)) #' @export chk_length <- function(x, length = 1L, upper = length, x_name = NULL) { if (vld_length(x, length, upper)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) if (length == upper) { abort_chk(x_name, " must be length ", length, " not ", length(x), x = x, length = length) } abort_chk(x_name, " must have a length between ", length, " and ", upper, " not ", length(x), x = x, length = length) } #' @describeIn chk_length Validate Length #' #' @examples #' # vld_length #' vld_length(2:1, 2) #' vld_length(2:1, 1) #' @export vld_length <- function(x, length = 1L, upper = length) length(x) >= length && length(x) <= upper chk/R/chk-tz.R0000644000176200001440000000201414743771477012565 0ustar liggesusers#' Check Time Zone #' #' @description #' Checks if non-missing valid scalar timezone using #' #' `is.character(x) && length(x) == 1L && !anyNA(x) && x %in% OlsonNames()` #' #' @inheritParams params #' @inherit params return #' #' @family tz_checkers #' @family date_checkers #' @family scalar_checkers #' #' @seealso [length()] #' @seealso [OlsonNames()] #' @seealso [is.character()] #' #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' chk_tz("UTC") #' try(chk_tz("TCU")) #' @export chk_tz <- function(x, x_name = NULL) { if (vld_tz(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a tz (non-missing scalar character of a recognized timezone)", x = x) } #' @describeIn chk_tz Validate Time Zone #' #' @examples #' vld_tz("UTC") #' vld_tz("TCU") #' @export vld_tz <- function(x) { is.character(x) && length(x) == 1L && !anyNA(x) && x %in% OlsonNames() } chk/R/chk-s3-class.R0000644000176200001440000000204314743771477013562 0ustar liggesusers#' Check Type #' #' @description #' Checks inherits from S3 class using #' #' `!isS4(x) && inherits(x, class)` #' #' @inheritParams params #' @inherit params return #' #' @family id_checkers #' #' @seealso [inherits()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_s3_class #' chk_s3_class(1, "numeric") #' try(chk_s3_class(getClass("MethodDefinition"), "classRepresentation")) #' @export chk_s3_class <- function(x, class, x_name = NULL) { if (vld_s3_class(x, class)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) .class <- class abort_chk(x_name, " must inherit from S3 class '", .class, "'", x = x, .class = .class) } #' @describeIn chk_s3_class Validate Inherits from S3 Class #' #' @examples #' # vld_s3_class #' vld_s3_class(numeric(0), "numeric") #' vld_s3_class(getClass("MethodDefinition"), "classRepresentation") #' @export vld_s3_class <- function(x, class) !isS4(x) && inherits(x, class) chk/R/chk-string.R0000644000176200001440000000166114743771477013445 0ustar liggesusers#' Check String #' #' @description #' Checks if string #' #' `is.character(x) && length(x) == 1L && !anyNA(x)` #' #' @inheritParams params #' @inherit params return #' #' @family scalar_checkers #' #' @seealso [length()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_string #' chk_string("1") #' try(chk_string(1)) #' @export chk_string <- function(x, x_name = NULL) { if (vld_string(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) abort_chk(x_name, " must be a string (non-missing character scalar)", x = x) } #' @describeIn chk_string Validate String #' #' @examples #' # vld_string #' vld_string("1") #' vld_string("") #' vld_string(1) #' vld_string(NA_character_) #' vld_string(c("1", "1")) #' @export vld_string <- function(x) { is.character(x) && length(x) == 1L && !anyNA(x) } chk/R/params.R0000644000176200001440000000432614743771477012660 0ustar liggesusers#' Parameter Descriptions for chk Package #' #' Default parameter descriptions which may be overridden in individual #' functions. #' #' A flag is a non-missing logical scalar. #' #' A string is a non-missing character scalar. #' #' @param x The object to check. #' @param x_name A string of the name of object x or NULL. #' @param y An object to check against. #' @param chk A flag specifying whether to check the other parameters. #' @param chk_fun A chk_ function. #' @param tolerance A non-negative numeric scalar. #' @param ext A character vector of the permitted file extensions #' (without the .). #' @param exists A flag specifying whether the files/directories must (or must not) exist. #' @param value A non-missing scalar of a value. #' @param range A non-missing sorted vector of length 2 of the lower and #' upper permitted values. #' @param inclusive A flag specifying whether the range is exclusive. #' @param regexp A string of a regular expression. #' @param values A vector of the permitted values. #' @param class A string specifying the class. #' @param length A count of the length. #' @param upper A count of the max length. #' @param formals A count of the number of formal arguments. #' @param incomparables A vector of values that cannot be compared. #' FALSE means that all values can be compared. #' @param by A character vector specifying the column names to join x and y on. #' If named the names are the corresponding columns in x. #' @param exclusive A flag specifying whether x must only include columns named in values. #' @param order A flag specifying whether the order of columns in x must match names in values. #' @param nrow A flag or a whole numeric vector of the value, value range or possible values. #' @param key A character vector of the columns that represent a unique key. #' @param vld_fun A vld_ function. #' @param ... Additional arguments. #' @return #' The `chk_` function throws an informative error if the test fails or #' returns the original object if successful so it can used in pipes. #' #' The `vld_` function returns a flag indicating whether the test was met. #' #' @keywords internal #' @aliases parameters arguments args #' @usage NULL # nocov start params <- function(...) NULL # nocov end chk/R/chk-file.R0000644000176200001440000000204414743771477013052 0ustar liggesusers#' Check File Exists #' #' @description #' Checks if file exists using #' #' `vld_string(x) && file.exists(x) && !dir.exists(x)` #' #' @inheritParams params #' @inherit params return #' #' @family file_checkers #' #' @seealso [vld_string()] #' @seealso [file.exists()] #' @seealso [dir.exists()] #' @seealso For more details about the use of this function, #' please read the article #' `vignette("chk-families")`. #' #' @examples #' # chk_file #' try(chk_file(tempfile())) #' @export chk_file <- function(x, x_name = NULL) { if (vld_file(x)) { return(invisible(x)) } if (is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) chk_string(x, x_name = x_name) if (dir.exists(x)) { abort_chk(x_name, " must specify a file ('", x, "' is a directory)", x = x) } abort_chk(x_name, " must specify an existing file ('", x, "' can't be found)", x = x) } #' @describeIn chk_file Validate File Exists #' #' @examples #' # vld_file #' vld_file(tempfile()) #' @export vld_file <- function(x) vld_string(x) && file.exists(x) && !dir.exists(x) chk/vignettes/0000755000176200001440000000000014744765210013041 5ustar liggesuserschk/vignettes/chk.Rmd0000644000176200001440000001170314743771503014255 0ustar liggesusers--- title: "Get Started with chk" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Get Started with chk} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Introduction R functions and packages are great for sharing code, but it's hard to predict how end-users will implement them. Users might pass inputs that your function wasn't designed to handle, leading to incorrect results or errors. For example, if a function expects a numeric vector (e.g., `c(1, 2, 3)`) but receives a character vector (e.g.,` c("1", "2", "3")`), it may return an error. The `chk` package provides a set of functions that check user-provided arguments and deliver meaningful error messages to guide users when something goes wrong. Including `chk`'s specially designed functions when developing your R package will help improve user experience, prevent errors, and make your code more robust by ensuring consistent behavior across different inputs. This enhances the reliability and reusability of your code. Additionally, it can help with performance optimization by ensuring that your functions receive inputs of the appropriate size, thereby avoiding time-consuming calculations. ## Goal `chk` is an R package for developers to check user-supplied function arguments. It is designed to be simple, customizable and fast. ## `chk` Functions Based on the function prefixes, we can classify `chk` functions into three categories: 1. `chk_` Functions 2. `vld_` Functions 3. `check_` Functions ### 1. `chk_` Functions `chk_` functions check the properties of individual objects. For example, `chk_flag(x)` checks whether `x` is a flag, i.e., a non-missing logical vector of length 1. `chk_` functions are called for their side-effects, i.e., they throw an informative error if the object fails the check. Although do return an invisible copy of the first argument so they can be used in pipes. ```{r, error=TRUE} library(chk) y <- TRUE chk_flag(y) y <- NA chk_flag(y) ``` The error messages, which follow the [tidyverse style guide](https://style.tidyverse.org/errors.html), are designed to allow the user to quickly identify the problem with the argument value(s) they are providing. The errors are [rlang errors](https://rlang.r-lib.org/reference/abort.html) of subclass `'chk_error'`. ### 2. `vld_` Functions Each `chk_` function has a matching `vld_` function which returns a flag indicating whether the object passed the check. ```{r, error=TRUE} vld_flag(TRUE) vld_flag(NA) ``` The `vld_` functions allow developers to provide their own error messages. ```{r, error=TRUE} if (!vld_flag(NA)) abort_chk("`NA` is not TRUE or FALSE!!") ``` ### 3. `check_` Functions The `check_` functions are more complex then the `chk_` functions which make them slower but makes doing some general tests easier. ## Using chk The `chk_` functions are designed to be used within functions. Consequently, when constructing an error message they use the name of the object that they received as this is expected to be the name of the argument. ```{r, error = TRUE} fun1 <- function(x) { chk_whole_number(x) # use x } fun1(1) y <- 1.3 fun1(x = y) ``` If this is not the case, developers can provide a different name using the `x_name` argument. ```{r, error = TRUE} x <- NA chk_flag(x, x_name = "`zzz`") ``` **IMPORTANT NOTE** As the `chk_` (and `vld_`) functions are not expected to be directly exposed to users they don't check any of their arguments (other than the object of interest of course!) to ensure that they are as fast as possible. ## Extending chk The `chk_flag()` function illustrates the general structure of a `chk_` function. ``` r chk_flag #> function(x, x_name = NULL){ #> if(vld_flag(x)) return(invisible(x)) #> if(is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) #> abort_chk(x_name, " must be a flag (TRUE or FALSE)") #> } #> #> ``` A `chk_` function initially checks the object (using its `vld_` partner) and if the object passes the check immediately returns an invisible copy of the object. If, and only if, the object fails the check does the `chk_` function construct and then throw an informative error message. The `deparse_backtick_chk()` and `abort_chk()` functions are exported to make it easy for programmers to develop their own `chk_` functions. The [chk-lgl.R](https://github.com/poissonconsulting/chk/blob/master/R/chk-lgl.R) script illustrates the general template to use when developing your own `chk_` functions. ### `abort_chk()` The `abort_chk()` function converts multiple arguments to a string using `paste0(..., collapse = '')` and provides number sensitive `sprintf`-like types. By default it also capitalizes the first character and adds a missing period. ```{r, error=TRUE} abort_chk("There %r %n problem director%y%s.", n = 1) abort_chk("there %r %n ", "problem director%y%s", n = 2) ``` chk/vignettes/chk-families.Rmd0000644000176200001440000005153214743771503016050 0ustar liggesusers--- title: "chk Families" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{chk Families} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(chk) ``` ## Introduction The `vld_` functions are used within the `chk_` functions. The `chk_` functions (and their `vld_` equivalents) can be divided into the following families. In the code in this examples, we will use `vld_*` functions If you want to learn more about the logic behind some of the functions explained here, we recommend reading the book [Advanced R](https://adv-r.hadley.nz/) (Wickham, 2019). For reasons of space, the `x_name = NULL` argument is not shown. For a more simplified list of the `chk` functions, you can see the [Reference](https://poissonconsulting.github.io/chk/reference/index.html) section. ## `chk_` Functions ### Overview ```{r chk_, echo = FALSE, out.width= "100%", fig.align='center', fig.alt = "Classification of the chk functions by family"} knitr::include_graphics("chk_diagram_II.png") ``` ### Missing Input Checker Check if the function input is missing or not `chk_missing` function uses `missing()` to check if an argument has been left out when the function is called. Function | Code :- | :--- `chk_missing()` | `missing()` `chk_not_missing()` | `!missing()` ### `...` Checker Check if the function input comes from `...` (`dot-dot-dot`) or not The functions `chk_used(...)` and `chk_unused(...)` check if any arguments have been provided through `...` (called `dot-dot-dot` or ellipsis), which is commonly used in R to allow a variable number of arguments. Function | Code :- | :--- `chk_used(...)` | `length(list(...)) != 0L` `chk_unused(...)` | `length(list(...)) == 0L` ### External Data Source Checkers Check if the function input is a valid external data source. These `chk` functions check the existence of a file, the validity of its extension, and the existence of a directory. Function | Code :- | :--- `chk_file(x)` | `vld_string(x) && file.exists(x) && !dir.exists(x)` `chk_ext(x, ext)` | `vld_string(x) && vld_subset(tools::file_ext(x), ext)` `chk_dir(x)` | `vld_string(x) && dir.exists(x)` ### NULL checker Check if the function input is NULL or not Function | Code :- | :--- `chk_null(x)` | `is.null(x)` `chk_not_null(x)` | `!is.null(x)` ### Scalar Checkers Check if the function input is a scalar. In R, scalars are vectors of length 1. Function | Code :- | :------ `chk_scalar(x)` | `length(x) == 1L` The following functions check if the functions inputs are vectors of length 1 of a particular data type. Each data type has a special syntax to create an individual value or "scalar". Function | Code :- | :------ `chk_string(x)` | `is.character(x) && length(x) == 1L && !anyNA(x)` `chk_number(x)` | `is.numeric(x) && length(x) == 1L && !anyNA(x)` For logical data types, you can check flags using `chk_flag()`, which considers `TRUE` or `FALSE` as possible values, or use `chk_lgl()` to verify if a scalar is of type logical, including NA as element. Function | Code :- | :- `chk_flag(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x)` `chk_lgl(x)` | `is.logical(x) && length(x) == 1L` It is also possible to check if the user-provided argument is only `TRUE` or only `FALSE`: Function | Code :- | :- `chk_true(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x) && x` `chk_false(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x) && !x` ### Date or DateTime Checkers Check if the function input is of class Date or DateTime Date and datetime classes can be checked with `chk_date` and `chk_datetime`. Function | Code :- | :------ `chk_date(x)` | `inherits(x, "Date") && length(x) == 1L && !anyNA(x)` `chk_date_time(x)` | `inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x)` ### Time Zone Checker Also you can check the time zone with `chk_tz()`. The available time zones can be retrieved using the function `OlsonNames()`. Function | Code :- | :------ `chk_tz(x)` | `is.character(x) && length(x) == 1L && !anyNA(x) && x %in% OlsonNames()` #### Data Structure Checker Check if the function input has a specific data structure. Vectors are a family of data types that come in two forms: atomic vectors and lists. When vectors consist of elements of the same data type, they can be considered atomic, matrices, or arrays. The elements in a list, however, can be of different types. To check if a function argument is a vector you can use `chk_vector()`. Function | Code :- | :--- `chk_vector(x)` | `is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x)` Pay attention that `chk_vector()` and `vld_vector()` are different from `is.vector()`, that will return FALSE if the vector has any attributes except names. ```{r} vector <- c(1, 2, 3) is.vector(vector) # TRUE vld_vector(vector) # TRUE attributes(vector) <- list("a" = 10, "b" = 20, "c" = 30) is.vector(vector) # FALSE vld_vector(vector) # TRUE ``` Function | Code :- | :--- `chk_atomic(x)` | `is.atomic(x)` Notice that `is.atomic` is true for the types logical, integer, numeric, complex, character and raw. Also, it is TRUE for NULL. ```{r} vector <- c(1, 2, 3) is.atomic(vector) # TRUE vld_vector(vector) # TRUE is.atomic(NULL) # TRUE vld_vector(NULL) # TRUE ``` The dimension attribute converts vectors into matrices and arrays. Function | Code :- | :--- `chk_array(x)` | `is.array(x)` `chk_matrix(x)` | `is.matrix(x)` When a vector is composed by heterogeneous data types, can be a list. Data frames are among the most important S3 vectors, constructed on top of lists. Function | Code :- | :--- `chk_list(x)` | `is.list()` `chk_data(x)` | `inherits(x, "data.frame")` Be careful not to confuse the function `chk_data` with `check_data`. Please read the `check_` functions section below and the function documentation. ### Data Type Checkers Check if the function input has a data type. You can use the function `typeof()` to confirm the data type. Function | Code :- | :--- `chk_environment(x)` | `is.environment(x)` `chk_logical(x)` | `is.logical(x)` `chk_character(x)` | `is.character(x)` For numbers there are four functions. R differentiates between doubles (`chk_double()`) and integers (`chk_integer()`). You can also use the generic function `chk_numeric()`, which will detect both. The third type of number is complex (`chk_complex()`). Function | Code :- | :--- `chk_numeric(x)` | `is.numeric(x)` `chk_double(x)` | `is.double(x)` `chk_integer(x)` | `is.integer(x)` `chk_complex(x)` | `is.complex(x)` Consider that to explicitly create an integer in R, you need to use the suffix `L`. ```{r} vld_numeric(33) # TRUE vld_double(33) # TRUE vld_integer(33) # FALSE vld_integer(33L) # TRUE ``` ### Whole Number Checkers These functions accept whole numbers, whether they are explicitly integers or double types without fractional parts. Function | Code :- | :--- `chk_whole_numeric` | `is.integer(x) || (is.double(x) && vld_true(all.equal(x[!is.na(x)], trunc(x[!is.na(x)]))))` `chk_whole_number` | `vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x))))` `chk_count` | `vld_whole_number(x) && x >= 0` If you want to consider both 3.0 and 3L as integers, it is safer to use the function `chk_whole_numeric`. Here, `x` is valid if it's an integer or a double that can be converted to an integer without changing its value. ```{r} # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE # Double vector representing whole numbers vld_whole_numeric(c(1.0, 2.0, 3.0)) # TRUE # Double vector with fractional numbers vld_whole_numeric(c(1.0, 2.2, 3.0)) # FALSE ``` The function `chk_whole_number` is similar to `chk_whole_numeric`. `chk_whole_number` checks if the number is of `length(x) == 1L` ```{r} # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE vld_whole_number(c(1L, 2L, 3L)) # FALSE vld_whole_number(c(1L)) # TRUE ``` `chk_count()` is a special case of `chk_whole_number`, differing in that it ensures values are non-negative whole numbers. ```{r} # Positive integer vld_count(1) #TRUE # Zero vld_count(0) # TRUE # Negative number vld_count(-1) # FALSE # Non-whole number vld_count(2.5) # FALSE ``` ### Factor Checker Check if the function input is a factor Function | Code :- | :------ `chk_factor` | `is.factor(x)` `chk_character_or_factor` | `is.character(x) || is.factor(x)` Factors can be specially confusing for users, because despite they are displayed as characters are built in top of integer vectors. `chk` provides the function `chk_character_or_factor()` that allows detecting if the argument that the user is providing contains strings. ```{r} # Factor with specified levels vector_fruits <- c("apple", "banana", "apple", "orange", "banana", "apple") factor_fruits <- factor(c("apple", "banana", "apple", "orange", "banana", "apple"), levels = c("apple", "banana", "orange")) is.factor(factor_fruits) # TRUE vld_factor(factor_fruits) # TRUE is.character(factor_fruits) # FALSE vld_character(factor_fruits) # FALSE vld_character_or_factor(factor_fruits) # TRUE ``` ### All Elements Checkers Check if the function input has a characteristic shared by all its elements. If you want to apply any of the previously defined functions for `length(x) == 1L` to the elements of a vector, you can use `chk_all()`. Function | Code :- | :--- `chk_all(x, chk_fun, ...)` | `all(vapply(x, chk_fun, TRUE, ...))` ```{r} vld_all(c(TRUE, TRUE, FALSE), chk_lgl) # FALSE ``` ### Function Checker Check if the function input is another function `formals` refers to the count of the number of formal arguments Function | Code :- | :------ `chk_function` | `is.function(x) && (is.null(formals) || length(formals(x)) == formals)` ```{r} vld_function(function(x) x, formals = 1) # TRUE vld_function(function(x, y) x + y, formals = 1) # FALSE vld_function(function(x, y) x + y, formals = 2) # TRUE ``` ### Name Checkers Check if the function input has names and are valid `chk_named` function works with vectors, lists, data frames, and matrices that have named columns or rows. Do not confuse with `check_names`. `chk_valid_name` function specifically designed to check if the elements of a character vector are valid R names. If you want to know what is considered a valid name, please refer to the documentation for the `make.names` function. Function | Code :- | :-- `chk_named(x)` | `!is.null(names(x))` `chk_valid_name(x)` | `identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)]))` ```{r} vld_valid_name(c("name1", NA, "name_2", "validName")) # TRUE vld_valid_name(c(1, 2, 3)) # FALSE vld_named(data.frame(a = 1:5, b = 6:10)) # TRUE vld_named(list(a = 1, b = 2)) # TRUE vld_named(c(a = 1, b = 2)) # TRUE vld_named(c(1, 2, 3)) # FALSE ``` ### Range Checkers Check if the function input is part of a range of values. The function input should be numeric. Function | Code :- | :--- `chk_range(x, range = c(0, 1))` | `all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])` `chk_lt(x, value = 0)` | `all(x[!is.na(x)] < value)` `chk_lte(x, value = 0)` | `all(x[!is.na(x)] <= value)` `chk_gt(x, value = 0)` | `all(x[!is.na(x)] > value)` `chk_gte(x, value = 0)` | `all(x[!is.na(x)] >= value)` ### Equal Checkers Check if the function input is equal or similar to a predefined object. The functions `chk_identical()`, `chk_equal()`, and `chk_equivalent()` are used to compare two objects, but they differ in how strict the comparison is. `chk_equal` and `chk_equivalent`checks if x and y are numerically equivalent within a specified tolerance, but `chk_equivalent` ignores differences in attributes. Function | Code :-- | :- `chk_identical(x, y)` | `identical(x, y)` `chk_equal(x, y, tolerance = sqrt(.Machine$double.eps))` | `vld_true(all.equal(x, y, tolerance))` `chk_equivalent(x, y, tolerance = sqrt(.Machine$double.eps))` | `vld_true(all.equal(x, y, tolerance, check.attributes = FALSE))` In the case you want to compare the elements of a vector, you can use the `check_all_*` functions. Function | Code :-- | :-- `chk_all_identical(x)` | `length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]]))` `chk_all_equal(x, tolerance = sqrt(.Machine$double.eps))` | `length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance))` `chk_all_equivalent(x, tolerance = sqrt(.Machine$double.eps))` | `length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance))` ```{r} vld_all_identical(c(1, 2, 3)) # FALSE vld_all_identical(c(1, 1, 1)) # TRUE vld_identical(c(1, 2, 3), c(1, 2, 3)) # TRUE vld_all_equal(c(0.1, 0.12, 0.13)) vld_all_equal(c(0.1, 0.12, 0.13), tolerance = 0.2) vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.13)) # TRUE vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.4), tolerance = 0.5) # TRUE x <- c(0.1, 0.1, 0.1) y <- c(0.1, 0.12, 0.13) attr(y, "label") <- "Numbers" vld_equal(x, y, tolerance = 0.5) # FALSE vld_equivalent(x, y, tolerance = 0.5) # TRUE ``` ### Order Checker Check if the function input are numbers in increasing order `chk_sorted` function checks if `x` is sorted in non-decreasing order, ignoring any NA values. Function | Code :- | :-- `chk_sorted(x)` | `!is.unsorted(x, na.rm = TRUE)` ```{r} # Checking if sorted vld_sorted(c(1, 2, 3, NA, 4)) # TRUE vld_sorted(c(3, 1, 2, NA, 4)) # FALSE ``` ### Set Checkers Check if the function input is composed by certain elements The `setequal` function in R is used to check if two vectors contain exactly the same elements, regardless of the order or number of repetitions. Function | Code :- | :--- `chk_setequal(x, values)` | `setequal(x, values)` ```{r} vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE ``` First, the `%in%` function is used to check whether the elements of a vector `x` are present in a specified set of values. This returns a logical vector, which is then simplified by `all()`. The `all()` function checks if all values in the vector are TRUE. If the result is TRUE, it indicates that for `vld_` and `chk_subset()`, all elements in the `x` vector are present in `values`. Similarly, for `vld_` and `chk_superset()`, it indicates that all elements of `values` are present in `x`. Function | Code :-- | :-- `chk_subset(x, values)` | `all(x %in% values)` `chk_not_subset(x, values)` | `!any(x %in% values) || !length(x)` `chk_superset(x, values)` | `all(values %in% x)` ```{r} # When both function inputs have the same elements, # all functions return TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_subset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_subset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_superset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE # When there are elements present in one vector but not the other, # `vld_setequal()` will return FALSE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE # When some elements of the `x` input are not present in `values`, # `vld_subset()` returns FALSE vld_subset(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_superset(c(1, 2, 3, 4), c(3, 2, 1)) # TRUE # When some elements of the `values` input are not present in `x`, # `vld_superset()` returns FALSE vld_subset(c(1, 2, 3), c(3, 2, 1, 4)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE # An empty set is considered a subset of any set, and any set is a superset of an empty set. vld_subset(c(), c("apple", "banana")) # TRUE vld_superset(c("apple", "banana"), c()) # TRUE ``` `chk_orderset()` validate whether a given set of `values` in a vector x matches a specified set of allowed `values` (represented by `values`) while preserving the order of those values. Function | Code :-- | :-- `chk_orderset` | `vld_equivalent(unique(x[x %in% values]), values[values %in% x])` ```{r} vld_orderset(c("A", "B", "C"), c("A", "B", "C", "D")) # TRUE vld_orderset(c("C", "B", "A"), c("A", "B", "C", "D")) # FALSE vld_orderset(c("A", "C"), c("A", "B", "C", "D")) # TRUE ``` ### Class Checkers Check if the function input belongs to a class or type. These functions check if `x` is an S3 or S4 object of the specified class. Function | Code :- | :--- `chk_s3_class(x, class)` | `!isS4(x) && inherits(x, class)` `chk_s4_class(x, class)` | `isS4(x) && methods::is(x, class)` `chk_is()` checks if x inherits from a specified class, regardless of whether it is an S3 or S4 object. Function | Code :- | :--- `chk_is(x, class)` | `inherits(x, class)` ### REGEX Checker Check if the function input matches a regular expression (REGEX). `chk_match(x, regexp = ".+")` checks if the regular expression pattern specified by `regexp` matches all the non-missing values in the vector `x`. If `regexp` it is not specified by the user, `chk_match` checks whether all non-missing values in `x` contain at least one character (regexp = ".+") Function | Code :- | :-- `chk_match(x, regexp = ".+")` | `all(grepl(regexp, x[!is.na(x)]))` ### Quality Checkers (Miscellaneous) Check if the function input meet some user defined quality criteria. `chk_not_empty` function checks if the length of the object is not zero. For a data frame or matrix, the length corresponds to the number of elements (not rows or columns), while for a vector or list, it corresponds to the number of elements. `chk_not_any_na` function checks if there are no NA values present in the entire object. Function | Code :- | :-- `chk_not_empty(x)` | `length(x) != 0L` `chk_not_any_na(x)` | `!anyNA(x)` ```{r} vld_not_empty(c()) # FALSE vld_not_empty(list()) # FALSE vld_not_empty(data.frame()) # FALSE vld_not_empty(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = c(1, NA, 3), b = c(4, 5, 6))) # FALSE ``` The `chk_unique()` function is designed to verify that there are no duplicates elements in a vector. Function | Code :- | :-- `chk_unique(x, incomparables = FALSE)` | `!anyDuplicated(x, incomparables = incomparables)` ```{r} vld_unique(c(1, 2, 3, 4)) # TRUE vld_unique(c(1, 2, 2, 4)) # FALSE ``` The function `chk_length` checks whether the length of `x` is within a specified range. It ensures that the length is at least equal to `length` and no more than `upper`. It can be used with vectors, lists and data frames. Function | Code :- | :-- `chk_length(x, length = 1L, upper = length)` | `length(x) >= length && length(x) <= upper` ```{r} vld_length(c(1, 2, 3), length = 2, upper = 5) # TRUE vld_length(c("a", "b"), length = 3) # FALSE vld_length(list(a = 1, b = 2, c = 3), length = 2, upper = 4) # TRUE vld_length(list(a = 1, b = 2, c = 3), length = 4) # FALSE # 2 columns vld_length(data.frame(x = 1:3, y = 4:6), length = 1, upper = 3) # TRUE vld_length(data.frame(x = 1:3, y = 4:6), length = 3) # FALSE # length of NULL is 0 vld_length(NULL, length = 0) # TRUE vld_length(NULL, length = 1) # FALSE ``` Another useful function is `chk_compatible_lenghts()`. This function helps to check vectors could be 'strictly recycled'. ```{r} a <- integer(0) b <- numeric(0) vld_compatible_lengths(a, b) # TRUE a <- 1 b <- 2 vld_compatible_lengths(a, b) # TRUE a <- 1:3 b <- 1:3 vld_compatible_lengths(a, b) # TRUE b <- 1 vld_compatible_lengths(a, b) # TRUE b <- 1:2 vld_compatible_lengths(a, b) # FALSE b <- 1:6 vld_compatible_lengths(a, b) # FALSE ``` The `chk_join()` function is designed to validate whether the number of rows in the resulting data frame from merging two data frames (`x` and `y`) is equal to the number of rows in the first data frame (`x`). This is useful when you want to ensure that a join operation does not change the number of rows in your main data frame. Function | Code :- | :-- `chk_join(x, y, by)` | `identical(nrow(x), nrow(merge(x, unique(y[if (is.null(names(by))) by else names(by)]), by = by)))` ```{r} x <- data.frame(id = c(1, 2, 3), value_x = c("A", "B", "C")) y <- data.frame(id = c(1, 2, 3), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # TRUE # Perform a join that reduces the number of rows y <- data.frame(id = c(1, 2, 1), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # FALSE ``` ## `check_` functions The `check_` functions combine several `chk_` functions internally. Read the documentation for each function to learn more about its specific use. Function | Description :- | :-- `check_values(x, values)` | Checks values and S3 class of an atomic object. `check_key(x, key = character(0), na_distinct = FALSE)` | Checks if columns have unique rows. `check_data(x, values, exclusive, order, nrow, key)` | Checks column names, values, number of rows and key for a data.frame. `check_dim(x, dim, values, dim_name)` | Checks dimension of an object. `check_dirs(x, exists)` | Checks if all directories exist (or if exists = FALSE do not exist as directories or files). `check_files(x, exists)` | Checks if all files exist (or if exists = FALSE do not exist as files or directories). `check_names(x, names, exclusive, order)` | Checks the names of an object. ## References Wickham, H. (2019). Advanced R, Second Edition (2nd ed.). Chapman and Hall/CRC. chk/vignettes/chk_diagram_II.png0000644000176200001440000105150514743771477016403 0ustar liggesusersPNG  IHDRSfтiCCPkCGColorSpaceGenericRGB8U]hU>+$΃Ԧ5lRфem,lAݝi&3i)>A['!j-P(G 3k~s ,[%,-:t} }-+*&¿ gPG݅ج8"eŲ]A b ;l õWϙ2_E,(ۈ#Zsێ<5)"E6N#ӽEkۃO0}*rUt.iei #]r >cU{t7+ԙg߃xuWB_-%=^ t0uvW9 %/VBW'_tMۓP\>@y0`D i|[` hh)Tj0B#ЪhU# ~yhu fp#1I/I"0! 'Sdd:J5ǖ"sdy#R7wAgdJ7kʕn^:}nWFVst$gj-tԝr_װ_7Z ~V54V }o[G=Nd>-UlaY5V}xg[?k&>srq߀].r_r_qsGjy4k iQܟBZ-<(d=dKO a/zv7]ǰod}sn?TF'|3Nn#I?"mzv~K=گsl<b|_|4>?pߋQrib 2* (Ѧh{28oIyes8';Z9h6g>xRx'b8ՃWOϫ[xn%|^z}%x cleXIfMM*>F(iNN)0%SfE pHYs  ~@IDATx]{ E&ISP@^UTPP+"6PQX){{dovowoqyL|3;WⰄ` `0 A `0B QPMfA `0 A `Pa<A `0 A a*"A `0 A `0./[z!ppu 8nM Q@RtJ!왁r|?ө3KU_P}[7wB y'=:  3W @l lūXq(BdL3YH b:c[,>"X\ds {@ه-ԭ,1צ誉y+ek-i9sJ?:ww@@"ӏ`qnݱp挼.dQw FJ˻*@1#L֦&A !i2ZeT)+賈`Hl XDA xQE# !v&LoA5+8=k|iA غK&#6uց5N"IFNt oA l tjԯ4g l0p2k*P0^~NBĜ略j"ml\ haLl@GrLdD5vZH,t?3+]_E g9Mx.\](UTV>irf)߈߀Kt~И~o8~x9>,|K4h3"@=@bZP8|N8pRԾ",LYCŊ+p1u/J. *GSO=<غUtB<G[(ۚ:uj,Z(463X؁bPN+GJRvmhlJlt:'sU&n(C|x{6uv::hcI$φ@\SA a#/ZƁM[nk׮駟m۶*Or+PBسg_>y4iҥKٜxUsoa]xxxVo0w3W+5o}ٱߓ}y^M #|TI>vMb^}$X< q?>O xsN}YcTd(F=X4n8TV ɨPBzX#+G 6FJP@v5tuVg[5}hM ?~i)`(Flqajݾ/$NlÝdF)M=3,X :s(QoڨiӺu)=߿4Oف=JˀN_I͇dbnȑՁTl SwE D>|;2#}ncr(SD Ȗ&" `wBf~4˔)._P9襗^ĉ$ 2hѢعStNM4 3gի'Oԯ_ݺuwYJH'F\btUa׮]ïiӦȑ##<4hM4q i63UGt0zh1aW b`Xcq*v1oˠi~_/VL}ޖY7,|a|74>@x<+<߈>?F.QU%$mkn0&^b2,kAȺ#v\4\XF$W6^\ȣ_~s;UZov+WDZm̙0'A3,r+co+Xi jeu}մemX_ii-KyNYUǛw]kFLks_:wZV[[ck嫷T/Nў=BǣgW9#BME,v?o >nYm{X֕k6y @K}=-I7\ E9jŲF1U?"xҒ%Kܒ^u#j_Q޽{x˗cРAn׶mۆFi2Iǎ1vIlDmZzk.[!=zO<[6WB @Wqj@u8Y毝å6/rEq5(r6׾8Bs`@9[hѷzm2 P|6$j*92_#qh `s@?Xֳ1n00ui7y(: / qJӅ SiFgѯGO](pٵPZ3f>R/srO~ܖ-[\Iv 6uzDgͳ vAhd+2.kGU!(V@-~y#+gː=[ԯS"r t^g!zuReo3{6L/_*ϕqu\_;:dϑ-;0vA_s1\0yM(vRxZ4m@"W".bR jJBWe-Q$ f!Ap1,VwN0 v:uireO14QŀZe˖dg 3z1bu-@QdˇV^]{%X B4d M }[P(zDwΎ%=e'l<9f9'_:̝XL6,z?MۭsgO+7 QĘ,?7kg]9GX8)$KGh۶R,*؁8s&>p}/4u_毌#?Etgdqҋ30toWEQU7h5lsoYϋ&zۀm&) m+pӌkXyE>7A8x*UwFxLV5_L؎UJ?AT7+1{9*] `4],}v4qluf/dȷlj@8 3d0O^l ]l 0i2B^lΒ9tKىZy湶K/֮]^V-sTP*UR[\0Oby_$_5W I%q_i)X ճ GҀWJUZ i8vOxp*wM\tQ8-)ýV!Y g½KļϽlȜ)Ȕ7BY0{n4}v2>r[ \&*BǏ-, O[(̜Ds1oЭUI :镯V~?_N`ӆA^oף*DڕXJx+(>M; VyED\,:&fmtbF_͕[fr2zCؾVmwFO|,#3C;0F09x!jh)j0Dp;H#_ԺukdΜY JhVYʙ3RJRZ;eÍODO5ܹsDrts#Vpf `--k?y%texjY)ՅedFOm#7TͅĩVo֠-<{HyРrTT6|b8rOz}֞@''t\ŧ4Hޚ}qw0c{!Z+Ck"?X'!W+@DT@mb,F(; M<%MVloݱDTC&BF/JET;²%3j7DMӗFVS t*Aj\7A ȩkx$Z}o"5vԮy5s9aWfY焇b"eQl.$Uc\*q[&M4_t;ћ $\fR3wS8Lѿ>CY\gL%׳ݞ*}cJH o >∐㹆h¿21[ZPú>\k^~wQ}Tb 2iu5"6e.ϊe5 SQӢE0nLzܹs1qD(SGO՜9sܶYfGEIҴxb\4J,Ka/2M4u0>WrRUDJgS-JxdL|VWZrL f]ykG Mg)`ɸfH-5~m _$iO ibhxӦVχ%&XAȑVCD޷5,J ח;c6|CDp)9r烖Ջ"iХ= jHP7Ҍ'/Vcl 1!MW =߬l CqZL$D ? 'Gch<^Cl)RX"8?Bk7Qd@ Er2okˊ0vO| \Ggk="hzw_O_YRLܐ/?[C֪IPk #:0 IIs mV/܏D|1p*`#'f$ iӔ@YTp -..kAnӕ@ySWս2w??!2#N:GѰA!\i YnL1v;goR9򭟖~S#"ϖPkY2}-u<ǰ%|E7f+6mM2uZ6"rRD %E'L4CL'9Ga]~ 0k REIᅬO>ׯ_ǻT>Uވ|@q%Vn] W|L7(G2TA~|ij_7턓ʘ*9N,>Zq_4wR hn޹ ֩eϺ6-VS LiuAmY~HmDj\%ZV˞* > au?=!(,\v Y'_2Q@M¡>^#CGD)pZƢ>A$B M?OjOv;io{Ur ]nPf~hI1[&c;BPF>ׄkHadȆJ)T{,6>65|Dphُ͋טUя#/ ̛F_a,YRpU&R"dY5{yuHܖeh67o0v;)(Pr`b~5+t)lWJMq 4ūeG;$Za;] VÙ7 !WS&H\5}}'6I_Wrڻz?xޟߩ"P/&,8荽J~KJ..8*!kOK|2\穑~H"WΞ{ػQ;7,ۨQ5/,=6Ec[S]+Q_t(;Rsݻ"˜>Uո~ gMM"Ͼsh\!ѽYůpڬ=H)fy\M"RU29vQ=6rgM4MYݲI*oM+'NdT"Qoeh{W>;OPLYX{!sbBha2ZQ;휢 C gQFxFQ9m8ވF .4jJ%wvA*){-H|c/~AʎH3j*+ܧU8rb`@MY|X1lX1["Г(dkv?1N4I~fۿѦ +M$#SLor⮴ӗ`cg9ek՜[n+fQ60'3-jFIzϼ01Ҥp^nD/z~$=q;Ր\Lu3<1[8ybRaX,fݖI(pgM8s8w摔8ERQ[to _Y]xk?#Jݻ*!c[|GFnp)Mz=7/^ǣ2@grO3(KʕsHljE{#V3߶IQe}~9+3Cs ,)f4bW~^b4\O3^<~Qdp5ΚJ80un\a<+G/kimGq}(;qݩܹCm{1?ޞm(}TDQ;g7_N{yIUuzʇo'M,EѹxG#Uq ;Zj _$->F@4ѹ߮EX:^ &DE.XAODb1]rL*CrK'Z!>'1娍^un_Z _RMLJ\rEk6|ܩScZW]ka9iӡ2ep=I뉅J>(hylfoVæ׃b G矻1׽ɚ52[|9gϮ% |/>cTZ5 OF>}y^dP T:0NVXzJ'ʠ_}[.빰[xzrE޷;fA Nh)ds3.Z*OSŦ"!Q{Bg͢qjkg|B*+۳ /^hBf*Uwb=g*5:)f9-kxL?qJjض [e@ZL|V>,5  x}K6]qEuj{l^t z^lTXջxJ|x8k'?mV|l9/W՛x?&T d3VAW;u}NeQpϊ3eKU`kVt?8@iv1/ *24q|^;}8w7^oG38aETs|6ky~?eֈ&VWf|i/^xjhӥJŃ"0|tqV ?@4 P`sng  峸c/^ľ}ʑ#|L ҭ[S$Ivm?^'N#G@3?\T{)^8º-|N\miA \*g-LHS+$~oF-@zKPyZ"…6w'1@,)ܢy|Rz%9k&G7_Ck9أoFx/߫C։ msO [җ\L*i.l'xfs%56tjN3^DE> 4[Etp2xg:_"~[ExjLq"{D^;M؊_*[bO֠G:O~шU)c6_qne7D3D4NLD*`7qUIdM yFnP." ~CBQ\jRmLJzb>d6ŴpǕfTI(//&!)Zw ъ@>z@т E{(Skѝ4iRg*XPtqgK,<aͷ,udN.h)^sjo9-)m}ҎNe4GyL_tP T-瓏4?aj5RwO32DE Aڏ0iTt5}i#>[=0-0+|f@ځWrRJ,>@L"b{Yf=Ш;O-zZyCB㶫<ɛk8}=jO HhO|i}ih}3<˙s@d) ۶o.|g0W.Ka;w`RQ@4]gF"+u~krL70#Q6m"=&#Z=PR7!M,Μ LGRD El'M捼iuMj=4Ԕ҆y/>yYΜ"@Y鬒a9D`6 *1M۷oGÆfO/30w}j;#-Ze˺]&XW_Uk^{ W\ZMUv pNgy|񒅬T)s Ȓ󁹒ߕ i7wb3KA D 7“/nF]421رceEիx g \xy %lˮ]\͚5K믿xC!7n躦5o ϰFrAUN)LD7so Ydt%0L2kJFj  1@6y'\sY|B/)YR1]8?~O?k=JaXiУ> }z&c$-Z"E`ĈRkm^-?2N:` ;wj#?DҥB3fP0aBHv$Y?|\J p|@c  Fn=.Ƅ)0 hE 3^#LE-̯6XPGΒE}l24jӦMZ֭[j2dȀ1c>S&N\l dL54m BS ``֋f*uh@؛<@~GtIT5wʕ+ݪ2e ^x:uJ #S,-C' s;wnPֱcGp'xB4n޼9N&Kt!4j}W/MC4Q[Nv*zRդDot+1 }|  pe &9n޼e?}+~ +iPǢEVY$#0ݻզ{peb+ɓ=՚7oJ&%hkȐ!hr} hiH֠|L2ӿkm۶˼e}s;{zOL"L5'[t,Mcm1ъJ^ٱ`bA3Lzl$0z%[Rz}hra˕+Y*mϒ%Kf B?+*P%EʄrJy={"@TR*I>Ijپcǎ.loΝ2eʨl_U ֋ܻw‰,x#j¹J+vg5ׯ_̙3ѤI=5d؞zȍQT_Gs'B:u7x#2KHH^z̨1DkCFJ…U[|Al\ۓ<ƃV?ܓPSC͡??vm6RcIԮgjFghQ;%֬Y0&$#5$F+uϙW߃@ϲ\آÇFQ^=g <Ddrm }*_{57b*Ϟ={,r-|h">b(pD&3iׇ%!/Md|Bc. G@iꪏ0&!9g]v-kժb/Shذ jE4f4 暖4[f+/[%?Ӝ~׸S_'~|'֩SG}{~'el/Y%m_khC΅Eyt(koc3J㬩%OUkiA qgDIrPr@AKNJKAG%栟>3ԆPTpE_(x ʯL8gѦGBW}98[Wt@x_aXi_q GK>MzQm~ĖK=pD}Vmv"4 ,Á;{h}m.|8(3FA=#ڟ_Z SN4m(l8!t1'S1UÛe"_N´nZ9@g(X|嗠BLhUY@YԦsi ZԊ?|Ć"E6_LtU &w#ǹ1%y=C|vڹ&RyuwI* |]Wpt?=l0b)\j4fb IBQjժ{ͼ| >CfyOFjɃ~9<#>ė}(F<HY6ms+GYA뼴,.|&BZdY rֲ 'lkpGI'K>,BFfZ-ยƉn'IW>5١/#BҖ^&T[Vp"(^hԻ<A"x@V}wI"LjY1Vl}?K/)-_vvOށ.o@|ύhdB;#G|DCiŢoAߦW;x&DZ{B9/˱^YDgsEPLPK U!W!c8ٱ}M:g$_b@!Iz-zԱ }{$R#BJO#D4V?ULU/!!¡+‰z2]&,xAc&Bi;FERXO諾|.SL埯)慮;wtjRc2f7 ̏R;qH8ٳcQ2 Du rOT7 }y>A p:Ll6);5$$( tUqƏkq#.4J? Ҹ#83hbuePՌ>ƃd4>\q>h41a&4ёy[X/MbHL%qF]Q<82P%7g=И[mM16m(hJ 0"'sP[C 7\;Ĵ@Eind "[rHfJ +ҤΛƋ&I&{tIXw귗㻑*jHPn@p U$$=feD_4.GĔZ/of'σ,c4ϤI&o7N S={T' d j)SOuDJwKvB[Rq]^Օhb2p)_vզ/1 SYD=@0u/x ٣$RL@*aYOa(y}鍯4/Ͻ7}e;× i<}O&. 8A_ʞ8jAʞ؞7{L}mcNfp)p*38.N!$UMh$J SE+'9qk;͍21n)(uzO_qRA4JhMƍ9vM$`?f߅:)L+pT,N,-jURׯ2&&G 8KMZѬk!<_'+eM.>~byY0^lٳ@ xTX׊ZN/a!LqFC[\!M'6iq8S!@d$6"1K4}d(p jJu ySȢ'(lO>/ׯ3 pZ R+'"MzS r=(O} =5_i|Y2=К2/]b 9NJc=(ZsE|Q:tJqA.H|p=`:CReT}a 3'!} l g4h:,Pmia ,B+*Bk*iRv%ܯ U`tsf0O:Ip1okaH~On~jO_:PA6x4 %8N4w<4-yqx9WSfZz `K!Dy6ij^M%GK~a77ԓGw 4R #o}[i}=`#<&NPLgU|t^J)ڍ|&4PP$)pmYsŨUojY?5i/ p`. /\4^S5T`X\1I͹`>s,I3 1]umw>]/B_JA|i )WobH7^xWg>޾lg=y](~vHo6ť󀅩h98FTҾT;2e)H%#PA \RTh8/Ґ8V] d@,QF7o[Hāw,$a `ҲT<=D{)GYlt;mI<#{1lYGPD?+kS F>`2y޻:x^2AE@7o;C=zt Z}-^h˹b 7隶Lou:<']vވIt`ݧdo#0D;VF##hVh(򥀕CQ#ȵ@dTAOI7 (zVLonza@IDAT}$UBK7! bj"|1ss=Ț>Y`K_DM+I7 A @5S<-Ɀh/ dvpc1ZDi.MGzJ}΅hzHW3 zF7|y Ba*t(*] Eӣ⃡SV-f z-ڥܵF7nſR.o֔zɉIav1 H w u$LsFAtɐ5Wj|?z4-k]z /;iie++Z66r"Unu _r ,?ܙS^L)&CIT,^00|<?nE' i|ZA `0 @f*J: E n'= 0ca&51C 5$ M#?^/й \*6WvaѴ{Xz/o%2 ;r&>t |?NڃJW>e'&/?؝^KA+QRrfrFߩ]>;m7:Ojbho7tFUsm:ArGBSNs1a!5xY3n8q*v{Ŗ O5s*1#yU5]1iA `0#v4=_J\74}}_gbg%kO<*foj4zzɘhf1i]_žcWq5$͐ 37EmP*F¥j)COP(5^AaL LK+׾ KQ3/>T3VQ[ *_.)IdxKGS@zŃ8@Bc4F1:' My A `0B Ny@xUVuҫW/bE̸sF3@2Q|fnGYZWu`xa&7\s0z!bJʔ; Xb[&qSg3{A `0 "-Pؑb{Mk֬A bŊ%}fi&,XPE߲ ӠA̚5-}D… uLj* 5kզ-Z;wԧfoC ^CG(ٸRxa`%Yb"=;G?>z#B'="}LZDc ZT٢R&OTImM/btM<ݿ0*eMP9ְ͜9ki $z| C?%m'끏~^ `t%B;>|U~>uYA>@`PO7>SZ #L1:5T"CΝ O6lpZ}NmرNU@__6\؜S%cڤ0w>R¼>.䏟-q DF|>u`[=(wтmYY.zb #ۧIA `0 Nۛt4/yhI7^d^|˟ץҥ J*eBhBi^!~8z yR9GmJYP2o45jnݼ]@*3h4@NsS A `0D 5S7_ta_Jo߾=?~\-KJ<ᙐw=cƌ>|j ^[n}Ϗ`:tfJ- fp^$g9P 7^1GԠBt1c~{i3Ϲ1 |D׀>ZCo}㤬'4ߐ(QwL78\.\Nےȱ8s>e.]Kܾc#6}:Zq=LŇ箏 e X`3gNpN⠿rY}˻|?@B]M*zi_. q ,4d,pI>dpP"[S s2U U0o%u% s58~: .Mu[SܹD(V& 心F7QV@I.rda,C!w Ĺ 9 #L;PHxz{[t P^CBKN,^ȆA H&oX R5X5>MOe p!' ($7Kr V<6Dk׮I8@,ݐMJέ.R"{./Uɖ]6ynF5aKa*,&&%|rB>@ߞT)Z?j8㌹1  fearLXȒ1 *fSKAUM%! U0]5f{q-Y:kKțh46Q緐U4۳p;i o.' ~|83gp,Yǁ6C;g3G Kd=1K=yځD#=kT(/]yg/P6kBHO|/^4LaethvJΛΝS-Y3D`hY@.Asc#LE S@4|"!w>אA pЫ?C25kWH;8|xe;XPA 6ݍ}  9b(!Ԙ ]œ"4LYj=8{QL4U: d/%~YxPphimt"P4W e%kZ::dx'pN4b›|?GwY7  | 9.\0Tm3G% d U߳FwF^|E~0~Jd/LF%a**L2wh,;́WZJS!1]%&Ztf CeAgRC"Q-Q&K$4E{8xdg7}_To^PV vkhLk_bW .`MT3?_!дPGLFP/e;S 0k_Ŷ@Q1A?&hK44F!&DܻCP^^jy95дH!@5'Z2dGȓ/Uy"KF,|Ҧzvve`+*r[X΁C)l A rld)Y6ԭ8)#HűbO{` =bq] Rk^G/{gҾ5Ӓ$IUf׸вg}c ,@:u xT^u]g(QҼSY0D l}ERܖf,&mIx[*r"QW2ȞY?Q %^"p,'Z ,>P;IYO}^YD:>)n|5T0ɱٖm4RE.z]}C7BBBC;wTԖ-[P^=,Y?/رc_Q͑#G 6̖!8q"۷}Xp!<pk;9@E 7Vցno˚#?wA $SdD28edUp?: 9uvnagH#By,+RE.;2We#|c !@a$sH(S4ZsL<& $P^XTō aƌhܸ4$)te͚ՖR[jժȟ??6oތUH~-LΫW~<-+V@|PtiF_ŋgnݺj]7^NU0%ףF\3u o~/,SdrE!ಅR(E?߳B!'p#@39jx}U8xiUi׌)e7)9pI&'T?M &M`߾}J @MZn j(0ߢE0m4|WJ:z;|%H!C wx饗T'Oe˖J:|0~mt5kT裏zoSP3lC8T:=} w&A `p֏3҆ Aլ#5>NM% HҩQ + Qf͔P4sL fUBتU\~k׮U# NÇW 4#Qĉ8tQ3f~7]6ȏ|w_~_ЩS'Pb?'էo9松rO7)A Gvbe"$zuY͋>'UuN:(g_T ~ll~J 1ӠeȕvPi~Q|hnWT`!(*hGP…X-4$𩧞R)qczN"ݏb(UJWÁуf4Szux7pV>h|F,ҥs SF y$r_(ߗ22=_~%4hrַiPJe[OfȑJֳgO堯sorʅ 6OF*˗/L]Le*Bf:?s5`-trN6a:?+VD,Y՛c@ AO$ w]dDҠ]3f)PN>9iEAQF>pM9iO 8e%o3'ʕ+S4 F DA_+~?mV gO|P-TK~e{W g' .K]u~(^i"⪍]:{.\ ́; I,?: ѣ2*[LvI~ǜ%dQ=p`ɋA Yk*M61&Nt@DAZ*fҔtN3f?*F;ST_ />P Gf `.]I_?~=:1b+O߾},Y27޽{b8QE֭xLIM6)+<̓y$]N.O\̷zey@:5}z[r[Nˏ*H"1%uM !gT? l>{Àw_ZXXAY4M֘2dJ?z/!W:rI&W\'mKvٳ],8Cɏ$#Iq4zh K͒'|Do5 >>U:Skb( n(QXʟ?w-ZM( ,aD@Q b~:[ BNܓbvA!=]emԙ i)O+Ac<rœa />Q E-V'-ͮ5ut-`R D~,lci|{9sb2er7={vegVJ_恜)%GXjZ#/z*ďp]qm.uoVLu>ȗivҾrlΛ7 bϮȘ9̇/uθҏ&L^uYGq5Ul4yw!Vuus0a8{u[$c־5e~[S>k ܽ)^6sjáB] C%76Ǐ`w yQ?'{tC\BQߟAqK^b|9]Eة떛A fROߎq`J tL-\dI{*M?/`!yׯj䀈&vzB֬YcU5G4鰾{ʞ@tnO>28}8Pcd(x'\.;sln@Z0o1N`i['EvWlr[hOVjZu2kh$w>)TNi|{V`FhX1ڠko3\w S~p\<׹,Z40U"^ylTWqVmtaJד8e\Qz+d:mA ު'Nx6lIWy@xGNߕ/P]M3uY}- N֧7$0!!!*^`EZ%ȅڡ0wI_zTy󆩇7\}~7U&ޘ#5JzcOϫsď\b[ bz{ĀI KOI?̀cĥ'Ķd˖oЭ% }Ξ%W>Yv?gW@lxv~sSF&He/>Mt`_zHqw!|c1ۆnNZ6ӭBerd+ջ\4L;苍SHGE~N4f@RuL`nϊt8Pk)HYTRC:NڬYTH`3CːA N`(e=IPxJqθ[$?q_ m V;ǀs֟U o=sę=;p24{?G! rl!ˊ SZX_vae]~NۗCDcoMѩA~[ uxQ:\"3xȕ-5Vͅ:e۸F<nerc}TaE޸4( \~E˂AرõpA I&nDW8t_zȯvp﫼gN?v: X=?8i$(vDf=mA;%۷QzXǜ0vFGN_G3I/csa%q܂/ʾ6_s/:*2_[] {̈vy+6-ZDMmJT0Q[C}YrԕJFwQ\O;X,q[G$n^Z3avܰ߶ߊilڦK DR8KSdn0|b`^ } gpOP`4f\{PXB[}ԥGj7%pI^8ۮ[ BݻV~# U\٪*UjrE<&"=y+>DLlWeͰtp5a)Ozs6 CHn/Z~qdͨF3eY\ OocԊn6rKJ%T(kSMԩUD̉`y^] z@]擬X? ˂+B~+V`r3*b!caԬFF5ˤG>[{6H0hGT׮)>WOB2.嶺Dnj]=ge <S0OI`Etpg¨9A A#Bqw\yyu.o_zcrr+ ğ)-uW?^]X&8屺;dYiiiO^0!YeH})0rE$EڅW>s[5c2,$MGy0>-Ǡ5D iV *B:*ѐhTׄ nu?ΦU)kAt Y:n=c$ {y[iS_B[^q&J S)EUw5MFUT b6";TEc2{X,WEgRB!-_oWehf5&Ҭ`ΒUոK?F+&IjZ3mJ*W=*k%AE@SO^oZG3:m>\$``|H&B/v\AFqfACU&;pO|q7슸n4.s3^!=]] $T1L´<X캩 tw-dľ0Жy[ޭ̧4AƯY)(.cNz-jfRhP5zM9hLFEv.d!C%x% /] hقܑ`ϷWbeJqc<}fWH&xE~`FtLsל!c^O4l-~ة,{;"VN/1K}=.bVDB0_=~*dΕʦšY17ZV5@ط#n J8vJ:Z7Y=g#\y'[ jlwafIۇDsd3616z R\O=mBR3]khy\LIn}xg3k|ZJRr*|l̐ +oWihO2K+΂aK˄8N|v̪2XQ}Q;3zPqE2Q9? 4Ȅ ?\j\H/eFoh.HSX1U}Hot9O/^E3Νec="_v[j%Ob?5M2jHr=EARB*Axb1哲M2!q|[|mTv_Yp]ףATQ_YnBm5fR[rkTkAV";nŖC=wXQѠN,j%hԓ%lT3by#E u@,~~}~އXo'07_1+d&FkO<ʒW t">*/{iaI+@CG9%jUZbR8nzGfG-s Yh,pI-vW2%b9_U" SgkgVCj1|V9];j\`^?*+ tp>cƋ,?\?k#w$*}öBF?[6HE0#2vvN*w+R[q_{oRFL$Bd@n`?@EQSE>V/ .rHʇ2ifkdPv.[Yӿc-\iEx(#󫩉8G0~qT}[<& *bɡƗSU[c^yɖ>}!3(ȹOfBOs;k4V^D^#iK*A@Z5v:ȿ A+ohpCZ*X2m:/>/(zFJdaA@yiMkw(b X o7,/@F3.E8Zj$~C$Z(S. V^h$'J2hVP'&/8KEg.F:IsF -N5ʛ%:3)Ac@{#ϘIJpw:YI\PT/Raqb_PT<Eqc :F RȾ~P&ߡu}4$ rs>8+!XSkQJ&ܓ^ֲI ֐C\LGHCM$X ~"ߎuDf#&s=4b:0 A {6+V?zƙ+~J)Q+BVHaC8DodmGLt XJ;CB{*'S ik}߄u3Y{1{!~$5_:*ߵ$ >BsS;FjV 6ttn%k| gՅZ,p>NE p{F-rs,^E}8&sj6sMWHg-lSVFnD/Nq3TQ >(=~Ku>ͪB;3s;pdGڐŁdɒcU7`ֈK1tX V֭[کq !-X}U $ ah3B iFyXKF?(NJ A/ۨ5aǎ[s2弉dNB^0E'$Dk!X£@#H)QR"nD̴漪J?i36)f*,[RQyKTb]͟KNPkghڑ:}h- vrt~"mel}5 Pz1@&~?JOОE}+) z$r`җZSzY/Ѭb5ɽ?^ gf]aH_Dy.H=3T#ߦr_& Y =o )x_[ y߼nMQ-v>Nv@ ><Px*:Ȳ ~w!?Lc2Z+<ZXxۤVT.A#0 >!6ŵ`(m mp)P\c[^p7)m, *V!- Q)5H?A|asvMc1Ec]=^W`.>Xlc:-cˢy{h&s0,SƗ 88aGiԇ(>v @![\F%ǧfЧ܃@V e}iB2fl`/(&E8CX!Ʈ^2Db'Xrw9}hX^~A9piwrS؟dR61. 08`p 90!C@voE]FK"J03ſI d㊏Ӝw N_褄lp‡C|O_FQNHJIѣ̭ׯ_c!j'QFHb\L_?M6l@…uL2H&ӽ{T^|pU(P "k.190775m۶(WhIb9r$Ǝ/ *aJ+aΝ @߾}QV^;.[L @dQ(b x;w͛7*U*:RHC-bf͚xмhI'~;)Ca} .](b׮]0ÀɒDM08`ṕ] Ր$qK鹑!CJ3|}:O":Rp IOVOҥѰaCܹsux>}z%mB\)L2$jB pUt$H1Ͼ . O 08`p0<0A!i8K~L$Vh 5jƍe jAk-^;J aB֮]Ǐ+("Fzb>x}~W!%YnE3fiѽ|ѝ089+?]\yEi=ic}M+sE0~-wfxlق-Z@~-L$oܸiA&h!;XVOZ9yMCF8?erss'|,UiZȶԦM0HR!N6:ʒ%,YR%e˖6cwޮ];q/_#FPzaLߎqv 08`p qJ7JD9vâ 'WٳgWSϿO?4P/湱~X=ӦM vpr#G…(Т`S;zJc= ru( er}!Qxᇤic5j~&]9Jӷe; N"Bk=Sp$}8a` ZƍkwQdT@‡1 aѪk4۶mSI9bBĉ\VR%d'*9G1s/sޗ&Hamfo\08`p@mH ZX3j,O}HŊD<#2,ї9՗~/^l#L 1s'*J3ՊU39sTZRJ[ X߿Bէ60J4!;vP/*C&=&(kC]ummHтpBm;j0 D&$TTR(Zz5rʥ,Zcű`ej߾=֬YcS o/_V[B 9rDmò>ѯ[nBx -ΈkF,CrVH>SaW Eg6Wg鑏o"^i5mH:#N܋=q5bz_#y=S#n2Jdp@q\ԓ<鰇3 qhYiҤ ~I19@!-Xw'"WF!QI̒V(=i=-X'&TUm3g9[}p (<2G>/t%@>|pϦzF4`~޽k_:ug+V(HR^s_4G4. x/_-a{psym1N+rN6"b?uBUX-|'u1pP?WKq")Q!Fkܹsw&tڵk =Caؠ/L>uwTG/}V .5?jժ} 裏,^ǏWheC.4NB5j;' '\ݸqCs{%K(&(dխ[W! vޭκcTaF4(80qCǥc7-J,܀Re&'O8589yQ9ٝ2| Dh"E`̙jτoOՒn pٳgзa08 |MF;7oS 4PYP|Wp;* QI˛7o^ 61}$?(TJsMnB"${„ 6χ ¨|?^;5a~Կl$@"L= rY o[3jw#EÖ&$ u|jGM32Iɘ1e3:a'nfMM 6&'mR^lA7><"(rO>ڬ^`FJEt-8Fg9z>p)q _ej_g0ӖQ_eg ĉ´K=u頝8tJI$.O/'9U͂V2"0eo٬5_-8w遺L-㫪2_E[IaK| ҥNտVҚGF ̏k`M~+{HɅ)nrM`H =ǏW{ZkU~aӦMJhb}HbS(cJnH,mRjUu͈_P 3G3;.]0їDڰ7Z'5~.g[! رV6nwWcPZsRg/Tݒ}].^RXpg5,kuw Y& 䧇 g/3~4E2JF hVxFU%4V5 wL!0!&ݺuSN'4iC_ڣ@S:-U}4ˁG/䊽P;9bE0y{(; ⋒0/0ĸ08JЈ}C>͋hs>AJy/Kd3 !$8'Z{$?xg듂<-1 s6l<"w$GqJKhh;xUrpmBtA 9PRpExADNhQ;{͙3ѡ D̼^jٲ϶ϯ ݣ֚Q4Ɵt>w>08y9p|;xoF|oi_N=B&'Q"Lq*!*ȎX/kn֨}zE6u /EtJmUĦ Rbژ7ۦP4(ۄ\7#1绐wոzMn&-4_FQ]z#|N -s4alte };NlCq0kjYj,ql +,bX")?۱b/Z|uކ[}Q&=[&9 S X:;L>nߨhc'nJ-+Me _Qȴ{M\TAfL;ɛt;73ͳWh7fV:fm/FDu#>?Ccx.eZc!qR0<7n5+ߵδzvcFk{Q y9|+n8xʞEtgduٴFGςjqtm7cL3~R,pNZ v@r4 D~P9'sхձlBy9{_ ;VVtPPcDqwcaԬFFX CYpxv(`s(|ǔAzY0-zX.qOM|0޵xc\"Rn$8DFKEIW{Bd"LΞ̆7)D*}\pڵEM%"\:rǏ+tSEi7iU>ĬW͉ BȜ>1l-r5qK@,Z& \)$ƢV! iS3L*>GiX+@j? ^F.Luze0xFYRMc`:$U?߈FXLaQ*_f^f!>5nNV0ͩ#y,Zo_Zݑ'"H2Uj_,]"=?O3N+8}_/ nÑeX8 DeN.hθ X\IQlZUzxe4H/ʕn(%ΕfTsjkޛx{TD׮̝{OZp?>"J({:) G$Z}qDNק/>Nȱ\k3E4 9=UL|elЁ ˷i eʥAM:P8\$61/^nO~y:kY ЧeNWOQLS_\Pߓ[LH*FBN=P>5rs⛸ ܂#%ot}'~ H+l&Maeߖ^t:7EْVgW@+Isʿk>9GGxDkN#r DQF1|Pӵq \Ov> cʌj|?#iDՀ=%z"zDl.I[(- <@8u_*c#_UGWici./>-|7xyx◃xR$rSwѼRUc "ѝ;Yg̘{_Ɇ bDY}RL(RUmxFY!ۭ )R_li@$SɄy7*:7ub_+X! ̮jȔ3˙b Ach"ĝ>e)x$k).{6+2P}o$$拗EniZځӚS,Cu;nF\x`)"* [| |]S/08ј"L%،SշunkcrC N}FOkZY7ͥ,_ +7}ws1tkM_i[hvъrT+9`> Gl|2.:tD?ҩźI"BY!-cB,R|o/ɽ&~j_}e")񃛹*S#:Zŕߕ<1O)? ; އ,yYкix~i'D{L>0rTi'OamqAĿn˟aOmqi'(Zt 9(~TP$GYK)GϖedUE EH 288dkX`t"1xЉe5չvy6[שGB~=2#eaO+_D{Zd4;_}ڱ$%dСf:5ch*k]&PDO*0MNPY冺E_Qv B"n[;k]5 {Q5M zJ%?DGQXrױk(r",9~]aըMbFP9F<'ϛH'LQ]kr'[_N9;,ڨ;MHQ|:2K}j_5 gVɃ R]+WN]oڴI K/3fDU7l׮T _5l٢""0u^7tU"7^HHTbtluo9kKDOa_K~8"&rЈ>T}]?:4_rz{4s{ȢWECIf*VN}C^y.Nq,DX` #?0JRz_&UPSI"9ۖlŬFFI(V?_5$B ԒyzҷŴ6)򥪝kv EHvNڳaIGEstd)%HOEMI&M+#]@Y%G;(kg#]^ u͛ďM("VO׌VުotOuɟVW)W:خJDi`PKGrR*;(?0|Ylf H5dTJjJkصqV4ihkVr*^25v+cʗo2 Z]6@)ѐF A#獐{# RZ> baV`2]/Hi1 ?Eg Z,0#{sIY/%Rt|؎y0?@J,yF%KD4sgta!T#%T7׍1⋀LSq߯X3~$z13(_0O^VE!Z}{AZkیrX˜ i!tH . l:edeJ6Z'\Z.bxԮo޴ pL|__>ѣGAy׮Y@"偕0j:36"u)VV;RX,Hii%6ii>Z&nv꟧O-B91w/` ׄ"}522y;!!G)8M!n˾_ h/mGi~O_" ʏ3FXV(X*~\}4I~:hD7 LVB$b!N5/@ џgHOqH:ZApQ8qcL摨]Vx=LQX+GDk:*ij2/m!´M4%iw1Rj waķ)Dbr4^*#(A"'Vn*~fCBW)l5]ު[ְ[@2cW^δ'G3v DAǔ} ֢MWUtB%P:Gu3a(6/CX/\ЈI+CuL.[P-ZQRqLWr pVwn;"'rNΈUg|/wd!WCgTzn8) ?3& %? A֬Ym:sȔ)SAL".'NlS7_xʄ#1mo] ?QD{C.GN ;p7Xʂ̈́IG-;݌8a` >СPk:` ObV#HG.;es?NY =MYmhd!ZVK'~V_n3^00.u3b3hl]&yWMz$2O̚E=1| o&Fs'T>fe^ nvV #FzV-{ zZ7C3 OE#Y_ ]?S>2/^^?g˶2Nk.WuVSڑ@6c} z!I.ܼA6^}I-e?:^x6@NxU|%{?ލBÁsłY| \j4s<|rm H,Rn2!@lM(WG7h.qQ`%&A H1ZO܈>>>WZWɤ?h8m-n#95 BXipKiTZ:b1e VRŊܣ-*:0!DF{*,QgJ#w ٲ 7~ 'Mc$!Hbop>Lԇ\]%0}%D&(2hȁ{KuT&̑`>0nhɁׯ_իW62׭[bNHk5800e9PH&z`q{7űaˁ{!@.jcMʗϰF- /&MOHG|)|8{AT ˑ#MD YK.ԩSg (005`F 0I.({ҥ6o<=Ӣc'\u4CB>[Wŀۍf "ȟ??&Oh1ڻwڪ$[lx"*T7"k֬H>=;1ɞ=;~wxyyaʕ`{iӦ˗qqT^]6ؾ={hʕSSٝfǎ;T˫Cknr0Ç駟p ͛%JЍ858`߰"C +N8@4@ϩ&M+P&$N /^MьDܻo#76 25+041Ÿ] 8ံ5#gϞ1cXQ{Dv?رce>}}زe 飄#F`8pjO>AtpԨQ -QТŭQ?~ `6l=JQb֭[+A,! S=YČ-gD^P Z M6RJ6q,a)\gd ٓ wo!Js XiY|L2$)Qi~u4)+Lq 8ErM;r`XQ_+ɓ']jBV> ɒ%̙3_~QƦOk׮)֥K@!ɓ? WӦMq9%?}qCJ*ضmX&_#iɒ%ڥ:޼y: yf%.!?skE9BI86pdtr D˚"FoQ\+V ݻww}n qbΜ9oa.x8e̘a&ςgJXŋc8}Z!NƄ*թSSФtoJqg˗β9p˜7oj} D"3gN)*HbD]˘1cv7nK]tQ0@Gi"-ZTum۶} AM,;3`~Q"}j"@ZdA$ID +V']4D !Q0ɄXpA N+@N+"6?Z59CTpb"~oذ5ؼa׭[*޷t,'b ."8֥#=!4۷oWs/1PVcF 4@H9 .O8aQ,^ԣG# LG-${m} 0`He˖J9`D+]yhՆuI| ѯ_?paL2zW-_\)֤Ii ;%Dz*'O%ʛ|e2 ~3*`H=CE>V,p|{{!hjwxGefE"q* 1h kJϬ*зr $~vř<-.Bu# 6D? _+ oLL^VbȄ~5_0?P0PBx~<g{#@Ebsw7=I&={ 0 5Rp.=ⅿ"_ @l\-!kV07"ŀ#hC' *jCI#(yX9#.^P;wn4Bd\ti I-´2F ng u'#C6sf͚*Xy\Z8AH=R$9w[n*i>(Є Y1 qЇp/)-=#)GeُB3Wۏrݿ-~iĠ*D ܹsۮ_RݺukE![D̩Tl0u*pKL{ 5,Ln Ύ5g g%F5dZl`xVYz˖T~sן_8; {{mNU*pTLcXag4Gg+-P>R 8{֥oakQ8cxdjR !(l1ɑ`CH"1oPPs4s<C(9uРAJ`ӺuE#"E*W*)j(ʠ#gc ܐ PBt?;fph }?fY˪h4:vGK Ӡ%#2m A ڐ-9!rf83 az Е]ZKPN:)m,f͚,%P:A S'.1>K$ׄ)R8"oIJGZtG"CFEm S%L9钻+Y\pyitrIDƔ\YkDq:;Ik3H?$-OyʅIAA>jZlJ=M+7Blew?bz,`4o'-G;3eXyۤxUf-4[_8E8JcL*̈́"N7hsQϾv#ل;v,c~̤Ō (#gc tȆlY5N_]&9}].Kg^2}[2? Yp'ύ*Kol\c.$bR^#{vۿG-@= U_HU7_[,KɒAR@}/7O{ M#\niC?k$M61) *U%#+]s~@_JhӍqw\8zMZBi)Bd./r"ah^{{A6\YV_ŽjUF0`d|sU[~,㵠"s[?o-ծmP[K 8%A%^F G}GiwsXnV!Ah4:U&E 1;9<6+Gp=-o{"D+_EgĴ$pN˗]O+_sGa󄒘k.Ud WfcE.Mhs)Mg5N&{75ܚ߼5~Xƾ%n<0yR|Ȝ$6c{RPveFѬnFzB@oOd={S\Qi|WW@Y-.~T;R;uԓ/@)~)&]0 Qn;vsQye(o/'*HLqbH= )bE崈Vwu{|3DmRh4'<9Ֆ'aGyJF? $ 6jz1T[&d<} m 2~|(sNsW 2:#]!%HhyK-ó??kG[6B>J-1y-VJ%` W~DB^vB~HfagDcBQǝht{&U_FY>[43ŁOYǗP.IK C nmR!t1m/^Z)|]mijM=瞣`-h7(evGR;*j̼(J^N7a׽_ 9?)~xب~4>{{ؐ -DTy m}6jMT{FΩ핀lV.SԸ'l6reciu{'l?0. `! %[~7W1e8 ->9bX9oӧGfЦVfw]ݑm^Wv"Chw|Xrk@TqUװL y >č="8YQ`2,Yp]'.mI/W}=^adI2dSؒ@!Ҁ>0Cdxׇ2q(N2E!مֈ$bVb"O)Q&> /F" ~[#Ml WnxrA'=}YCLm8 OA1Zy3WGЧq:]E  rC FdR,񔿔KٮZt6*2Ǘq^t~>3}V jI5*Ѽ|2A_:idYVZ=x¼0_ؑ1]64qPm+H% #d;%PYV~8} "_XQ{RoX'2-X]LL##YCXs1OztR' [ync`Lօ#$SdIc 'imb\,w[< F{M٥NK$̽\FE#w$)2 *b€Fb}&OIX/|ٯp|K7O\Gs^3%0WoHH]w` w*:}J `w+vI<~-Y k E {WlL1vyD('UQ@H(:VLZwقݏUn %*x6?G1~2(^OWu EMbⲞ;"lϷQm;ၪmwƂ;=kI-x\igQkъQvC{xǐ ]poqn*QV/h;,vt]*Yԑ^]q 5^s{r>ILc>v)*4lQ-̃Ot  *o%MFMߩL"jmuנufY/F#ŭ3e$?%VHx_3-:?1揭vQvf7cABqRCGHop M<+. ̮ ~-;(wݟ(I5#_|~%DzдjZU=ݞca'^AF?^É{C55_5Id<`%A) (YH4(}d٨xZ9$^-nέG<[APIdGD/nit.gMg4+s7.]ŢőS4K/1k yE *&NCcn kǘJ.y:R|KmS/%$7pPXFŜhϟ?fU SCE j@_4cHʿ@8cw[rMKk:~l ?WOͶItϒu=5B BB˄Ic|!ʊ=qKH<R:E&вk6_<1? 7~h!ێF?|eFŇ+R@M^T1I}%-&>u˃I}4{{ r/i@i&?MSq!Zg4uG[خ,k-@ʲܷs.4 eY5on7Lq3EFIGď-׈>Fq"06}vY9w#F4M~ˡ ?G|͝%V .%FtIZ<0WnybĊbF؈&Aڙ#=<(l/6I ~PvʊԿ}GIK $P~u0r)@K[o\*]1TM&፫Khs"9GH#o1o7 4%FLo>S%Ń!71Odǜ:y L /<ٛ&G)WEQ5t 7 Wɀ97ztPyzǠ3s ܨ@)څ ,.-}@~kIcumyV_z~mun73ɹ|,|~x^y,V $|p<-O;UG[n֬^F,zG|-dg@>HXGVɯ_uL+E+_<&D` ƍMkB͈,`:osVÒg/7, ?ʥjylW[[Vq˸8&QJDng +d@f7%&%\4vD܌C1sfYo )C䊱nP4!d ݂2%"rb*U1n2Z0%7:+8q$;/ϋԿku+;O>T59<#M@@R^cW _ヌ!, z0%hȗ5Qk6@OyR]_5>[v qbGL`Q#M4b q`{5/2ƌ;e3k|S+G!0O *YB\I@LT֮:H ~ɘaA߈C;YW 2s9 $u89h8}T chW44CI#Vx >UAGk=^Z-ږh *ԋ*@6YQ@K a„`cɈ2~(KL΅:lhT/n]|]]G|xGBB)\T^eH ;W@Ӹcr&;0h~Y)8}iB}ng^Jr܉ucfqRM ٪*[~ZUHRI%~= `pBRC_K _ E~zqW1=/@#{HwLt΃oUzoVW?`|v yvt:7]A'R46*g6U@TBI}y?>rFBcry%Sŗ%~ ˢ;D^F ]bUbJez(}9ntxxfi\X? r39%>wPP9r)*K㙄'p_'TCћH27nJI{рџh43QjLoicgށn#r)ང͖?ƿ۷o2z͟>3wbyf?zngPLۺbre 2Uz Eez]!)u.FPK-Z4Y8!J(AVK wC 9hL? /`*xzh/[:Bi jBR!٘I>|&JV D9)V, (&}l€{pYMċo*Wx(-g=B1T"̬UbhKXLj1m>HD-G9н+ 8Fz)D1I.Ŋ`~>$ׯ_+V8$ӧT)1CG+`4i`׮]v^xÇy}ԩ9sḵҭ[7Xyi Tv]xS6}xCǥ3πHKE(sLR@g<֏*U0۲})dİCbZ%RP%#f(jpEZ*}*[Yq?r1Tm=m (ߺ4d>Sr]GV*PqU@-#;wk֬QGңGl2=뭦#`-[۷ZUuܰanܸyUz-ZkEggGcg1+=|0ヷ,Y'O|g[ϑcѣ~7jͿ:=zTɋ, /]dCMhĉX`]@3˪Əlƍj_ǏG~,͘1cЩS'÷7۶maÆV-خ%J8;[:c] ŀ}0x&K-U ;vlTu@rcFiS_H(_T+MĢF HnKz/l 0ҥ:tH͟`sǎJ+FsC@22"ysޖD(M F" w4 IK#!OW?%3(]k=,9-&$4˂G *GjYp7ۢP1aߛ>WVxňJfb,X>F|YR@y;`8rщU @Yt H$k7PAIBD&jhG 5=Ԡ>}Z]/W2#wV\&n.kJBMıF4vލ|FDF8}zhѢq49kyNӏĉE#(ښcڵlь3зo_7| )r",yL^ѴRL&V&4d%MVQ+wv.BBo9N*D?%K@@$)XVjT#N_ .]/Yˁb?eXnoFFgҌ/k tdvuը5@5C\ԓ,-QOԘ0\o:ZomPK,[dO^k5LV"XI]d_>}ܹs}|϶sС3q wD-b}FK H |'^0{GK8/,HKpKx` eү{ ϔ(!v%Kq:83]bvIr)ַcPt |yh'>q%Կ(P_TXy1 )j,G_m NČ?PXqbMp_K $$OGi։G4֭+@6m,F:~LkAYt%Ș;F}>R6%J61&1bTLI +wC6'H,~MWF+e1K*G]߻~"e ce7Ici65ڵKg9|R%fE4lrk$&fKFrܶm .țyl#Q|uÍ& }25$IgΜQ9xN %9s8'ِ5^aJ*/_2%s1e=~l1>fM]8F 1B)̈́$&߷o:g- 97j(w"a7!b;7s``o715}´(ycĴ)gj儁иljl<V\Ľǯ.iL~F(ѡQvkV]'pjy=$ImF2<2_)'[%=͍wLj77*K}Q>sP)c2%K@@@$@SiFEgg]ү xBZGjժEXȎ R fZؑCԦ1{/AcFdt*U1ALƭM4IE$$1co.]8|Đ+A f0s]vՆ@˹17eS6TK.UsٳJd=tP5NYFH"*&ctKۓ@_"6@d tj |ߞp;[e-Һ q0ծz(ޅQt4"IGŦ5P\Z{JK8 -}vzy=©;U, gwF6y*ʂniMp?m}/YlĪ-n-#ZDMBIhN+wt%`AfNw8PH|h2e2wUX1 ]!,'8x܀㧙LjPH"Tb(]i3Nښز6 x8,>BҢ0wU{$ x~fĢ~pyl:⎧^'"D7H46n{޳Z(IJ8rH$%.В;zʛeE֘^ʿiѴ/M4jGU),,{J LlIZ=j,s-ڤfz:uj4Bjh4f'Kv'N:샤~ƆkEmɓUjH\nhRxkhL̹f,QH|IԘ1ZQ.LsI3B2'5zi&MFf~m2ȑ#Ǝ9m ĐT ^.uoӜ R*A\ ŖDKۖ>;]~I!L-iL9crjœճN߅f"]-ӳ{XyK[0Jh u ?ˀɍH &|%< q0uc̚y{nyM;g8Ȓ=1nҝ3*N::"ė++R0e`Su!ni#F;Xct qZR(%8}diw"̣)"?2ʕ+4#wH@1j4\߾}Ѷm[a9lr˺3fTxm#έLv٢YdX30Co)Ж?D.Xu%V%<XoC [+YW`$*5 ! a i6k,[X1~A0.; Ѻ }2`]g RN4Ad sctC&c?ǎ-Y r.&hW# V:RS-I@Sҷ4smB\3ŀWMDyA&>N;hn 1&F6-x؆|D>`k+ #wH7TP:<Fp|0>$J O>ދyf1$.`?[traė/җǟ KwM&5[3YTr’lzh8.Ѵtr<-' \jA酗|^'t)m )<ND#{ [;0E~%K@.P۳!4DY)nƌlR@9MrHYKN('ž~ `E._ϚۨWY0k]TyXu=ǜ=<0zŭ̻yšI[AYUl.J9Ҿ1kuDfEqIRcF z`sjwDˑ!-FI Nt %KЗwP?s:qz'6iJP x`w ͠5zKw|,+<29XE|d30}=x6+lcWdUmA{e?yь:gX5(=] ңU/5&M7 fV|+kun>|d-g2e^+yPKWE;E@jıLY֧VwЬhQ=XRji]#,e=\.]t %`)LYJC?WH,&bqR -w`h-M9]UN`[(r5;5yxǐ Ń&C)~;O>DvE~/\$dއ0`NΡcX.f-^; &V%&3w>M$p/+b{ryL>f]@JzL1'Q!r-vW0E&Jvܫ8 .wBX3Ŏ%g.a#M@iPXjO X25oX']t %^%<«v1L\sSŎ@  VZir5܊3Lfa^C_kh[9Vㅛ/"M\)#ѸA&)<ƜѥVj앐;UPMs]ay1/Q"{Ѕ1ް:O, G=I+WhRG)2NRq'O/dԃ;F"Ψ!,nWOejCXOڰ+&r>3cpYr;a Ug (䟒9yL| jX9YV4-W0r;\b_Ie)/|~ 9^FDžmL1Wu |x- O %TwF|Wd/<b0*%vΩ1b^4)R¢.Bәd&I4I b|bF9.z?)sUlY֝:08+"WU OH7ܼ)ihF2@Ww2(S ~-_C3͑&6 f2_ZM.*M279mLqQ(MMJP_&9RF1 ¯~PAŲJQ!nG~R~orw/m _/%pNv49yQFŕ9qǀSM ·$w\,=e3#^2eݹ VFU=O}߇t0}|e 8'w5ȟ%lw?k ]p;d+M'}G"2_- ;}zc,醁- m(dz9u5+:{Z"F}Jd$4'4IL\ rQvs,̳ Y\/VEkj$ߧ_D -j|}AwA1g0(+^=_YVUn۸8} m/Z((c6+jN["}؈#Ad։ m2,?Ѫ1b( ƃ7;B|aT17 Bj͹[gGD0p9YTAmLv {WĎO.7xK:{fz.oP/E۴b3[45 F9-KߊdѾ?gQBc$P·2g}ߢBLqSؼ?tڭ {a+nel@W R K q2 tХN{mWVnܐVUE,* 8EȨ ,4-!ԓ'"~r,x="v?C1'%@̱Q~g2q5C_rYmKKT^YC UjӂFbĈ()4ˈkoHd6(88* P6Z%ĀXfK;R髺BO<ߢDW4 .V( w>{>Le uSR*0&h%@IDAT%N5S \(AXX~ k>Drl4YϮE̠?f`Q9}/IL'#/LD-ͻ Ln}6\8#D [JӢ N)P#k4|\lx.@\}{ˬ-Emk?WODsqG":oe>T5HM$KIMMFETD#TzRK:k87XPRF\d3ra޴alq,+~b>vY]?K7?R{FU41jO/Lu`*Q#ZCBw%F}KeΩIgkP֥F_UʟyhZ$I;ml5am8j:kmRjL( SOS j 4 ր5 (.HWQTüg[YI辶s%}`<VW׶F~~R%`jYO #(5z./㸘(m_wȚ3 O _ &,8wGɒd`qUtyO$@X?ϗߠh H4J`0 {!u'^ɂL(X #*D>0޾| YrXY$IoC@%匥ϔ&% " Y^#pe%YHk@<Yeǽ}ƩQb[@u[TDWKk*0g0OpK戏_;s $Zymvʕ]{UɛfV~K $]G{tVڤԖ,vk{Mќ9Tc%oP&o֘{Ot   Q8 H|Лd0NbL9LPylu2ECw:K]_MWyA dFk[qϏ+1(& /`aw 8Q,T,6]E')Zz6* UBz9;(>|{ 6_w^cARJߢQlu*vu[w @ro' miw;8iUp嫷}l} ^a1TԿzW}% jE5deup2z4d?WYtUj$h5mmʺUůDm`$}'"lM N=0GI((JӠNC*.~iy4cU3;xrߊ_Sɬ)jh52 eYieqBn{dNӽ_+ӏE tmDRRvſsBQe_%,}! X٣ 8:>,ĩkOՋ'WT>F*?CʡITV%HrRfJ#c̀hQ19Ǝ4 L[hQ)=Wt N%;/¼s1C?fświr홀9FH]jڵc(VӀXixi!='5*.-B5-^e&Ο|@z5*r`QT`xK(3&5Na {v7^7<@qA$ (W$xvsG1T-D56}W[=z<WB\3U)hٞ{r#N]TE/!g1y!]W=rZ4/:BL* uKP_/<- I PL?n}w;YQZPXǍWvW G NjW5 Q;3`jHfIت){]FU4krrKSOFd0칝Q2?Kk.bNSHx+Yb9aOyp'>Ƀ#p9j,Ck|ZɃęb!j0bl&3i]%LT^]^F#/rzK%Rcԯj^>yVInBxr9u܌O(if NTRE#Em`֮ (hbu$JسJ_) T?ax0GV 7>w4`h# ք *?+BV1cDvuQ~!;7] xEL!σ[gp1$bIx|88{}$\@҂1suIO }gBg$yfmho?hYDo;X[+L4<z읏h{ jロS lC;{NS+^̌ŁoTIYl BJCN¥~ZL4mKu hG)OR:W7{|9%@ ll4њX@1:?ZF$u6 [wKA|TK/mUQ AI T&7Lj2^Y) [n ,X;ZϺݷ-֕O O3B/Gƾ+A/Z 5f` 8;9%K@$2^6y s)l\:Y\tE{=9bƓYal.S7&Z`Yu H8._hJdluFt )-&1l:E?TJsJٝc_Cj5gaAT uw \X\ TRfm|nDzu# IZى}(_%#0M%'פqܯ;T_F+y \J8f 0=>Fn;2tw|C@hȂY.篽jL|vvK<󗧟@!I*#$ ] 8MA7*7҈dI /&:%K %p>zbG-nJbR0dip4,'NѴf&@hք8!bJMʺ]R)/yN1i1ܐ]ˤ>xR}0AϋL3Sy#n(}z$عb~:lT9;ˆKϡbW\\Zڬ\+ v7@ksel =Zƌ.^8%ڸ\Rpv63:ϗВy!z4\gX-hso;@X*xxt0- ,H*98Oz[yEŮ.В-Ff@/Z%K{̥@RdH7HbEF 5w-ه9:O,6J26%k U )k^<:nG0E*'1&3&'L3>_,ĩkO^|> ''ј?NdǍg*z%ۦ#`ؤE. ߱GU$t?4VXQ^[5.^ i(u37K֢ ˌ6Ĥ'O0LI`~w=f>}OOOǏeZA۷}nܸիWٳg~ȶ$$<.X2P&`@gl}爫;ޅshX'rL;׈Q1bx16.UAH(c87v,-I䌠my=/Ir螹s܈믩2[l.W25F#Z3RѢrZĉY}޶vF/Rvbſ/L_fz ;`C hR 4&+F'])<׈S%dbD C7L.])S&dΜŊéSԠy y̞=&K.yz*]6l>}jVx9$O\V?ڵʕ+(Zڴiȟ?uaSkߗ#/U u+Yq|m\ev]xS6}# m$$1؍yyݪ~j_%p{IEr<>0v]6`Ŀ ۼ%Qjz+~KK5b ͍ppZU v؞[(e+_0mhX?.469R@eWwl8zG} wD(ѷg :[EL1,{΅0y+5_}{;+&VEΛѺݏKdX(6c%Xav#C JFT+c1xw]A&m:0.d%F3Hpn5/("$N5"~ĕ$bk{3xxi < /#"z?oJ4oBߟxmUk&-:(PTjH\oڴ mڴAΜ9 zZ 7n (&޻w}sV&{!{ѣoI" *`͚5S*iZ}"W\ ?Ȟ=j~WO=4CݫW/| 6(~a:+VD֬YQ^=4lPݻcǎ>(+vssC$I8r<;lH#դI5/2 ؆ÇW0~aɒ%Sڸm۶RJj,qFP.#GT ޽{ ?Ž=j'3#+p~ 5x Θ195,:u2Voԯ_;vPZ%.Ν4J4[lKRy&L//ŋfiЀ9I +,pŠ8qо}{(cYyZ8r";5o޼y u.$&jXN  BOiضAm޼yUTRW2d?Y"M@IIZݺuuVZjAǕ|=mٲED)dsĈ{86~'nKM{f5c!_ޏ HQ=4/RX"˺yRf>E-R\@I@SA'K)h˜7 j߉adA!h'i&w4&@4uTu̐!2Sc;_G#Rĉ"k׮̓͛7Lb@ Dm<,r/PsF*[(?s 8Ї-~d~g$Ӓ2YSҤIUA(+jhR1Q;G*A?5$jHr$j u 8w%WɃ8 ֡бޥ.]t _V̜9SPPo-ڛE)m14yԍxԔVXAfyQ՗,Y4ODfZX;*SP4? !e@Ԯ "QF1cƘϊDpK?&&\Y? 7 ELÍBx%ҕг|5͐Ch=dȐ`;B, ﶈCo)۪t0 },t C ЬY3CE854 af!hFV(QBhy)R`JӳgO3[>,Nh^H-."9NcA }h(h.Hbp "Q+E"8d fuݺuS}y!5}v"Gs@ (MCJٳGɉYYUG/ = jD׿޳- 97['1%#A="6,rhe_k>NKB9-!QOHg-e9-$fg;mkZy^Lj*hBգ74W+ +0Bsf.?`m4/"$7]!yބh m|-ֵr{G,v>aH~4mL@>ˇfF(/_*;f@VG?+ń:S2v%u$@$_TX66mZ9gwQT],Mz5iRP""6l4E@TPDAi.!=oydMvmIWμs+P{Oq0 Et҈Hq hiPfMPg)ϤOvaaXF*%=C+>ѣU r,YD2q ӦMSZzC1R,3J-=ci!MA#R98yL PJs@%.E'cW}<%d(v`@ŗ@>|MyG2pM^~$Wr$K!O~w\61s_<̛坁1 ɛq/bor5Gw}8$ș7HR9v eş&֑fbSɋ5 QhrG%BV0&~o, Y7kLE ej5QCEMiZ"}hFk)S̱q"H"- h]@Cu}}ن4~x> (g3}OIL(~)tTc(hƢmTLK{s;Kv4<%իWWNDtfX`ޜ6Euaa훨&$՗hOF_شՆ QڸȐ=cF;Ҧ4xm="uDh -lx!# c700svd.j.|Is51â),:Yà2 D@;w*<53 4C!*+3A&u xݻbwlD0C" ևV%(tF:c&f3H&əf͚%g)ESjUUc 5ZV 2Ҭ+_Wy,(Wȝ7ՏD`(>Vaھ+*ՃDl_YHINDI#K(:NWۑ; |PvÁHĆ$yz&I@v%PqR, H8یHEW4y X x d5G\m+b xU< t0 ́BbFj !hA8Z*q 䊨kN$xBرUTiSeU!y #J#Áh ]7;^B%.t((Sf $_)1g_C b@PC"$&6\X:kFv)Cn Bg ih mA@.CɂWj)$3"ӆD6{iɇv$bu#1_h!Б&*M%ﯿZJKtĺe[ B vl![GPGc ͞G'e x&W>gIS.4 #.ܤ:Hq-Z|1\-Mgݺu#N4ۤ%ݔcA.M܍u”C2qׯW]@lYKp͒\,ROw5d8j[}1"?1i4 ߆چ¹ jw\zRQigÆ `!}]\=k" /!3H_Us^n |P㯀O1#Hf6i/5/VjpzZl54!QOhR{OI2AmiLj:8P=,O)6ۦ%%4I5ha;\jDS\p} 1/jZժUK?W8ؘWEs.J  2 @(Li Is5cm(T3YXclK[X@6sr}L(?P9o||?uӢ90{ O 7M@nQ>,1cg{= \ߵȖ={n ^DHw1y#Q̔dS&5N4E JЩD\`fϞ>$!!`b^.ID Ƕ(v7U?9j8~+$8;>D|7V.H#'qoτXX܁%;Ǻ  $ylG6+ofZ1 NI._{P!ĊPMBp 5?1> L%ES>0 /Cز ' 1ͧ!;FI?nH%2{l8T!+SBn%jPsEg|Cg :9n Wul2{G9oun`O =rLņkǎ.PP"evsS>C;Jq pt7֤ l\+ zk"aQ:$YM̛7O4s TaG?RM܍U٘`1;Kސ@8@5W9$5蚸g04}K٦J,϶(DQyc0v41L ./Ck+4ЍXk=A?w>Xƹm`mq8P :jb#}|P|n p%:Z%W$j׾6< #SM$I&<'VI^_\015Ss@Lf`D !izGLHrhG?cьOXb"MHJSCAwt7ՀsWOwr|?gΘ}gx{o97qA<(a/"sdWɖi125G?~z&ЇNf͚U h]K+6$M.3&k^@W-˒D0M4JQK!Á`q+2PuNLM?#GYi#2*}P9N8qئMd[>|S4B D_ZF+"Qj֭(։_W<9o,Y,'خ&;V&O6c9(r/TZRk*Ts|HBP2lΝQ~}o@#%K,O3/Dzq݆f/O:C~DF4iu)ok׮JrTy#0;v옺yh}^TM,c~9-s<4њ+ny^-ùPڟع GN]Ex7`~@.,o9N@'q;"Ul; t'_Fۯ>}Mb!EKhAswl{eBGWa U۬c<,CAW8VW]c;;r5wegZ Kݕ5 fiND2P<ƈV?)j\ tdwɖizM 0VP;C`DAվ}+Қ<|JoJ͍ke}RƼaz5kLAW_}BTѢsMz˚c{INusiU@1ڬ7sZQ[z=`ȑ&GRmt dɈ0I&MRHx#GJ RK Q>/U,ۣGկ;RҠ(ětȑGBf7}6Cq{YZ$?> %YIX Mݏ mnY֛PC>tM<̝Ipuv9~Zݳ$Voj܆'ٽqZNg%nA64co8g:41d8B Li./It~24XGbLHa/$V]Ε_ Nmk/wpy3~Y׺إM4#΋>CF3ٔ:^Wɖ#Q7`&ṟGDIk- yPu.A "hg%eז&OZAE  ?C__*;XM rĹ2eL;ڟ8yB*.mDdM.]hE I!ɍ7ٺuٝ 2uQNY ծhDTAPo +#%֌rVSݻ!:<1LZiB(thoGwUܺxj`݄PjWݤJÔox3Izǎ?z[L26k'wRNF;sNT̢b8+83};Fxc(x*ܧK"*ɗK Sc갫vFZc9+nN Tlڟm=h+Q.݀^Wӛ9j@cOIPL0.IիW⢞&^u @.b,Y"Z_j '@ JD<ؓ94aW M+E//uF![lo\"އ|`e(]J亗ypu+-h}动纗ՁhfH*&LS_XGaÆ*4E@e]+?C_@&{ O[>XrO#H~Z.DNM7ߴ6A0p/d̜χ>BGI時GO{>;~ jšG/Юq1Nَ: cpeg2e`̩򾤪͕ϠG#Mδ#xj>yEjⷭXp=[N\7߯B'Ð;K(c5;@ji0o;^ +" Y O Lq$(oԨ R8\Pk ga},r\3 МVE1́g&@߭l.깞ߴ.bY?b<>f Mxet91?ifjhd#: Xzĵ2}Oć#MzzLNcA%ڛ`kf;q_hVǮaYsoEMThikikV5~|㺝%{ f7 ,DJ2HakU3%Γ7)0D'H$~vU;gǛjF?5k(dZin(n'Α1%$glz &=&(Q7Fyr$%şaܸ/kjqb(]x]ri'wUul_IY4Lvh޸YҨc1l3=kJy#Z|_lF鴹mGW:iț}m#(Y(#O})ͤ o?l#~HqzY.Ap Qp T'~2UVU׈4]0U4"ŲH;Z p5&=&fpRLspOC˞͛71qQL7M}>+z>Rt0~0\[K\^)q FǬ l4qZO^|)Wec_Z2rэ\u]w[b=!k߬y( (AjKtKN"RQrAU5xP=LTgR.XHX}|XQyGtܴg[㫱ѽEie7eDܹig7śӋo \L|,/@.ojqNj;)_y <)mZV {&莘qoV{(_*/ߔ{ /'Ҹj<^&n*bd];`̎>߬_>R&13u60x@3رlݯ0W ~Gs"D󓡉?H ^/\[s\PXLSȝ?ˈ#ğ뭑^D_v(++jĨɡFs>M~Зn >qhy/nG^(y Z>Vu4XKZoE@E 뒨Ez5!*IL 4Yc7V2έȖ0>#"c=>uՇn7ԷEt=[}[:C~\Ac2u*/=rhT&;Vȍ{,DidIpU,zKe&űxnTj>m?'/aƤS"[DW_ P۱z8nH_īiBq -z/3.r("#kc4h;w ;f7vlf6޷&~g?ƍބENP.V̹,*=f_$ZK>O|I=%,lqˎ%:y rdLi,ed[wYiK8~7nQ0{JiQsp @DPucj?>2 Y͔5Q!y\p"jYYh}Sn]eES>8>fv MsL)@IDAT-(et@:П49}|97F XYy9f8HJ@ݎrq`Xfd|w)k1N34#)F4aNIfYMiT(#AҔIqbɫQtj)n_Wsˊ?A )D],S(Z?z@=ke_ZRvT}d10l%1пk/1hN2|=l {Ϋv΁<鲝^D/#5SqՈ1Q_ _P9pDh61l(Gdg)ښsȒDr᳅"ʷ2MfcO oH3(dVR7>iZ@f|ڼNѲPh(8z?elZ莯;%pKlȟ-5*> $PKt(WԡAINtt(7hw L޿SD RJӵ|9c]é vPCܸ"^x96^[yn6P sF'sļbLY@gy`F26HIJ w+1 y_ EL OTߥ :  l1Qc㊒'X~LڗU=O38os׎nOo316x(nͯ~E-2|'f܃2cȈ}@UŬqv!_L'A\lY`⻃6cSX:Z1ϘJմz<)'$ ei0 ם I0׭Z =Νd.ﵧQhFE0%X``oT_<1_(20p\%QCe5CFJ3f?VCi1})esaXLJ0hLZp0Lu wǒE e"bJ;c?h#Y=Sa*&>R/_o?|H쩱mk/=vӟ@SZlGNE^oӑ@9Pp_l%IlC EjP>2JBӾ)EuKwM@jJs7GZ /{dAGH>l ,Q8wj8 fsD>9 Je8`88L|s73vÁSȐyCdd9.$~_,2 3W#!}7ћ =Z"3YuLt5ܔKޛѹbw#m?}%ι7x"t3e :#2# 62`.%2ؐ1%󉌭fe :{ eS١,Z7,;%䊒KTjb9`~l?t%x$ق<3jNh޴Hl[,]>VHw]:&9䪔ɤwp  }!>tMbe-s]%Q Z8$^J+Gld:aRnh2LV <q t].T :Y^Б3r}_~%͛chР:N U\9U7O<`J*rۯ_?uF,Y&3t/nݴ# ۂ9b89A4hRK3cg>a4mKܥ^c`hR9>tOz|SYI{C:<MIspJFq]ݗ>;Ψu"B`z2=xdQ{Cg=xfdY]) Sˀ(oXQ =Lmذ%KDϞ=ѣGbo˗Luh? *;KU?ʴ~?m$3!;p Ym8GgJ.^ ln kvL}ÁrL2ŶzDm^ig߾RbKQxKſ'Yku}Fd`Qt{Jf(7Q]+&;3C kh$d,Xi<R<7<<\YSrmdimݻ7r̉ʕ+I&8}4݋RJ3gΌ SQz'"nbwK9ׁAwɓ'={vUsR?tR7"-`:FaDlShl F^>bǛ9Q#OdCskm}\LB(3+#o.]b wSF6v[٦s2q `ڊnfeuy~s6?dː~/B|ozc}B)G6 }f[ Jw38yY+wu h\}2W ˎc ->4nv|%C+sUp/uT4c&ŋ+p4c ?׊UVVZJzA`E pB4o?`p9@uzmQ{{XXEN҇ݶmh&oLt'GTR%">=Ƅ |ڦ7qƛ&TYF|NLÁ(Z$MשyR+=V)&ܚ]aDμzÎ_ϹIN` 3Wty[pLb~X52F,Qt]-Cê=ˌKʨﯵ]PH*M=mT~ħrT\${;+IcSŋD6ig.F5&LZتy(:ތ/֨* ]2bړ7QnDFάٹ(YzQ+լY3%ŦgUs-N_'שf͚ʜ|,j۶ʕ@>$5J{)+L8PP!=Z`J}U-[ZjJ)SׯWkV nB3={(=)΋xj; !IT# gϞu]IIN8ZBep.\cYbRhl;Zg;v(ŰaÔТN:j<o$b{.RAD+.<$ǎSO=t &f`~'Mz ^^{OS8C9~V/u&U"a6,ZuXcO1sˌ!#UUqv!_LlY2"Q7O;h3=/?anEYp`9|6⠴ШbvTyoˀ}!?w#W3jKxf 2s^+~g1`lxc]Vl,t 6,<4*;pIs2b4}\goF -{ ׾`8G(șNhs *po2o> 9@X:4`1>x6,"s qHl++y:z4e81`X޺8q]7y&дqe,C.7n)G}V:ꫯ_VZ) '5 Rt'̸&(bq!N 6vXރ>LI)50C AU]pqi&e~  ܙ5jyEӦMxXu /&իݻw>A B<1h iҤI>k R~0 %Pk̺ $s5ou2fBnT$[~ѽ{w:z(QByw /Ȟ쓀/'|Ri8)<$1bpqw:p(kƪ[q[3  Y.[kG<{jvB=Oyޘ͘XM-:k7saXLJ0hL@2CaXc5ydß_U@v1O|>f7-9O~#D霿 n=BY6UR]م2~@ 9"X,ixa6wV&~,T8WJZ* *A%ijCdTpQ D76[_,}Ȕ>=7]01"浙0e!`*B-TBkcݸQ ݛ0^m /(by"ZZwuDB}dG'+ASZZ>%z[>8z,c3BwƍjL EM9bĈ %:0#&9>H j]Ԩa={#"U{ º;`QCFsTWi6lSb(RXQ5\g4o)*Uj0'U $thH:H @B6jzq&D<#g[׏;IR&O,ĝ{'νm:u.sExt HnܲE(n}9 LZK _.Vt?edǧ\´Ր[3eϔ$FG1eEP,2gI_mtY$j'I=kNcƌQuFz>,]֑QH$jS@ה#G0ZUEUE%W1 O? vBC C xPBs6jQH4,XСC.M^wiѢEj 9hɬD,.Њ!١d$ .KSReݼ=9p;Qc]zܺ2y饗yF3?jA5LSDph1Ӈ@q>#8բJ~RU^λZI"?nDG3D3t[ﭿ]1=)bZjr\]ʔ-Wu %s9쒤Hn*@/x#ݗekVnGxDYb))5z2;@R *##}A,wTjߑWѪj|0pH0m-k})G.%e,p$Ésfؐ`fD-M\г57oVZ%i.ĉ)(sڵk#Os{2;SEң>춇L iG-~h>HPh"xhrGP1/'ZlxyZF Im>F(5lحYn㭻yb:9o9Q3E"i6H M-9rr.H$]}2HJ=]~EÁp@Q'ȕÎ9=)SUlX6nB 0/9>?/ͤBKV̢ᚰ:h +-/=RV)^ȳƟ"v[+ܗ?wrPD )k0zZxUΧHzӢݷ仵BRTġG.X>' vfvk6 jy^#EMIÁs ݗ_~Y.ьZ&Pn߾=~i^xsLM b 4ҹsgfTH#>RPhƲ[׮])h*HXϠ)Q5_4Slj $̱^XX=ԞQG#h`z@+z~QWbE%٥4,]ҀpBuVtp5o]/־t幥Mgǀ5D^ 瞱c\zȎTƆ)Oy3 {B+eG$ɺg|Y!j9iĺǷLN?mGnR)p@8Ly?$A!8dIj=&=- dQC]_-ޣv*pP8޳?P,toL9{H!ײS?z>yeiB6 Lgl-hV&S{W@{ѰR$O% aȭ6a7종ed@TH,to/5o]qP4M;qyb*fp g_Vw;h Kfm fpu~Rų:";-ݞOI]A p pOc|s8.td֛z,E?8=sz@7G^Z}*ڭ#sRgGM3?#Xۦ@pB, ((}N ? 3N>gL#bW&M,Ľh6;q V̟߯J3qvLjCra!; >3 1`<%HDYS`&4$uG4liVOG6%G %K̭^E@R]{Խ<1G+ыwuqg; fu\}g;|y{Ӟ>8W]s58 5F 8RzO"qk[zԶŅ[y]yM=G' !Ár`oOJ4SvdLo'}[Ŧש] xYhzrL@vT*' zkmLō@?F/q`-jNH-\|i`Ć mj'eUR]Q(LB?fU .$±Ӈi5pF9U3eWoSr?=_ӂ@B$W6,[%&"=5? ʚy9/Q1c@D:rrF1A(0{W˱-#C@wҒu[J̲&[HX?Xx ;>t96 )0EJ'$"(䇉ݘl9 1aPU6s1yݧ6 h#g%n&tz̜3% +-m^H"`5Tz:ڊ|.$~\gǫ/вq`ԠP ʢ|}`7Ŏ@mjJ_RH+W(5P\Αy RNmU0Δ1H y 4*? aǟF3d8`8w6 ?Ua_ې/WE -' os+CsQQt@joJy]_d#OKk` Cǁu[g7; /!ASB]x1ޛ֡ #?U$=520H(Y6Z"3[ڋDSfq/ .1l,Ĥ^޶J9gX2Emn$v<_ߑ\V si>PL6ELb4>oP5+ ƞ(Q5c8|Ԇ-l]E6(`#.\L|?עUiӦU7ت~o@q$ T~-pͿ:S{XµBefɁ%k$6$>xO#O*{ I*z$#C;]#dMa ;ʔad p\vL1s>Ysc9s9Dp..]Pjߔ>`ڨDpIKX ’@GB <`jh`-z'S"5g`?6 ;oǃel(ZȒQ>*WΞaf8Ɂò@:+ F ˇݲS>ȝˆ*=%tTl"= ꍢ_m(+Jb\! UȲV/0l&z \{"vdX.㏯'PQa6pO%T ("X!`ӧO#s̉&@? -l 0hKdɔ),$S0{9qʆNΫqH֕;iLޜ7pǁti)a&;$OTp 0[+$A MLI9fJ0MtmLs]mX ocOUyo>c\J ϕkc-NemgCdH.ٰJ)w۱a DbS G]6!mF1^ ZJH|v`S@; *|ǎjThQT:P9Hb}1o$bЖg ^6  B;L=tnFڴu s;HQ4Rcz%KP۷GZ>Ub%L2%oVr2d8hPE@E?C_艎rʩ"Yfţ>8#N:+V`(SL2 }ܹs o⳿x$ߩ5J>RGÁDρ$􇉉(UfZ~o/^ҥKoU*ֲ yziS"2@*^x0lj)pӐ@ 90Em6mTG% PT) 0,?x`!G@B3Ř ʙ}={@0a8`8`8`8`8`8y\`Ĉ\YedHuVuk׮j[HDC?F#2]_8`&C04j8`8`8`8`8`8SLU w;n8̙3۶mSgĴex/Kb6fjųd} Cf1sߖR7Қ90% !2000;.f/c@6ədGm!Iw 6;,[gm2ʎEm[C%W ܈|z_GN@C:;+1 VC֭[\^=Hĝ[o L81S>}:N<_=mħZk0Fq 5ESH~??C!Zd=ɏ!Áb\`,#@F347Mj1hLr߿&$cŲ`@@1#5.\k ({E5#_OF*U"#ّ#GPR%hl2ܸZj*/YqqVB w{aj>|9rHϟ6oތzry+.]RK Q}ZVa< \(&gՅ2ɔ.W˴ n_H/qEҋ(Dsf)mGlM@hp`?EyrƸ( 26z |Y4Us>SJm 6l".}4b1a@m?ǎ;p1fƍѲeKUr<\cc=C\PN PoRl!!ٳg+ EٳW^QژBk*pIIm&QkG0Zn("Wɱ W^?ߏebɒ%Zc\hoLM`K\5kFڼF$oھ f/9v.eCYYysZ%bqBLN\ ^ц&ĆFdMc@|ՆU˦Áq _.Gz H`<;Yr`-;R$w3K:K7Q|68'u=f`cxfnfCr&T|ڵk䐞y13[lO?@MPhQtM:fΜ OMց@A&kڴ)vލG7xNmذ/)%y@MyIp3sL8iڵk+;=(Qo"Ƌ_~y~2j(| /ʽx7"gl?XD\+?HѢXܼF dZ|E;Ƽ}Cإ-+s@c>fvuknf09@ae#f:;6T/'`4_I6?>Y#o."8!#3pUFvy$ƺð)u?f*eB?PS\x>ԤЏYJS*JѼ@Yfʤ履~R.ѣ7(WZD' 6@-Z(Im;C=+M >'L./_A;5ٳRQkЬ3Dy'5p$n#д1DjlN'~Z=/ZgߊɔHM?h(l9r\n9ax!\Y=wεwNʻVG˜qe,uП!Q]?VC3f _6(ATЦf30!kNԅ[xjNMT5C 4} 4# `xJO-ҾW0aAˀʓ%'ϡalȟ^ǰ-xsO@ןbzάi~ij}*Đ!CbT?_;wNiKFELQ;E"驧Q|yL6M AM 0 b͖A6}Y"x MjԨjfjdə JM?7BYh0}Y5V,R(ܧ`ohMlHxp`pfE_ouN-uڽs+p$A|6_ȒYa)cf +Fv(<9+‘?v9gäYv\P u9LvCz0Z"aFkjƌw O* VM|ӶOTlK[7)}?b 6fk;OZ $OXI(j,FтI老s ؒذ%Ǐ(eN~ΗCGnŸUDL(Ԩr1soDPEk0ÇEjL|m۶^*K/M6ʗJèoYfUexg4ۣ5%\ӧWXXnLZ~}3FOJ#$5H4{(PhG3 (o? * bAAo&RlcǪ$#4ܳg&ML3ՉG `Y~m 6/5!p9^i4 5T_P|T:j|6 ٵ܃6|*c-u3m>!4jphVnJ*YRmQfpye1^ Z .N"J>S\P{K;r[UUM;D2h(ZWaԼCxi}|PU93Y6URMo=Ϙ?L钡-?a/w|wF )TbyV{>`=!./_I*Y[O+.t`D6#C 58}xhnHíqa&UV L߉D?%KDNs<#vA"r̉+*CDro߾ܹXaÆʴpʕjs#8BxX`mFѦ L&Vڛw>o;&)"W'^/FjZX֎>mȔގ2_/z]gԷŮSp >qB!lh->w#Wq6񦉭."/]CLwH̩p-u?vYJ=A,Կs:]*]8jxu3 $<1I/ܭ P)qWbW>1mVfm#| #} <<ر#hbsnrMS$X̫R:.3וP%M ~a7c?VRtkU+VGFPlv$_I"b{]E-7l0UB | H@JwUX9>l՚H>[d+.4w,sDŽ\h0KK bx! )$J1EBVum;HSygi}ѓb @,&fՌL;2:5; LΕ%S#ʚ>*%uL,,OQ;퇮D|NwE ˖zu|0ߏڎB9ad KmʲS #˿``-L6KW jPzJ2ό`H_oZ P""v;`ǯ"N/~@`U1P8u?w*w-C<78 4}E 뒃*Zh\BcuhoBbK *q-dH>ʘkwZ'%|]\.;[ ś7߼{,X,NeQhzZ ~hc-d<*ρG;˘>w0]@?~?wGiJLJzwX4jua9 6j)/ gy"Hв{;}6m;gƐpcn1)_FB|5ȁ/~ |=;mj0A@ "֏HHqPj\&ΠO7@c&S+yLJLُ]Iljɱu:q `1'1\٦s#h+[ ~"{%P-C%DlhƔsp ,h×A&і@;hX)؛vQveGeoj{Vva`\;ڽYy_~ glj ЉVn<]c| >_Uv˙͑ΞRQ[/.CqAT~acz*wN]C\6ǂāK)s `!F&* 7O~jՍbOEm6&SԞPSLg{93~hε~:Y\B?g~[/r:eK ^bh6('O<\znx6qDxJqw4>ymgE߹"M&g%5y|&`06`{>@' ،lӨ[!JjG4mEOV(P&o?oC64n&,=zDILY/K6ċ.O>/7q#q1}2l7ƤE5rpױ]Z ZE$]ex=BE#W "70JEs._T mx8}RƶӎgrcC jmR04Tst߶"OQW%qÎ59›Œ{yG^+RXtH'xԗ[~Ls; +.D:$%$E AQ[L[DOQQEPiX:;;yocX3o֜?u_$ݺԓE?%k5s|?Gw*1~E?Abjz:iÎƉΖ{OO&k AX:^P rMu9UjLHzrB٫nǻ ,%[!"> 4+Ľ`Ո/a7o{nf,OPiȓ_/k 4&2ꓺ>ozĩ[+W:3E>/$#dַ$ocS~R-f75!K6_}T>W+u.P-_᭪̂2gP`cNSb*k<Sdͪ-sɵ5{vmSFC[<9!7O]޿[! Ye {[Oha17<0B@B[OHHP2f6y䍒3S*ټr<޺\&<8٭JmC[]wKݥ.ЪaA ˮYm40ާݵzTGH)cȥ{@s[HfiѢof-%U 쾒_渚XZ?xuj)Yye߶O;*kt|o%wTzmTY@~D$ߓp mע<= Meӯs9eߘ>q+H=\zJv 6~Kw :uwI=7* gT TdVO?QSRv6v{LD ,H% ;58hhz}jKLJ|X:~dP+ʌ>udwd}UkV3ڥ)=bݱ||)D>dӲtZNH⽙Gכv*]npqh+;eE*5 RxfI_Ֆџ֐7fl9)#}ǭLA"E$M"La3}KtWTqQX+` j䑹ՕG#խ J*RF-QFfpTsz٦,=zΖ Ҭ'e(G|~;U%O<м Ru~O#{P ɂ%}:z Mb+l-m97pess;{K5Hx܀+7M9[hoOE'oԒ/Ua)]܏_z5zmi\"؎m?m?'-njhvk]/,'2w~+4PQ-s=z),il ']cn}`1,V`q#*21%4vd2? 5bj4Xc飍sXUמsP{$gFEQ/^Wuu ټKﮞ7J|4WlNY2s$c%jlYS3fr}PJ w>S.E,e3ӪMyQ,>xUZvH>ݞpT^灩y啌z R2RX^XGfFkJT.sT|;3"R)u~\sS&R1߻"ŽԨ!Uo]?{NMU5n,&IS"uU Kso+Kf ɰMT)ɿ6եmR0kSeXXBFeedZqF>Ћ0BlJeeǐ@h7?jr[fd7症;M2:MTx:|>CUV1ai٪LIH^%C5XܖϨZOU=vMak5+2HdtAO_E劒*e$ ΪԩL9ʧT?>E-d\n_t}Vı*dn~LU\S)ۮn.3?jX=y)g L[.Ac^p(R %I^a2q/?5~Ɩq/w'y(A.j-_927%5].zEqa&B``vlc#Y6-GRKO`mRO`ɶq,֎j~*(p2 vc9ۡnz93|ǰkviUZX`!-wFBve {7.ϢI?25ށ@B[Or&ʱ` FZ]j[یoN7ڞr""ꎧ'}Շ#+iޘ!%0]:(שv='N}EI1M{rM׉O˅wM-J7vJF˝7v`E+1=nC&LkL4.MCl r=tlƅhY׾}>"s5Je/W_4 #@*LVͭ"$ɹՓ3+.hbVhqDz)._.4Vs˙#'wnQ\z44 o,X/TU6E +`5X/??Ql4V2(Ʒ4 i-T >tH?eSw`(ifIqƦU+2K{fP/ϵjи чOd^h'dW-0O q/Xh!~>7f/7wCn<H9csm\m,&~Y3ʻx`Dy' Vy m+P;6ˁ*̬^ZB+8?\ Dz@(P^Nm#ƥ گ SkXd>o[kǬrn7:'w?Jp.W2abU.#Sw(΅ ,hWαԙ:BwZ2%v}5Kgm V˛I6 =#@c- ,N-3TC6Fewv)DiZɝ%F{<Sc}e)a:}^ 5yuk6Z*\_0zni)Tzrj:5X>ō$i_MZ6^Lf♒Z - x~Rr.\W*ـwf#g34S!!|Zt 68mˋgçMˇ?=n5c et&Ҭn~y|USMw wemZy6j sCuxY9J*u7x10 M~}&܎ٮF{UUQ,$crbgT!)e ~jc֗GճhR3/7BK@Hvm:r usnqv)1'rii})z>9df p?1V{Vu-ӊt{̒,gaōpf%Q,:WúY2|XM9=׸Mty~i|gӍY:'ۙV '1Ľn:EJx=;*;mt.<36:^AډP0ΪQu׸ڹsg.=9sڵk˧~%%JHwÇG}d(X`5.2p@yWb6lT^=>~Gw.˗/?;/^,.]TJ"d̘1h _yJCzo!Y7+rCW@tb"n|[c{ҾdPnEb2[D_ ΁R+Sy7yQ2ʇR YЃ,s ?y5[cL'5ʀpj뺍s[jǭlPܴPoB?ս_~:ǁҥK͒={vcڵKf̘! 2eDժUɍ7(˷~k*^~eՠenV*y! *%K4hѢcSiwĉcNKsqIXbpB9rvmbAViӦV5tңG>|b5RX=x80oIf+\a Lפ(7i&$;4`WnJ\\mlPo1J-!jDl%]Q@W05@(2;"$@P(Aa +qZtYTڴi\rfpp4ibw},[Lz-yLDmڴI~W0`A߾}{,E5k?,ٲe6mHL zL{M͛7 [ߜRqI*2yd5j ڂ /41\o> b[%y{q@ "wH':QpxaMB7r9QL˸&i8@2 :JҴ{"(czNbL@ɂW ٹb믿ppƍ8ޤI?w}WJ*eYO<[xRo̝;Wڵk'*@*_Rcۥ[n|2vX;(믿6e@PǎqbRI*UHϞ=+#.Fz2EbCq7Gӓ:_͕Jcl;յţŁm;#$sn댼^ȭpdf$!ٳ\gB8PCo&y_9{b2a xB-Z0 PƷ _4^Gm+P}BCjժ谷2q MQ]1` (P zpl`5ZtYHᅡ[͛1E롇2\ Txqٲen~'bFmdŊ‚ "f =#g3V/S#5K[{'*jsJHzۿ \&ҍk8v,gX`< \K4gA5blBN8\D'$`Ͽ@)I4ȦxqRp ]Zw߫"{W Y7&L4t=W_}eb X ፄGQٲec*a G$4co6͚5bD #"9n0N><3yܬf͚F#t$7֭k@M7dȗQsNbȹqF|.Qr I8 L ]&čkE[q:kE۷72h(ɖ-#0D7"A]#U^= sa\m=\r< 64/eIA<knymMnr$CVʐX3kߥ/;D S[ _v5{iP9idrV,T%p_A󭽿.6҇/ոy|Ӿ=yV4.$Kg VNsjW#elm[s$5Ia,_KfIDDQo8I V۱3JwoɨDXK;Nz EyΜ9& 3'o޼ў=ǻdžpdΜ(W^!X̮P#s- PaZq#@ 3 <'T?(9Q;VN\7q!`dm@p@kB[~0 g_eL"H9q)߂ >& 1 K~D U5T,l*sRfݡ/IHQT!0Χ:zJW@ T"lSuIT>>A{{8w/!F">E2vL2ږN_--dCry\֘$n)uI>dz 6 ._wB t޽rx7qᒍ!l8qX3Ŧ~? 9/bks ~vĝƣ;qXQcXyH#*U2rw}gF$i`%D,)ڪXQ3tK?L |1&_as' O# :g1 *8lX.es`(E4KXHd KL +X .l΅L@SUhL1mʔ?̣zCln~nӤEIRhI`4nJ}vՇ0vm<)VG9S,yX]<ܾtxtT^L:^cΖ'K"#0qO_ +^|2UrGvi_A{gD'Y2/-Z5[QKKm.С$OBn1ZҘبMRJl>W?\LJ&{,S'?muyR$WjitG!XI"dȞZ:^,*OL֕ 3Xg@YDӞwxV=dcRӻ|`1\'Qzd`C; K 'm |qA3KҝM2 m(;8A&.4ϸ0Y;n6G3ukE@Xp< BE 74UCXpA!YCh .\ ;xl7'U 4.`ɀR[-tƭrC~ͅeܜ2jLW9p~},z[4[vIDֶ g&ˀNL8BAΗ[<}m>BFzw<)YC|LEn!c (W OF?r{]~Z{>%SOd ̕9vb WO,M8!MTD@뚏N9?"z'Y%cޠ>Tz, p㏦ad;L@+B"4Y[Op3 |&EjN[?܋\=Gy'9yyVgȹz;?W^6:.% '3? <8qXfРAFje N0Es -q0B |+6u[j%̧ e77Iy!fR`-&22X}9wu4|@8B>`|v xGԩS{7'}3fq hK}ʓ LyX}jѸҭeҞZxcE^c#d+-ȺORTRZ5s/\.]$6 ƽ 16Jou=7Ɏ=z4ݸy;Xy&q .>Pְ$u!1pಁvIwgK>uqL뒆_TS_NgYFC:w_ ˟O!}jVYdÊ}Z$rN+Wm*bW6! o: %3KKeގ3xF?Aˍջϗ}5\>"y]_ƵDEnWJΧՅT׷exOfN!z=89p_M_je2t=*lGuHlK܄4[>l~GKA v؇%+"bA# 4G{F!;)CJbY KzuB@oX;-/awDM&{XkInUʮu6h7! ޖ(3@IU{81.C {ܧTbeQ|cW/%e˖C9,'&; ?<1 ϵlpED6`@Y+J Sen~,]$KbF\:`؊On5ut̩@gθo^K((4y.~F@Ly_Ut]m}MʟSfڙ{D5af|fA5KXA nkq B nhʄ &нLu}&18nmy8q . ]ǗN)!؈@#SBXmڴ1!6l0G E_8 `'2k/V\ qM$>\XwX9xqeje!!c y5`5=~#m ۿܜ $@XP Cy@グUI&*ªP^z\D.n$lEc-bBG<$N\60qV§mZp<ΒҤ6?jVQꊗ-HMt)Lq\ҥmgT.g4 ݱLЌmU7.78RmvMw wDv?յ-o2qGAG`gTX(Zieܶ_z%Zz꺑sJ g`4cG %8S>0PRk.X, 4JE\,Qq8 ێC%&$A3# 4fx`'^XpCK,B.dX;畲"J\1IX`AbL,&,KX[bF[wI6V9/^ld DM&3%N Qz'> zP@d2sϙ7J$9q)6#-=xHl>ʪ[N)?PjͬpJ$ӮjHsd٦(9Z7փ|jz#%#4؍dKc7fH*9斂;Ue_k''H:GꚾEn@*P9 CG\Ig>Z1}g(پhQm۶&ƍg\c1 Ћ<{h9wl]{%V}.܁89(#B(2HbcTbHbbs~X(Ky8puqಧF4æ_/u%FĨy⤢[Ú f!3z6ɯ=֍R]_V>N:'ǁɁĚbkrK|*55\  $` -W9h ۞s N(| HٶY:7gs ?A8۶hRcUĊ˽6 dXrs_]xg晿ҔK"5:[*nR7K{W@` lL}褬scTkn/tр8qǁÁKy5}cq`@!1PP tnڳ!1\8L'nlz.޸g+5 Ps|+:_)  ydS]_й8q<\@a!tړN,A8f‹rPu!VLx`* f*pW7^L)o<xH @%u0΂bmlsk7$$|^n0 3'f"XW }n=!۽m&o /WEq|d1MRЅD{8kW"y`J*WH |2Lx pѣyPFeZ>[Τ&0LHyKh+5$LI[4dg2DR:A)pıFKT\9a@j\&p$8!h3]P Z+qǁX\^;8@N5d+<7+\!-Ĝ$؝?<"mڴ1 x /T"2>h$xm5 vn}Yf&1/2eȏ?hc P5g3~O:դ5;ɟzˌ$ÇzL 8优T!-p\yIXIG F,V^+C;v22' F?k|waddf~~jL$ A@tLdʂv7xdg{'qƍg5o'Y8q@@9I6C\<\J q!OZRܸ֗h@cRoF4} )LPXAqB`S2~+7|]/9Οw}WJ*e\ F{>lرZkc=M@p66wK9s}>S^{59rd,3]we4ǝJ xy8q >he%s?\/vc#s )Kko#@3I44_ "%<\&ز3Ё_(-C!`P^eq㞼Y.f!&44e˖pKDʗ/oF pDG /n‡ڶm͵tR HYPl9A0e,&e"/G.qw%&j-[4l8[>}tZ#<ćq))pZn˵Zj99x`:nu1mۚVFC0`qɒU,}µz̘12sL㚎R?g X?D(!bK YaӦMo'[n%e:!LDqE 76{L?چUPLR=o(mP_7reLq#/$]BaDԏO^ΤiB^):,(RHaG(eew2 ċM\^ 40%/)!OPZ2/&r]Y寿j^|OLkWKN f&UTɜ87"g˰_<|$|H|`|N"ފ1q r)RĀ@m:^*>(py\OޑR-0µJ +( O,q͸*; W{e۷oo@ߐ~#b%km1c7VRC |U%{e,xk1o*rP.… M9"w1ck{ga @\zزx =Zĺ>CLsl`ʦFcCC#`5M\ܶahQBe1}.@ߋ?)&C 1/FG2ㅉ0ȋ =;/^,h^hyhӚ)C_Co @/H3! ^)t<97orzʸq+$ěy9ӗfqH\@ jӿ7@>KO\k.%>G@<ʁX!(DQ9o:дi wzȑ !7`uVi%ien/WZ 7 Y&n(v)zy~y3,HĺXPx5m6kXhay$xF.u;w}ζ6rQuFB@%Z@$ؓK?qpäɃ͇Çf1LY@nsb񰳮QɬcC 714i֌9v-ѯ,C(9_)ۼY93XKy{kEW %|Csfޛ6N<`> ڴ&JV@EC VA](2(xY_Nmǁ5SJVط^v lY|/g̳.\~ر$5` @ij .DΓV?&@ a̲_[?!Yޘg `֦裏1nBЂpEYy8ƃXKp ·7(|ßmօ^PyE<́)gAKE<V)仸A\9JՀ fq͹қ>Iބ`A^'qd, "^̻iS(\r9n\'1EGes vLe͹&J0lLܬj 4dsLppqOſo]́se0>.5#>ŸNd|9FL ,moBB ;>'N"?IP"ݘRdFٶ+钌(Ix8}&J%ۊ|vM^Z[`\y=x8pqa?"&q ŅŒJpCXyr2(IĄ% =Y[Xk;*g]PK.&~~b-!:d^Ȧp.n^A=K Є|m`͞'$ݻ%ɇ807~5[<$ Ѹ ].*7K k"?hmc}'@ze\`$ c1a29۵0-!w?,B;eBjtBx7>.-_ ӌ:o;:[%Ւ-C i\\ Gy}Oa k{<>[6&,6&zhץ\.>@ʩ9w"6L]NrPƁV+nvE06zƳ'P{ =%GLR|KǼ5E\:UKcI1쇰2i`[+LD~!W.ӵ^) ;.;'Nɽrq>sT.AܐQN>+#gLiSȆGMSy?[jQ-R`:=7v98~ܧ}_ uNBp ¡{PJ]xG+x_qLs .DYdͤd,qummMv69r,F?Kδ ̸@&Y.r/FyH%r '$}r)aLl9{yT(Nnyr+Q6o8$GgΏNʁ$dՖL|DٗNhW7[!#F7d60 ~RU?%=/WNb2c&-6`C9R7`n~oV5Bj kvirkϗaĪ x)Z*|PjߔSh[Z0U]GJu=p@Vc}L9:2yr[8xliMBIG7 (.׺$Y"(Ylc(B. H~m|3K-Sd.o}>0|$*0)ই"̤@Bw)]@RޥpRp{a$G 2Ѿ6?+M{|[{&/N+%ۣVwWZ>%.,P)8X.+&MjPKNj6}=ˆI:ֲz6dVՒW 9%O)%:UeJZ!1gɕJFMKx׉#V˯=jp?KZ\ҷCymFAyaΟ^9ɷ.wkKק0EH6(Y^L*Cީ,\5|z謻I9{Q]Dzv`Q[MSū2rNy?7I#4CγJ{#_xIXD;>o}rOp}QKp׾euܜ2؞׫][8rϒR)] ocǣndz2i.٢ o4smzswpޭkXSF?bTb*`_Bj{l>(p-IOT|ε/Yo6ML#uԻcUy2dJ)[9 z7WpA-brL#+7{п>`/e-IʤnEkK7#%Jzp.VǺ5M˓V)pZؔD}~V\Z]Uc\'K`TjYhjR2sIn,V3*W7?hk?c$OM/.c/-#Z,g+-iRshmPbOŜnFbn9Oxl \5F@awb.|@ڟPI*^ 3@5ޟ9:eOԄ5|LΪ˹J o 3bN)6-mCWKb "Ҽ4LY^5K&8y"tBuJ J8HP[BV*|2d](\2h54%,J"BJ׽b2E 됬EyA;*X:tPIh/ uY &*sTzŲo! ٺvT*ɛNnR̯'/[\l֣j%2ɢ_n KJg"բ6RL>/IR$1YWkJB 7xv}x}%.LI~'_:yMBsOe |K;{/|=. ד**}cT /6q^I#Ϊ5ێI2k yf24mlrX/}OdiƚL\);)ϛ%"7(#2!cq ^ZuP[|e 6'tJ7u LB݅> /5E[ٔ9t 6*yѣe؛34Vxe{3uErwY$Ľ)}?J1euc->æK&h-lU~̧.kN͸Uw߃Ǖ/ 3LX;ù/7-n ɥ}~u+wg~XS&L7$^v٭.^J 7fH*9ֳ"Xc1IVHcBRhӡDN&ef Lrz-mG; N_嚎Zˉsfʌ)|5gVՐ>1y\"o0 s~8 [9BX"Aި$]/'|%Ge\~kxbvCe-O96""I@v1nkE24kFSm\S*,*OL4]HluKn`އ ̞-B~M4^KED''Ȇݚd&æ' $ZShLs.9`@>|GYCWfJ2 }JM2Ǻ]eЀjt%݈OPg;n`qBCr+;>߲eqMnXe(yddTZFAɪ}IGk\k>CVgc~w;Wx%Q5Ѯԩ^C+=YZIs|kBnGF|PM~R4o>cBSdZ]p {Ft>w_}rÉ@'+BkْO_Oxh-W kɟn`aԭ?cQvʀ@uzYP:/5|V xa I}BX>[^w,5Hy1^R3[jF4eh^zfM\΋M ϞC[_!;5R ( zb^3*%EV(z_$qMU v ,Nh3plv>#3AħJs.nW[ 4{M?qV|ָK4.psGj\%4:HSf)C-U;R+8Ru"qR0WxMw RfL%)R&0'[>LI%9vo;W׀ E,9Ct!Hh3w*;WQH /z hgLI+e8V)o߁j81 -k̺wz:+KN+-M5%a{ۡk8ǠR|cx\-+ޚ.4hJ"dtk|`)DI¡%D (B@.\6+IG\0.bWqZlsL>LĔBv?i2>\jf96=^,g uޭ.^UlδNSH=MLR !9L}V)/X ;F7E*]ۨu~'\r2{n9) s8fTGjvs13 CK]WoZ3.J`]<$5ZdPmkdHڋ@&"P;ڌju?Bn,Q"m[]>.قUټ}[5[-++.\k …?WA-cgg~4FyK7X{~U;X-g4h?]~TwYG&p38Z%5&AzI((x~qgN^WSЁRJ>MOOY99#֙%yUڙ%\;~E>u8PtS9ue SA }8bewM Dh-Vm:ds=OMj jN|넫S'n2rH+#g@;YYЕU YvTO˧1 +juX {=\ H-_%R#rYwWZ)pu-K Q'6lY :i=L-|ݨG-,/|4*nqɠŠ nŮ0eCu~i"S-KY]{'Bʕ&rΠXh!-/! b{YǗ7K*A}svjJ`zZLFٷp{T-S%u~Ru9zLJUtdiSDu |LRo}(JF|^7q>wҭy]!opKWߒpC>)`Vp8+{2_Km+r]&C8VA] 3SR\kv`\gܾ#ɔE M;|UO`RI˩0xFjש=D4~ J)7+󝢤Kaʴj/b3*p!$<=7%U|pܱ{ A(6ƺ%},dS39r'~\QQoԕX-O=v}S^qNEky8={|tS`U!hPy!.bC zJ*AP 9/JJ H[ՠ^NQ޽[XY8`@p!@LQ( ^l5QPuC;1{J!,n䖙L)nuUIUwH[$,BDPDQ@R IFBnإk=wwvvfwvbwf|:8s&.ub KU1%yJ8%2 %+AZVjt`pRӢ9K<|.h 9H,{mH1gmC R:96i7|WK4o lfU:ujMQC3%ma[΍Y,r倚 iV:pGV,_㞙o˄ws}j@JT\$խQ;-q߱- jf{9j/CV;{\q#r >:'̒EŘ:l.[#"ecƕke0T>{s2GdA<"=Z&uL>7$^ >i}#I_2R2#C:3tAEďQPg.r #բSkK#^u3~ȈVJ޹NM5cdWU}N#I"e(SÄE" -#@.N?5 qJuO#=N2]%㾻jj:_A|jAyƨI1τ&uǭS+.e%$$3ڙ:t@~{M{}xD+h\'j*^+nn~";fE.C RfMilO0Ja$[SXh^.]:Qv_@a+Q8si%GESƟ]A4i ~d3[{W ?D( PFAEs^~'E=OiL d>Є_fpq4*c'wPDa #˟'pリWs6W#N92OcNM ~S8`iw߿~~^*v#Y'}LiϺ_u*XC}PP>خ4."I{Ry_Ź !q-ĬYq:+tkpb>_~Y"p]KM:3 mt8FeXOz݄^CO2R,N]Z{QuĄ0&P[EQOGY$f|2z 3c0м ޺um@pbh z@G3Zqa-Nb6(jc4ݓBH \bmˢeҘgg=*Jc}{%wC$YT0~صϻf iOL)3~A>sY[M}7%>ftQ '}i'#A)I<Tfo,qyǢH]l7dn5 Z,s2|~ߌ +իؼy3]ˣ`OwE6mРAե Dи@Q&DFNL1T BN%ҟs/?[cr|q)=W~A؛*90&{ѢV}koաˍ޳L ߫=Q;M{W`^1_Ih@ 3Fj"M*YvUs97#qUoEc8ΌD#=πw^4lPFut ۷Ǟ={pH4ib .I m ?n 2;Rj m4K`s]._#Y\KX!e4 E;ޗ]DJtgKo֒v\tmkb2c[-cDPLZnL-ZϣYf8r䈲6 5pi~!&Mb}m۶/d ;g]QL ͗S&=،3LhY߸х'd#0c.DW'$H4; |%Ѧsb$oo4>1ApVޝ3b~2&Z%;ŌvT1Ӳx!PZm~'⢩jMRnlkY8SG!kٍ7p4jHܨQ-?j#GWڵkڵkܹs9sr=W<4>K)4U#v HYF;g3b}QLA~ \OESuvtZסp _Y$Ęb*"& JCSV df .L&/!EO;/˄[Ѣg`.m?0ct! jwƌ"9x <״,&4->hoV& >}Ί1#$kv5Wa^S*TH쨅m Տ?̏[n!Q߂0>sv1&/ ಙuG3eqѢ||[)'X EJ1a8 'N_nqB bN6aJ^wOr]P ̲֌kc!$}¼Ri*ɻ=N%I] aԚb ubqnP 1Ϥ8h؅THfL!7JhW;;DXDj|~MyI| ZjXf vbŊ)Fƍ*vލ3g㊡*QB*cǎک `РA;v,nݪlϩ FrhLGQ?z,^!zdcTd'ͨLČBMp#D]`V.S:8S-ȜdaJ?EMk@mj+6XaWMxS&Jܴ#c5)9 H ~4@|m^b5r+P~':wˬϖ$Z(e-Ȝ۷ ~}iӦM*M4+]bbΜ93f ={v,pݺu?~JK+R=Pre|8GFMF̔)(̑_b."+z,'/ʄ$:3fwRelF%.b]؋;dKi@";9dY?},fnB* fid0121 4!0Ȍ L(ZH, Q Rǖ[Ș4=#?>,0ͼ9(Q8f)fxNÇ4iR޹sG J2|؄$$q*0S?@-3eϿ %ĄL-2)1^ IlnMnX# KH(d0e2O֦ˊ \)JO f8& *oVhvۈZ|SZo"Xƹ"4ʚQq}Ӥib5D)6IX.!`H)$Si.Y*4!H[37r-7e@Hv E 2d{`y8r\֖8*D8e Oz6>i9"o\")F@#>>ƺG̔E 80;sA&"M> 8/Ž4f-bRn3>gN|,Iԏ? pS'9j#`B1kK#ZͰm"Фh4~f$3Xkz܌x"M(!/e[Lō'x,2<ÚV#Int⸚E޷N  4i4F@#8!|z}Z q}'QZvn fʑ/}W1w.T#h4F O0 XM[Z`ʊY÷pLuy"~[{ h(TnuޮIh4F@#'(] 6츪|({M펰߭+fś]7Yw+GW”oECU@.\ | tQF h3"k4F@#D@wsa (ry*9(YBτDk*>U[BV2to?D+D*Q0J4!@IDAT1_5 KQhjPo5^C@3S^V.^5㜬v;$ ܚqGw[Bi%&,|, ``Fl&+ d-uj4q2=TƝ{O$qΫ~!PbĪ>;]Z薼){E*R^H[RfM|YkF(3hTHOEM\yce\5< Ztqͮ#'غˤ>.^Ą<9Maq0L#ǁxos=5k"@&)N&?Of<._63S/b6%f3d`֌x bZAih1D{2I:y'4#"M̽O^'0*t֌TL]g#P%,_nZGsih 0S#&CǙc~} 1ZUW̅i!cW"fڠk;$zt:ڮbaCuiEڷ0Ͽͥi4T n)ߘP/tIA#uR&(g$zi3>Mtًd"Zc4Κu]Ph3z1GPףބϚEi+߀gŵj4o4cpO:77n"Х tk3Aam~^]Hx 9nMkWx,{GAB񩒻RsynI4H~T،#kN&c7Y"Qc/k.8q"\s֭+ ]&@,EefN/? 1bWE kr@n&]$zK=Fʻ0ң@ׁ㧀ߘ7> YNzPL mVV vP#hC`FZ>/`Μ9G*U)Sp @lA%3Yd!T1O/:[ݏT*-#M!;w^Ϟ0P5i| /?o6h[uNq &&UBd?UZ]W\{j6g9_w>2a 6k,];pm$JgĉP?p^ UO s鮪%ψ)LX(%0G5z ڎܡ8q*vHݥ'n{hy-/6OX!L\RՂ+5[.0[,F;:B}C rb$Ǯ&,[ 1A)ު ?*wySƼy~>}͛7N=l2ԫW7oӧO1|1OU\runGh| (͂FTqfEp]4jgYKxx,Z{/*UnӦE+IGPBU޿6QS swSz' _lk$1+ϖŌ %wd+e1Ø_uum# wyPMw)EWyw}xr!|No+ yP5ɍ[ęet_6,~CڿaqYgsoc:xAU2_ YVɲ ί7 ’Y~_~7ʭغӌݼB+O?oC 5z䏈t&;,Ӹ]0B>x,K~#}qN4"AQ"4k,X!9dɢU߿7osG#>6n)S ɣw4Ԏ6=Yf3 *^ĹC,!Ni<]45Xd;8i%{Gzs2Uvp4Q:"*Tύ I[w ;}JK 1s4x𺚠eZ/43%nPOM%ޠur!~غzߌTA8!B6HJ[aDV"#=yGcT*{i~)^HS&^ĠŹ:9jV˅5Ks0cTyeKmeV!\C\i)OF"*@\1|VP`ԙ A<)Z& |m%'ImKQ9E&oxJ. u;֝B;Gj=;`?iLckvp@&F4 ܿz^6mN5Vm<2VUi 5esh ;,cG>kT_,VZ 5:݅}7o>Q:El1԰/<lQi8C {y?_> 5.X;ce{b d9?ָ1|&wƥf͚ݻ` j`?f}K.U*4,YR/]4^~e%0}F8i8L$8)ͼ;ۡ#!wdʌgGPHF5 vv~} 7(Jjȴ؛8{TM~m8%lȚ.IHo>|"կ"eVמ`tdH[a!3 ~/AypT|EH}?Cf }L2b۷ѻp+q쵹}x$kY5)eHcNdƐS. R&rf(ɒ6 zu*Ub Xb$NTiz5*0]I%WYx5|9z?uTX<*ͬ4.BfL{ KןV׍l?GDY "){@|Lȷ@4&S3Ŗ:Z_gĀjxb6uw[B˂CD&| CHڰ ?) cqc`b<3aygkZk"EPpaUdӦMM&]vFjȑVT\ݻwW>U^0F &LI /;La&ݯ(!c@bl_^ɡلoVkN!qdX1v6zv)``*"yO- AFN?x˝*$5abHS'9g/ 'oK{p2hE<J;gYAfbL'sķҋaO. Jk',mfnsCsŏ!}.Zds)_X&2'qBgYJt*5c͔۳Pߢ(׷g[BƮw'gJ?O۾YЮEqWc1-+%*S$n: 1Iu@l#z(c$5cjY%8b;J\f^4|U8H7^ʞB<2k9s 5>}71eh[\;twxFXT?1 ^,ŊCѢ >| H~5kTe_>VgΜO?mbD :ޚѺ d%Z}J1LW6@+YbnL|0'H95 %GVKo:=uCKF"ΖjϪNLȥΡx%!Ȧ3%s1p4.!I^BРu!ߌk韈ȖB2C LjͿE9O:^m#>=vYq"Nꭔ.Yţ$đ*_WLSfE~U͘>[cO`3G+4CJ|oQ9!wh5b>L 7+X/tj_=D |~[tͲDi*u~vDomM"Kf[S 5sp`e KAS qZ"I/S&V…Vcc-ώָ10L%^}ل.-ؖKڄX3-s7a3o vu+E_TXBsI:r )'Ǵg)->G=ߟu~ԲUk1gzv)iDBk9hT,U'LZl\q9%xŗ gjRĝxÅbvu&_b1ˇg;xPJz\t&;P9*eJ]Vs1J"_3~5Vס*$m/ʆAMOj0wX GhF^aR^EmƦh|PXt-٫N(ޝ>mZE;\?k·Ws'P $Q:aIWɖm==왓va_i"c"UdKT%{D$vPPwB%Ʈ%1q{ow#~6%xcɵO F食TBSz8xmi=lZ/Y%V'<E~xNsNPj+ ł!UQH'L|PEl=Ts=b+a*``Hfp=đFc(S^&8oK9,*{Լf i $Зɠ[9@FhxCk+FY mJf]rdLʱND@ܵnjut>Ode:s+~4wPYK V.:~d4 Q/a_*F{˟+tFaERc!S5?Rb *s(oW/"d#O*P6 X;u 'JᬄO(J<1Z{nLm/]TGB?^o7vyj d[Inz 7I|߀#'y,"o(5Ǘ$v;s:X@gK 4QLX#1hjꎙ}Z!01 >:L"A4`:Nblhzr;ORTU&e;fǢKg}. #-~yN"#gEV1jQnkO3Lekr.FS:0@否f4 yE!#ж_~s4/3n\@tkhH_uȴB8|ܧŁmx5s$% a/iԐc+c r4&1=,бep]EH iz,榉w'^nFwe+(_0]{j&ZO ,Y2* ^Ζ.2rdQqk+#k([3Rr\nD\,=su*F9rܱ,aɊe(azbҤ]/klv܈>◥'Q媐ş ލ%/VղE)!M e)=:/ ى{.Z5%kz=+f+ jf ~}oiZ*LZO؏_ S|/6bX2^-۲m4%XZ|ukY jCKeT-S>V}@vXqn^(NymNCFyr;[fM5#S"wD;NҚzS2f4- B%$P-n@ܺpQש!C[!#ێ_VoNqr{Tl>ydA1 SZB* Sa>jU6: 2HU**הaU?t+̲V3wѾVcH_6-"Mʄt6l+' XI0'=5\yیٜEr,4ENR0j$}F fDg,;bވڤ@"3@ZjܷPl>~*dp'W $}^7GS:eə5fSQ^B$#}Q$9zh~Z= ~Xy(':d rԶh^m _M8=+kdEJѲfv 6<sưxas S>6 :a4Iݹ!3eX{lhT"3Eиb%Zq8q"Vu2ꫯ:ɓ'9IޢE0w\ у@d 0Ӛ)8rpbm{^vxs+I{bG#Q ň{([S]}d7ٌ@V/'E{U 2 = oU@lqUdɠ*-=xh#7X8Xix`jŨȒ76ȝv5Q\W]MNj"4K<,*5>@piz 8qWA9J("E,k.|{ƍQxq[ Ⱦ2:t: uU |A,BI}c !N-&Q%>ӧOWիW‹+mȑ#5jxg̘jժGZj)v:8If[nJh(l'dNnq*-]c89}:iW,2-D]xbD#dH1!$5~ _qfk.9fٞ׆- ׵q# \J3RF>`-گ9)kE0+%=zs}Cq%˼>>35sɿ MH4č` 2j8ImRܹs)}&M&MԌFMҭ[ I,;Ԍn P@1|ҰaÆ)"5NU<d0^rseCI'$єh k%ɤ^!{ω NѿfnJCj@9k۶2㤎Dm'giӦUYy㟽<5n9 ݻ7X,qK;JI(TzwQ QߘqwiӦwߩ:sYϞ=I"{a胸 kL)L3C ,/P@&wϓ<dp SY-'swm24O1m4d" R8BEď%45!Exv 0Y4F~nas 0@O(7|{ć M#IDd?upR]Džʲ 뚡2t:gғȏE W]f~RG 2$,YE޽{Cd8h&J'2L5'E%='y4)qFͣ0Nq_pL oD f.Ҽyن:g#Sɶ FVNqФ p&>fN7oVy)A+Hwa$I1,~:c&R]2VȀsf#(Y0c5jsj)̴0RMpL57,kiMBOX׫}_|Q5i|_oǨ|( ?6ZN135 sACq!`]ϟc.KZCƌC{ ZqXHǙ4l+gΜ,.QMb 4otdo|Ì|FFp)3;q+_E"}k(J:k?0Թ<MxOlI̫Q fXq?b,h"`ěD " )mㄊRHJiNHXdȌ:J4 Lf\O|'c$)m)鍭=I!Qc5JiG 'PiD>'34&{fz DfTs5#ep6X3Ry3[uHR@S%J 2u<=;Oɑ٫RPEm54+#QE4Q {ykm0K֦ I ٌNI-jf=gDK!"V9cЭMKI͔u7"к!YKmذDQ"G3(>~S#,5K$~p SuK1fD~di(EZ'&l4 rhf Q IZVSzhK@9RRo~iRA? pYdPD ~%st 8MhnAR_1rXPRGI%?u$Q"%dFq2L4#@Iaʾ3{knwwȐ!L[ <'Z)~2Lf֦N>d& 3@2Z4ߦA3u2̚Adhokf49CkkZ^#>/{k6mm'Fu7L1-e24_Lc]#\.SHʕ9-vęZFix ~mŞA'ɐ0ik%3e-A$@h:2\-E#J@0C3͛Ȅq2O2PBi-au!3{1SF9$juz()`_5S֒<ۼuyܷMk{]k4_DcA~D:ceX7c:~[Fy$Ib5d`BN8:"tثnQ 20tH˭2"j#|`4Y)].">!00&|#˲k cbMF^0jй2|tQbo}#!M"3.gƏߘ]v5MGy([™GGdJ _!ۼ[K t]Fxb9p`tCQM<$J/2굜 e3nvF[{Jďl[Ö!@)RqeQh:Zw~rJhAまG;xЄ-Vgg)488yVٞ4yb! &w1܄sSRD[L#/ ZW)F4Sl5bLmgl0R,Þ7ϖ.Kc8鍼HX6 5q7("FHF@#->~|? _jctL|ETXDٯU#v3 ŕ:~R k/_S#h4#@ bIo3})Hzؘ֊ADդ M&[j5̌4MhZ53>>Q7ՠ>AF@#hMh-A)x@Nm-}S.U#9؄M" xsye F@#h4#MJQF 6"uСPcqҚ>i4F@#[_2ax3NZԋBfT#Lm>3no\F `L3_4&Ԫ=443=luE  TV{߽{cEʙ%<]F@#'+MjB֢,ǵ^WqTI"pA_[ J$ԫjgʻ5ыM@qDmGwmcuhY0^}'e?lsm/Tߌ9fnRUJYb3oًߛ- f.iBwX|[ך)_Jt4N"@S@D9WlIF*2)RP&o*&/#Moゆhqۄw؄GH„T)T@lSzU { u]n\D3vpdd M(.~}HD5I3SэO#a8&EfJSE9H2e.+S+KV2Q4сOav0a:H+ SZ&Yt߄w/ƚ+C$W {R$kf*nFe8s玖`ȉ۷'*d&@L!@F?CSEU\ Nfˑ5.VQ#LD4e⤙4ifH&Mlj+;`}~L#@RTQK|bs]F &5`7nIkʼn\ܼy3VjF*N<~I2TjPkI#hf*[ݳX'$kXz=->#nBԺQKĖ;AfVaDf~ƇMu}#ԭ/-6]҃rDk 6mZ77YQ4 6˨j"F'{aD 07Zq+T0pP+qLZ4MRUzt5"Q3?Z- )?HtĮ8Wͤ4#Ǹ3dbm\1SOÇo='Ա|urW]gm'p_ }~#j{q>G #O6k~cü@IDAT ^AIch~.W̘Qp=y"u nFm8\F@#x$0JWn?B e3VwçhnY.!L9sj}} 9gy+ya+Ȝ& yB:MU`tQ heIr-w"9w_Z[V /L_z}#ݦ؃S'!c-=cxrQ8OJ5e҄ 73Z 1}MT鳢A<ZA2)+i: B>CcX$RfNᓧ.x$"Ὧw`JX,wʧG7s/wfհ-~=u sdܽMS1,[/M!@sCm!0u1E Y%rחۢ*|'Oک7;sȄ%ҲXLaBTfH-:}ׂ8F1 ~SB#ܺ-AMȒɄ%WJE/cTwsa (ru7)x~?Tds+"JFl=m,s/*2L?WǼŧ3|ܼ橖zDՄ\R#]Dxzv}iRғBiw@HauʦÈD4Qd4¨(x[R{.ӷ+F$_j4?GBfJFEfʛ}ek|_Nq(Z {Ȅ eڭ 6[_EW+!`̙p$e/3F|\ƄÇY8&Nr/V?m~fucXrWM$q$b{KVT(uiQͫgL}SZ3kU lU^Q!edKW>ss\&uwΥgW:88%_g Ǐ/qY\PرcXbdIX@|˃}?wʷ W<-SGP9N;p}<8yxp9.TwrYc"5D"e9mE^V7B#)N>]]ޚqݩS$_MkDF-Q#7my<%pC̑mn/>BT%WóϘ1ݻ fE ,c4w\|w8zU)1{A̞= Ģ0}hI#@!iҰn 1\OcB OdHuj\C W&{]VfDh,ڵkMW^T0vX,ZH_N(kSB;a Wa:4~1LSAc!C& `kjS ٖ-.LUkTy [I#.2ꚫfFcj2:$2SoVZ᧟~BݺuѺukΝƍS6mD#D&H"/gq4N .] F]p2eŽ;YT)={V?x`l75N,-L)VV-|QK zO!g`!&o/~nFLh?ۮ[?UE4UFѪ 7.K =/t׽=J)o{5!7]t>=Eŋ3СC/ad˖ e˖Œ%Kt94jH%E}?iӦ-|DY*(qRJX|9vڥ##6qDuf|$ȄM0A]믿bd*|E+툅Xwp2 13cЗ߫)W ybA]*D떠*=hiJR8!1.9sKl`>sdx|qΙu!`ʕM`A5*t)-\ ߛSLiޗ:ujv:*eȜ9:N&MJƌuؓ}j7o^eȾL{婄GfpF#,p6N-$n'ƾ5%H@M`d?#FoGx[1tRկ__M4I݅dS_\]tҹSԜ:v쨘8)-3gfLBMw5 ߘU`&KYJ5i 5+Dxz=LY7~_plnY"ȭW'Q =ObYS$@ @ժUCNs!'vTF ZJ/Y] K }4[5kD۶mUvN2 R۵kʣOS) /N8TO!o~dER@/q4{Ҥgj 1o?{_DČbjjլ-.tբWTRJDЈ1?Ϲ͗{{}_nu{}yG7o)y`N< X・(e\LؾqѡcÅh)ŭs L%Tge_ q{xx5(2`&q w5ێ4Npi`@A b?:;FP# ߾sN,#p.7lL1j́k >|d"/:13)5F͇hm ^l [."k зz&Y tlXDX_>R:vNHnؿU~?g5GF͂qud̈W/V!иj)5[wkȔj;ފsDmAkd}r#.Bhd5M >.SE@vOZHO>8QbFd 8!ED@>,u d'-juxyuMo` swЩ~>d5ɅkD:5,`.os޺7 {gkp-$ )Zȃñ-mzٰkw)^e+70$?c`ԭ|~i![sC.ౕryɴ_~eyk$]~0z#Gd&fo撫Wnܸ!x6j$ Jǁs."%S$< dð1кVdҪ@1xK0#1v|<a횳R ԵJT_{7%zon,_xZ+1v)A9-Dw@^[]r?W̋.⍡Fp[DVEVxܺ.^l^s8~;̄R5veG&%-<>{#vNrZJ$֋D%Ń)'HA'Jθř@bs&bՔ݀l3ޝG}TOǨ}Ȗ-=&<"TGޛѷu/g_(>bcŘ !WŜq  l"\zz/>} 死Fs a+~u 9xGX ڃ]'ХcithCE`˔)&9sc _x*C`Yqt}X]^*}gS Na7ZlB1Weqz*Աs F:]/G4L%^L{3"'-;{X7z w a UQZXh"j X`LCo]v… W_} ˗ѢE re~gFQ~} E{4njsh36W#G;`0#jJӳ ybŷ ؿ,r \sfW31- Bsq)w\]qE=Po^o򝁸@_+ +l1'~UE_@/"۹ǕJD- (M%+ճ,ms@i,Kd<@`QMq`‹S5T3W]67eZ}d¡ &3B[Ч{9tk)E4W;KÏ#k~GH=6Mç[-sU(텩.MQ$Reɛ[ԓ[Y|r?]&/nc|ەU?N 'kXMM|,@ ~sǽ v*as[¬qo* X,4cdˊ'L/KU!/lD=}F ;v}^Y&xa*r´THӒ ӐUXɃV](Fph][d*7_d xô(do#̏D֧OYA;v,J,)VժUs`x|=_J g+4GEAr;iP] 䱽<_'\Xowsһ0;2^bWɋCeP0 k.k#tH1=FP>kΡlaOy~Ŋ3X_t_ùMo>5o}j;yg4v'_ĸNio&w+QuOċZS&W#$$DP߹#TP@y-%7(m$P0-jmqoز=ƨ}16S>ׯMYX:9CcH\ɃpZ,<0wyi+Bwz&j|9kGR&PioJKo7kT@.L{)zCMf }t8JXp4ꫯ0~x%Mb#/^[lpkNg̘6m֌Voj:PIENj"\A؇H7>կռ9)E_7@aǀG&!,|Y<79 Sh|ƌ.#xA2ʻVOjͅUsg^ #]_x> UOHvYgՎlDMT %q?u͓S/{N)$-SdK݇cU$=Q2EVːI?2=3xgɒEdJvE|iAo s晭8^NҢ yێ?Fȧ~1_U|1f +,}G׃mV^G"}/k-?~V/C&aXhcUm[U]Z歊ⅷK=<%e1mI-Ǘ#w#*xBD`XД<9L <ģzIQ0?f͚%}1tPܼy3JPwyyERe===4&~f{GcOwV:Iֻm3g6ū*>,_/2fC!%aIY 'cإ->ôZ斊Q-Q|sl$3ə2=lڋr ct<[Gfw x{o,Niǹs6Z)^֮D=U,c" Өq^7ح_z5N<)(.rެYdkuBAgPb,!#w'=- 9qB1 ϯ]6Mzr1PV5%1Oy>^| s9}Us@s :Np_ gDfo48D"M={\W\>7YY?.I@ Mپ ]?VBp),`@/h9sF+kӔt"HD`[@p%Fֶ]9.,ͤ!{Aۺ@8y)Vf9|*X#MY0zQ C@f~4sl۶mDMb_e?4=$qb2tZP{G2|9A(|3i}*DFaoS xXMM_ʋۥ t},qEgAkCqٮ`xrF~"]"g\Ê^OE U"s5Զ%.M]Gsi!\VCBl)vf~|h>}!'pEpIs@s eq)L~J.M fo֭2J(SD D8j hvH`ĀgҥKKϮ]d xщA%!R#2Ub>y3' Bf5Kc m8x*CpǏL|Ho\̵~n!WA8!gEzu0<?PT^֕ 4 Ԩ̒%f%KYBD@2ꌼ`M1sJ؂>+VRPbp|JER?<-$J9K85v,xrF({JvoI )tdORGFE.Tҧ46iA[DXAx\6۵Thuwj󿭾u `̆k_ZI8qj_׌RK1x~x oOwy-_,8{ca2XXO 򑃟H>>>ؼysrZJBaaj:u&&HwUͩ,]~G HZ@rSJ:4ih `I-ﻢ… Ҍ\E?/FL؇ @)CVw5L/K큘"N\NBر5;5-WinmPL]'|E2>}@NK*er`~c ;[f 03(v^hkZ.\(?Mf2i./]Tr GS,5duVm"c7dI4͝?sT8f1(dĉ0ł"{a/^Twٲe`7Kb9-Ӥ2&+_3m/2?UȪy?v:/2&Lwz־sqo2B@J^^^)azi\XYǤy(~Q\|QE(֊ mč%HKGGjZ~HG4[;9n70upP~+\FSu?n~m.n=nMn]REyx!phcZBz'9\p\PW~\L70mV ?ɷ)իW+H/. ɀ3Æ CڵHSdIYרmԔ1lLؽc9]t*U@bQD [VdZ&Pu89sH܀ :DV7)`JI%ר+`T=Tڎ999Q({础YNڦƖʓ=jV^¤^rp'EB UaxND2h2z/_\tSCc-|!H@/ qN1_޽[&OR[A0jjH\S[@ z>:t` ;hBFBQ<-4裏0f6W5|p9Gy TxO?$5+7G[:j):u LC7e9? S??̕G^XeuW_}%7S_6l-iS;yJ`ŀA@[m M&xƍ%T9U:LUE@JS)c\HZ拲nJ,ףyacڿ`Ҕ6kVNK<PB"~qNRJ.|q8Y)wRE`@M 5L/@(O+b_ԒC<541csֆڐ!Cj2BΝ1"0\j6v}V5F H#qޜK`;.󦖎DS_j>-E)SFjҤvq((R(/S}6ǚɕ\p0&́mwDPb_{W5s/!JԺ 4c)A\ӌZ%7΢z_Uj!1~R5#Ԗ+&wy[`!Yd1OEn1f͚([Ԩ͝;WR;w[]aS;ORb{/=K\ ?lqj~TzLgLb1i|,ot,tL S,l`Ic/0P8B`Ry3~*M$^/#"NyspqP Q K*7D5􋠶̣ kQ9<%Y@( 1B= ́)+oFM)#0À\80$%H[gJi qA{hj(Qj1T(MRټ:)iK0 t KJ)'QzjIb1 +M(^|E &'br2,)[vyo7g#.Xͤ-exR3f>hhJYNdUf~r+WG]dUiTy xvYᢝ@HQJKr%#~ B%j x7HZ<\Wjͦu*i,4444q)`*/B@m5OVޓ@ł5'>J>.UB[^&cR:mS\`&0TDN*JrGPLc斠qرQ#F !J.P)Hy$90r$F}2\ [\oz9@-AJIpп L)%p"A?YsMj77w,ulժUp,zɗNS\iJ`YfIJ\Pq2դD)IYJ' GÜUXt9&jGk&}$4d j,i E2j'iLE;E͛7%I'x)gt#&0y/ߎmзβ}yBH`&wRm'Q0Dp² .]w^RwZ)jCBBARI9999`ׁۛk)DE7RJќ EMM>3i8g޽{یphIYRH*T,%NM"E"bN R&)-NRPi:uKXw#0JiG*K"0eիMTlO#peliӦn<< bQ@E3X +L^gksGC-[:7H1DTQIs@s@s@spf-:Mk V㢀QhssΙ"ag&((HgjӼHF`ٿewdqりþ}J:X2QsgI\QO|0b_V¡CB믿Qj:lZ+rV4ay+Qj$>TaYF꣰ Z{U.]ʚ5Hi DUQoOQs@s %r@c̔Z3c3+G9#\?~J LR'E$\T<%\06h@(^׍D5JL1bOoEդIY T&TI)h:cќ C75޷Wۖcu޲\r8.s,RL#LEwMQ%oJAs@s 5q `*%/>STsa@K_%Xafgq|?,\Pj)E7f1$thhhB)B>q,E:ό7Q=]~``;~Vs^ڡl&||^=#7ψ[ٳLyKQ)n8o0弡R2b:)@?'j@hzH)2M޸Gcy-縰)$OR)>}*bO$}uU2*̴<5yg?WCoϨk)fvӏjΝҏ矏"tIscHjh0߀?ь;PܒXU [SXZO"/@1 iac.pł H,kr7ayJE,Is %sO'%O!Nm1}YF[nBY_}>?1 S5{g1*=t́SI}ݷS8@+~/6tE} Z,=[kH)flOF"fcYԾ-Hsp<):EbqȆs G((c ooocz?q>ZTPHRd4D=Te-E'5i0@2߷*! hM|1-|?egAXۇcӁ`\`ˎ@s=oc\MhAxfXT/MKn>~}<ȖYD |vZ)O<_:{[+Xh"жvns 'CаrNkp\ޙШ,˰uxyw͇<2eH^q,l21t]~>[iפt KF%,3O^$ \cSL:͏2hvwz LMPP$ő2&;ED0ck1:'sq|Jh8r7oIU'͜9f4F*88X^#"k„ rAԶm[ s2J,wՔ8Q5B=*`s.$`j޽2Zn-Ǫ1UԬ\R4bf,W%j$enM=E֌*`Ɏ "FPŚ!԰@dC_JMӫb1~3QEw QVEE"ZHG:hU#RY,ȏ^Uq5!TgQoѱ6`*؉/gePtLTOr`(T O.eѦJh JKvvP@% !f50hi,Y~?NbZ:?:E<УM Q&8Z3-wfܻsV{VH8B]̕܋beRmރ^ѼA!9}Os󖝗_/Q6m!Y=#ʨ|з!`iԖp|Q339_G4,O_$(Q3!:#2"&iɒ%\PԪU+ٗ,Q(q|qiyΩaÆؿzQǎ C`'GQL={ի圙:bz;e ` q~i >c #+ ߗLw9 a yҴݗL1\y ~Ru5($$Dv%b>}İ$/?8e?54W:w>ތ=*w^l.>/IT-"x[Qx5l 1* !WŜ˪pQl\Esb`Hz&Z1-Ί"34)-/]z&yDQXɎ~1eE LP>[Pp6ElIf X.$¡gτMJ Rw˺Z>z8ϗ3#͌SL.84>>8}V|Cm A_|9_tI+VLjJ@#0;wpwI@F%2fg2I6]\|)`Պ#M{SrKnjդP^?* @9s`;> 1?!%1/V=񚒞\R{Y@r-!8!Ɲ$|25U$Tx}4(Zb]sCOfQ -D+pwa*'=; Gr6_}X+Dʹ-ӽ ktShPKy#k$~qT-Z el`wuPZ*PS2-kzBNmj;duǎNmq`n :*ޯe~$`*605%c4 rl/-JQ12i;lպQ1-}KzJˑ 1-C/S#٢Cj`kx^] bŴZ )B'ܞd2bf2ITmųiKM\'>)2Ԩ%MG2aŌظ2n\L(_WS ?/G_&j>>e7i ->P/Ed57jffs@)}*iHM]]sWMSiJ]טfdÆ $@,PLrD@Ri@Ӕ|)SF?Xձ2PժU9!ie J/lM,E 8$m'߯*ʨ]CUFIJh@ŵkJ)ИxV=}>a8 ejH)sʖVܙH3&@ie;ݿisNU{hʓ'}]{2u{iV.a ݘߺyS>*c´(*̵Dy`̈́:8x6 O6m?YטϣKh]01ȗ7 ^ƕLZBVX3b=9tÐ7Kb BZUnP\v1@7_V_A<ô$2 ch{+*[ c0& EV/ѻ1=,9h2+ۮ*BcJzQA|!( SY{\:^E慱 _-M.D5E*"&5E*L75P͛7(ag}IX?C#qaI3M6EY46 @@< HlÞcWW+졩$1iZ~4 0]RdmDNq4 Tć1'HuYME&׉+BlQ O !2et*69"gEL.m*|.E XJ|z#GHj>h@ 9$lc[428{T( /ՖlT+W4 hNS83H`lcײ񘼡_\T;BF>c=ebi<'7wK&Ԗ7F>P/t M?6-}X\ ( e| ۞4a>e%f4)s&8,e0[-F o(wS(lMc .!I 1jDuIZ=pIAjX֧_ԏ*gJL݊bJO%%#HwF?eo $ۦ.28hأvv?]v9^0YyE㢹3lMI JR0eKQ'J`:t ?!TP *sUhw7!Djh^T xrlO-RߟiUҫ20ٲPLki^+&gzfElXfE+2)+E2g}eEq8*LpQg(?^bLXN؍cdˤ$k 9k1rUpM`TZR10⽊. 95LE/I8703`Z%Kf[Mma&`l')5ŝLPce$z44&ҹ@ iQfM예S+ZhgLufm}A),6phfy|fVXQH褣 9P^XHEnL7T(|EwF%Q0o5\#Ҳln)W9 r^C*̾*<-(󈰨aMEL#rGDezҰ eNKsU^oB-guV%[T,F e}}} ÆC!v7eQ9>]QK >99&9ZOXģ2{&qa9{,:O]zbjIL>wcϳ:'.ߗuo>Q=$Ωr[Ģu܂w6Tbҝ(GM8\@q,i'UdYk"-H`2.vPU}-MZ:1 ~ @! H]?ygzO9Q?C\ѿ`Ct\ZbcXG%,N}{[ x3^A`Gzlyt!^^cvnGAeFTn +]"ȧkIsEtPJ)GH,$ kE&7WCr9M2hVrWnz;"qŦ{ZH״CT%fs1AÇe4Aj /"OOB UM0;߳g{iWE2Q EU~KS3ɫ>xUA^xrFb`J'|Y]0j~@ %+&b2;tYHLp^o-<$ffmQg}:pWI}6)-*h~VL~Ezo/ScaS0峷dx!" 0@Txvlc"18uۘ9wS l[9CsEuN8n#\oYǐChSBf/~ E2k8 kv ͒ULP6;V]Bs~0y,25Tִ>`t3@-?HnN!We"I-D֊15Qr.)$[|XV̅z0b~VAa3uJ=t,Oq "AOtu8wăWQ|qIH%jԨ!s0-F|ʖGP$cy}rzZ_psx/`???.Rpp#ɠMe0'GÅe¯HML~dwZą S#g&}$&m]  D&a2LMI\^V*-^O ۘ} Ogp~Ą}*l눤$˄fzaҹl\:ϝ̲..)>P-c?֖L,JVzȤJT WE+C\bצ+3)I]#ճj"l͝zTς\p ODjrjs+"byX>-[vB&MhUX4 Ԥ999928"197oޔ1x(ėMpa|_%[|[C-QG_zލX~¸Rk(M]Ό[4!L\ rgA>Хi!p;3:y{uUc2GKy2wgΫ+ʀL,]5TS1QYfE!Qxߩa>2&tvdpQh>g,()\F4%8z?8 IT]2N.Owj7fb˔luiUTJ*Lk`Ui&D S6:779d9j|G@ꥲv;kAPXwʔ)#^C30Ɇ6l(ٳG&k$.999/(MW.? $ ƴiR]鈟I5J9X1b‚DGZz wVtta K% c?"sO}7jkoxUۘ˩}礎ҬՒ{0ޓ}Ep>U6q9}~=b L1tӖEѤ:!0qE2^2؃qJ^kTozFE+EQ,v%2y3l@{5p.Omex2j'!~Qo54m}H/?~On:v4FkhhhhćqMdﱵe?[ck/-,v Q;ȌZS9@ἦG"G,:$Sd"DRsJ}G%[SzUZ[vȨ|a3*fR57Ъh{e1F^Xx0) rUPx6TlR ݋MJUUPDApʕ+ Uz9999D$5J$r¶">nq/a[Hy_Hs Cw7ǥ[$[Jn1(w@J1,%[#"C[lƠ8-\0e52L7S;wN֑_.999X[*HxEH,>~L)#pCegZhHp> uAϘ9$bR_/5ZԈ?ԍ7p%STVџjs@p&"A3EQ;R'uLK݀'gIY1Hg#KR׍{k.s&vש?G̯`>+73LPD#1GILD*† Fm@?\\!"0T݄@G|Yi]52%o"9 څ6xߎDܘR*pJS{O:ɋ/D+Y5`-" JJS8}~J~YcTk3|.åF""Yj h(Gc?/^0 C}f̘iӦDƲz_s@s@s@s61R_<ɓI?=sjy`KsH͕?,K`#0k5/"s2^(x-$/1TчRZ;/$O1"YcePDfcE@Ǿ c3-ӆC!j~qTx[m#kR~:8rCi!tsGI3RJ*a͚5`GT6"(+M< K9sMѼk6П9s'NڵQF`p Mil2N v<Щ:RUFN\پLc_r),]vK_IdsF^:w) c^So_0MIљ>r9P: 'fqSGBd"9p|7Ȉcאj GB0}1̝X|m$ѣf=_b` M)Igg)U+`ytau\l&6Z,MW}ɮ`5~1Ehkx L?gna9cc7+A0kUUKs )?xc;`u/2ra҇vV˩sPɫ>xUA>GWa fi:4{ ыw?#k _N?cfJx*J*->6B'?8@aDn-Sh0#{1gΜҤb2#"4̓'Ξ= ???h_#ESr۹sg ݻ;J`h" ϟ/M >HK#)7qMR旖٤i`B׻wJ7ݰ'A%H_劙5͈{B dΕY2DR,˅'Fh\ӻt!S7uA/k-D]wQJhH H\5̥손O0}e,^rDNUjl^lS3p"]$?E]/6h.wܼǁ>GN/Q|y!.6J,͛˼U48z $a@ћ\ L4 :uMI LqUcqiH9tj2Sߥ1: DVbQpdKRdV!{ixdR z"uwjSG 2kD:h7sixJذ몼D9&- S#[v A:9CcTepj_҇Y11eNJD^`*G&BMOl4˨Z*^|E2/LEyxxf) @KO7nR l2"Ӥ9999@!SjSN;E3#iOsH?z8b9cK#&CVa_ ! 25+1i?N\o\f H#avgQo^= GŎ(aCՐOۙ=Th=|r5kV"ѻQUl,eCٯ*OۓCho5~PŨ=Z)7о=->>9'ʔ)#5n8f#ٲeOuZ)b?G-Mz-HA`\d&&ktvz ൞8zEt{BאTӨ2mkFE-qCfҼ,-TjϨU)A&E'r5vk&êșьT{v@j"atFΧ<e,UP1bҊfT?y|92[ʃ [Ⱦ<" \~= u1Nj9oooi(}G5PԔQ{|.]Zjɨ},444"J-9}*/)Rr cv/>*FLiCÒ[s H9η= ?v=dB7~}ўj AX\F_opG&}EQT/ekic[K~b F`h~'o]jٲ>NPIs?ܼy3}hvZ\rEF䳷q"wX4ȑ#=,:MN=1+B/>&:>t;ZǑuÝj2.gC'u'_;C>E775Z%8~I{?nYy:'aJ33՟Sv) \4BԢѣG SӾrle2FSVb8+Vd`iJ̼u8ϙE!ywjh$CP($>T,8I(d>LLd-JX?b+4Rx:" ~ ho:6D7Rm4 ܨ9JIܹƌWI϶fr%+:t/%jh9Cy[?.}A\XX Gαt$TuZѩ`Pe^ $Ebƌtļb4-Rms̕F(*o%4R;>2R|izjpNS@/Lx77ouVMϟ#ϯs#0|}':3ge6ma ~jOѡC 8\%ٿ<תU+L:w.\ڵk&ΑaQ[u>ܨt$ܹs(Wym9'O#(3/ n'0?~GngBUDzcGaNΈ"7"򅋗˗/Ery~ɐL(c~ˏ\<ǏرcܹsQn]lfƜ" ҫW/7o_ˀ'N`_}3M@ZS{i\Pǜ:%FjfMs >]0>rYDy_pm\R$VvI ٹsdGM퀑.A| ľZ)5JM7orarJ?D6@… ڵ+^ysQcIćٳ͚5"g'j @YyPjtH1 څFsС,p# d0sֈGx3ʈ\kE7ZZ;=E(UDado\TKm N|ԖycLe 珐?@Gm%9'!:t 4 C9v?iDpAR@J);|pZf KscH P+#)lsbT}'hpw ݽZX)B+-EP /bJ)Z\{?gټ,$dͳww߼9Ww֭2lx%15^o8 | 0uгc@ߗ T3pk96#"0xOXV.@c`J- 5LI]0@ \$ӗ~R?>77@Hyyyr @D=*S͸o^WD-ޣh]#+$o[< BY:y5W} S$Bzŏ7ءU=,y 3xDQ3)NeĄC H˛5X; a@pZqKm'%o\4wʶQmt1aq3ΫNAG.`>4$j7o.Ol\v }JG [Os >p@*>)?xWD$Z9X#{&ʇݶmԩM*GK%^]G_ lt)C|תP|[}ӎ.9QpFaHA:H :1J*%Gw.;v _\1B%[b#1A=d;4Y">ՂR]s-MsE*( "x"b D{zo p'ptqCe+:r:Ej\L5{z"޵aȰ&/:wA/^^ppZ_~"g4-kbx/)F׶Fcl"fʜ'5vy Lؒ\(łMUP""`'-z1R~3^A#~cĤƱu&y $AStdDƢEJ?n1n80>R<#쏚`]QK?6 2#iNX[F'} Kݻwf˖-3wɹBSFT ZسhzG@(s`Hk7_GU1kA~x}?am10E(r䥯irUV?[D?!P̈&$ᅴ%%}[ 9 jGhDž:5P4͢V^.hE9?|"񖧬*qRlݿ<|5ڛZ=;5byRrA{?VXAtIqcab¢3ӭe )GeW+Kv'{8%@3"cvx?{%MhԮ* FB"u&[^R߱z, q߾}U8}t E3Zi-|f`yy3f|~7*THR1ww4Poذ쎂' fϞmךrh=h{I|)L<`4] ~|ݻW:fta)II}8i9M jB v6M Nl>|zzz~j֬i(EKٲei˖-r 2X3My4%b  @,t+zaa!o)1%S[10(Fb.Nҥ4S`%m▓'p.դF?EjWNq5Oe@*_ZF)uuGIN^GrC^͂ͺ|ܲ)3(*o-/yyfIJ+9H|3 /fWRJ?NHNlhB}+ Fb%j֬v '>8R DL͓ )'Yu<QSOn5lp`6` |(1㤄/s%q<$&Ii~TV-yۃ~W$uD< ThWL@HU@M3j86.jbt#=a䧸92IǜokTG %5۱XFM] xM,%v$˻ 6nYTc7QX=iy*&\!%y;|VhW1WMlڵ6iߢEx <|BС(/R<Z [V bK!_ (!;#Ek ܴf5'@b?C#tʃIiѧޘyH^-j%` x_fG Lu lFi8}}Q^,c}ku8bnRbƗ%x%jbG,֋6ɋ]PhNM<$=C } rgJ7?@,U>URs9W _?U' 2Or639,>ނ܅ҙ, ++~^"`7SN. h2`|?1|7eE,bݡ*IjH,ȼGBD-I@G@5QKNA1^0j(9F4)S"t p~ }Ih#,E9խjYL |eZ6uAfaGlǣ9@ߨЮ >6MIeL)^4Y@?N|_R!.ǧvڡЭ(?-/& [\i,trۤbf4ZNc-yҤM퓪YZ#:&VHRDYIdBT>7 35cYbpME  L s@yPc 8\[#k9Ä!^ LmY(!u؉Q#]+2dh-ǩr]V4c/}=vsqNB5IZ8RObBjHPĠ2$j(I!M@JB@ė"|4fA('yLA"ϫ 6ȡk[Ն1*"Xc<,wY9&ߛ̌K.9#SsrZhr̘eGr /zZu b1 |/6m B!$X0E[`**6iH=-siOաvgΜq&IdRl}^'%mU'We$oz9D@[4_dM`(%X>{P]h 37il>pk `XGiv]u%?t'\9,scMbP;w[D͜9S.(NXV Uf`J84Mc5J`K믿p&a/'[&^#HU 44@IDAT Tի=M%@c^)Rxll߯ê C`G"9I4Yf@ e. C0Fm]xi`ޘUqy[ZK't'k\ЪP0 / TUexso'ӾcAsjf MʨeӀ)Ji*&BQZ}uM*eVVͼu$BB7+h.ghNrF͏,snpGl$:!SES@#U(h; \|g J~))%1r7.4,yb+ص{X9k ò=Śfz98POy.}]@ (["]ۻLuWCN2ښTZoCPsڷ֖񜒐?zU|i0A._E;%Kۤܠa<۷OJls8%rځF _Ru.Tޫ V.?x!>u "bc/wg&?W<=; yc 򼉌Rb'=-AFFN<4 9gzE''K&_sK(X<!󧍪=s͝XDTIN}f-$X6(xtE-/ZD2 ʇgϞүʲvIy~F bca9՗Hsw#ҟWIIStNXОKׂpAX05WAPڴ.+5+ TX<H>5iu@`nBmM[IB9CjxӗhW?gM /P,ؒ&IkxKBmӶPLpFbx]%G+Z ],2[=viR=˃C$z[u~8 w ѥVklվ{"+| _4͉{^/[kYK$|\;,i.w4lqT ,̼f<2 Hzz i\^479&r}WIsY8#`ʚ YrO_[0Brqxzî҂'yf{=#[k/cNw{PlF̜ U@Pm%7D>`Ȋ0J@f{R1,# QJJ[nj"k@tf jƧ1J u")q0%{0eK _J0?\]q.4} LYx O(x.qBbS& 2 ,&!sbKH-LfD^g/^e1g M1ˁmӇ\?#9ppC _FǺm544@D )>~ RlXSe of=x 5K!,,/`rR"F:+%Lt(>1yU@1}Xy;tbf)!Ϟ99N]76gwx ԠAivB?j "JAgD"eQ)vpvNDl+`"4c^{$TDĞ)xa܊g1Rjȕ ܔEoBg1aq%翛ohfy &|fr]<{ZMQ!-n ,E/mi4iU0) bDs+L}*#uV5n<|lC+.H+_p-ǚѮ%& -ȥ,>vHd),4K!{%TY*}\/]EBjs~~]%Sz>bg)!Lh;nh.Hә~1E14mUI۹#`s~@ё:Gxl(EŠSyBdnh1`7 !C0STی~%^oOr A}bJܔa'/,yrqdrLC;@Ӻ0x~|'pQǘ{>]."4{ٜ&h=ܳO 7)~'V4VjwV/]2麩5 T~3[n?\෮3msXzaKjh%Q3a-}R5„焰0#U<|vɠV#EIaBRtL }EFRy0X5&8mihh@)mKhH}0x/??W X[G.lEaBU\ $Q{5zydJ=\"JB5ٳgei?ݴiglSspN.\Ç'C G|;ڱZ%齃j&:`P5X2XTE?PUFm9B)L%I! l.EHe=pM4o⦊] B|W/:\Cpzy pCD5(eVDǘ#ڇ`7ͫrR[^ MV|4=V`C$>'UM).ڎ-m$msc%g40M.#!$2I@Zd%KLf_b<" @Ag`a\Y#DO}k^:w)qkּ!̩aUtMRuhgtT8F_w'Ɍ(=ӎEtU8+-ϟQ\?b1I'ZF´7h(%!zxZtk,?vz\ M3`d"/=ĆݷfMxQG}hӺ>%+ S$y| ƚ+Of&h?a"'| ޲9f M7ϐ*ɌX^1c ELc(7&́pqRZ&}^5'\]7)u~ Hs=Q$>u*- o.|/fŋ䃌)80ƍP;wI@o@qG)cz_s6~(KE ~JᮟiެQ; @t󲯹z>;Q|0`5X7LALN|辌\Y2zj#9zx;%*XS@J+V.o4MZ"3aB&ucX8qIHԝ@Ι)n/nVMlgo3 F̿< xCk".oKU(_Zf(筿"| ($I_'MD)#/V8#)+pSJBdւ J H5/FE>A1_JT7>@#E-5 a"s8v8s#i|`G \__2ҥЌy.K9f,|PӧJ"RKn(;Sr h.^ mHfMTk+71ܶmd>+[ `q!j֬&tkN~t6<Խ{wi"߇>nݒ`Z@j#GH"]M nPgoP]s/޽{W@sSz^c @uA뮭8<}|rZo~?;n(6US[ب Qc)I_SZUrȃhUҜYq3fKs^ǁ ^CxPeӧ1-fӊme}c=O.p(ԧ9 Mj"(\WpTr˔)|}LkR^۷OjC3g6o!0ŅgϞO8!m*ƍ"0Z-&4b4 /8rۘ7,c v2}@hн(ju߁Õ ~iҩnDs@s p׮]ZmG4W5K>_;?ݎ=l \L4`(`>`M bK`*⼋͛Wj[%N˗ǁP~}!(#=zM27|#D9_|4C<1Ь߿/5vPԦ@-[9 ḿIMh\D\3}4gjph^q\`qtjԨ۷oc޽Ȓ%4 N,*{D Bb Q'`4}M6M^STUq5[mڴFwԖt5.J*a qv44444N]+ ,H߃hPh`1`hOo S Im ͨu$&ePYVFIm5A5T +H(+W47֬Y@˗K`pǏƎ+A .}c5kb֭}֭['Se1KHuƱ429}8իQ f\I6OJpQ9l\6s'BbIs .s >}PZ>=#w"e}jm'G?#˴mV[;˝ N:tرCj> ~KDb I5Nϟ\ͨ$&eAARcE Avy~HѴTt+V@V@DֱE8q$7&ϥ֍&Ԑ1GÆ R8khD8/~QчnSs 8u05.~bF: (_FގܘbL3a7N.ҭE g2`8:ao,gjaKbT@FK*P~T+M:`+b*~}^z!I$߉';v46Ԗ_vۡr@xIs@s@s@s@s@s 8$BH89wA"oO98mw`R"@XIUD(Fݺu3k" PBsaÆV(=?Q[[;xxJnIq_շܲzu,-cUi/5tPNɥ?MhG R%gRX_Qk<3g&pjڴi煮jhh8j3Qx=C S4rOu;nQD?>Fe86ҿ+9hg Lч!+*mAPK [´u:sc#PǪUxe,Y^^c~HjjX2,˖-fv9 L0F?04"Nȅ @ 29Ր.999EntQ´o Z65E8tÚ ¨\:F}rQƺL2 mmLJk$gp #P) (bl7.PTpa&/$ ~ZH^%OE ׊kdWAHgd芼]/[Jա69Ѥ999999x )]е-jV4X$@jེị @a"6q^z2dL"SKbI\19-}ҦM+#10MhzF2.i:G 56qHOkv3kh>d&y [ueʴ]#\pc1999999 I@Ĥ^Q?Sj|><B՘ ![Spk GJ_a?z$]D#ْS`DEt97St!?EpC(ԩSѤInZFnS=]/禛X4.<œ 7NtNbq8ჩ썧V˯[wCjY}.v444bhLa&́o_OF;y/"]dx".;򟈌1@{ǟ0s$8kWFN+H#=*!(nu1@Aev3?<2FСCӼϝ8VΜO_`4س^?{x!uĘ4-mdn|ٮ;90_|N'&2fKDVKUsk"AbdKT˜'5v7ۦ~JzGs@s@s 9@_[%t!i?:]#"~o,۬m=z atG#UX8&*̀3ؙ{xOڕuǏz#x % e`'C#Sṕ[R%anlXuϽ U61o)&C"1bcx8P̃UgvG~o7J.Dfku^VUP>;￁?Cń>@&.X BraŨfqq`Ȓ' <Մ̚V"35}Ruy|8|O㪡)\Ŏ֫4NX\_|iL@ @wꊩ }(o$[ b,}9w#mhhhh8GOL)CA8{1._B>h2dž(?=b֬ ]8*J]w!.\}GO^U5m|麰OKhhU? `Z%jfN{'z- -K攨_'/=>SOz;+'O_G+S1> |aeT92@@NqEaRS1UEooXԲOKw5R&R$=r‰Lc[h$̠3K"'Xs|8`i:{n*TndsH34դ99@3o3}OB$YcdH}X ٫EVK =(/;?9w*KLB@R]hV Rn䩽`M$͔~ fҫvw>n}iŇ)')K`2i3;P噫}hsbOgCG[F}O"F^Ƌ1Eh|")eJq&M fyfZN{BkEz%QTxqU!w|U’Q+Ϲ$2 ӤH,_ A#A(.%GVw7}MegѲYͿLABcA= Xc3 0'.]*tZGH8SU’"i227*v:TWPIn,Ah@G򜷷LMp0%A۶mѥK6ߍ9sH`Ԯ];t WZ5J`յkWlW1ydsc2 ⭮Is@s@s@s 8n}5ںg꣺y&!|רf"CUbXheF"V|Y/_Xg2W͎ {c s_PrK(4/6ɒ&2:9’%Kds~=zYf`yW`A 8/_ dOs@s@s@s 9i;eW{9;;3"_l2ll\uV~L,] T5`2o[06TŋK(;M3W&́KO*R) BtEd`IJ vѩ~"mܩkfcz:@n)4s^@(~smd@JƜoj,{M}$}}0!b0Qqssd}B^lX^[@o޲ G90R5% qtq} Ni,(&25EF"y3]`ժUJ;PɶwXp! .,UtiS$ee˚}l5@R9-}@cj@Xme1Ágv* R~v5LHHcsg-$N3f@"aÆ`d?C-\0-ZT>u]j:p&)o#Gԩ#'5444΁C'*el6ئf.4"gTZR2SBwo9@a5omDBC0s}߻wv@,wh;  2q8/u0w|Eewlz4ӳYJHEӺ3q ) IƙǢ9(*(2g/>99`@F|:~..99/Jy=zP'OqQQi8 R4IbP@8!;gL現9Ys'5FU"13Cͪ_s1X]Gԩ}Zoghmh>;G.=v5ryQnZTO&v!D.\MgbIۡ^ 5H2 n/&OkL) B+\3?bz@uݳgyؙ3gp4m4V9 +W~;=Mh̦ 3i)$2 7g_9S!y4E,Nu▓eLIpSNm̉pǎ29nڴoޫI&Uaƛ(-sap->T"$큳P`ʛ ,j=~'ۊwѰl*J`m4(Q$=4-?wg- פyɀa_$v/]Ʀ9u1ud/qPȚ:4s`kSm=?єa Z;z!R$d07~@)B+Wgk֬w}7Xylق""`,Xݻw;b&T~Eś`<{ 7oޔ/ׯp2d0K2\})$ID)unМX"r 03X2x9ʟAEѼ ԯfƠ]T͘cŕȕ/-&8o{FR1rar'B5a*냼aH9Et |rō> V(],g(3mk*Y$Hlo&*"tS,NҮ}/^ Qֵ̅dpM\rwwvp!ٺuԈԮ]^znݒ5֭kFOmUb̼K,?z\!P,5+ߴXNB M͖L5!QH{ш>3xiDōو&ѣGѺukܝk_(SOpOyf}2A<S_>bYEjC-8/ׯ__!Zx1ƌDɓ "}$0[js45iD_<8U=k[nڴiSLAXCkŵsvg~ւlJ9hGLj׮ XpBsPR Mosz sOLi|r\OӑhѢbAJׄH4!xFYw)>H(Z;|;ˈ*|I+ExWa[+szM?}ы#S({*< vNr>> Xǁ:@4 8fS4pZwp1|pIիC43gN}8mJ>ZnPMZRCs5-?… V$A531J.I,&sI#P<ʫ22ԣG2f` I+Lp4oԬt|jر,jkvH$jhسgOy< ;H[$[T*c#a$(vȔ`p>'^R by.6 E4=DU?lrTua3''Jx!C(UǮw/j8'Ɉ;yK[ld~0jJ|[=o B> .,? *1N_j\mr$ *́lA I3Mª5]VyED(j=wނtxCO[x-LT;BۀQ.Ҥ89Ґ(52|nPmT?8Tؾѣͺ+9)$0LpA@X.[v\rBs5iM%"ha7k,nA1V@l5U4f'$\ΝkIyZ5_U.]*STd^9E \{\Rֶ4٣&kΝ;KYF\!A-(v5Z}iT\VmhK60ZLL<-8h9ީڧ&o4OwE"E&l0iM+e?7&33`ilLQI}RuuNO__ ؏q՘MFsM\X6{qY]n.L2qǭ~m?^8@ :wus|s2w ymd,S@DIT.8".(#Hda#:mhXԀ9:uٹsA6$v%00P 1j@Mb.igͯmč;(Ds:WP:쏦ֈ+>s1-&"˨z@QCʇ~S~$bF"M(H%RdJ*uڄ8kyߌuۥƍE /BV t:yҡ2,Dĉ\j(e={ U}>L1 'JNJlR:lV-&e˖mD8H o!I"'(N8ɏ&j(Ue HYw<"?a$j"BCk^Fu.͇1OY3( }=vr:7qJ FbZ =]TS LE qb> \(QD0.lR\$ )ɥD Mᢏ`ε\\q1q[S?[}ZA:,9o{ĉfKjlU?cǎ`Zs>bQV>l%>S(4+1;yx$ +(1 L[f E4O|\}fsFIegU[朡xVG<Ҕ8YvA'xNE^F@IDAT ; ƃSdĊ8qRRTIj"g&KpB 4?(I)>x=;9D=qqE*NiS&FH6{l#$߿=3?;_JkD34i9,.68"B F뢴u-nF/>tL#:M. i.DwEXP ?.ĸ,GCIs 8@ H UՖey>g0g F Xn@x02^7[mfm린 jϨsݳwºFíX&;LWΰ~\,iFJAy//)!b!JpU*pr}-Hsi?ҙ.^dGu=:a'\͛7;Gh#A4P@>1EK\t(b$X7Ai~L CS]NqnF}mH9$QbF*+jCI PgDz\hX^Ӗ@a}8@s@eR }l069C0FTqC%ZNef͒Inr eXj \p!3lذa+CS }TSz-U\|q˅Ll٤]0#(mI٩P%b0ѝ)~Zڻ)JN)p1A^"|H6Jsa(-=U9JJSH_ k9U64흵:@s@gݣ#90EuˑmE,("ύ"):Z>*&mg!$C9sR{CPԿ\W6T+9dGIqJi7F\HqE g$:S+V?*<+smpAI_F*T@8vԩcL-_\j9OQNbbmv€ׯK@$Ep C=4W9!QP Nm}sN,&χ3W*F#߇|XIpVQ%cXD]-9@+i\oyU\x$K H6V)yk/Uns'= l>EYkХʌ . 5J 2%qrD@Ha?–'h-vXYr~o,K! D\CֈI'q>g AN7hѿj 5[h h&LJYdaAŐŶZ$S"tܣG|bU>ˆ9G(_[kXs@s@sY9oiJ5LZqp͇C ѧ{LOaePT؜7-^EI]87V&M8ӆ?ݯ999`*&}_kCiPPpHU kǒvK! U"$y.|ֈz3%É+N6$MO k:WgMwsT*F͒6)x"랳&^bꫨP(* TwvU$^pr3N@lĄC`Y&u$(K2\09O(3MbhIS͈ .7@RfMwNH9S@~\[;pQ(ʅX=GYcep&6gtY'򡖎 I ݸqc x'h "ݥ@tpCbp-dt#+xja`7M)-NWr6zCpzLw6(r&ĩ"OϟQ&Svlx8bH)X\$ĤqdA=֬Z-]ޘ5,-5bܓHO^b宛B0}i|Ԧ X9 {ԘI,:zEgp/ 3I}n͉,lT߈@&j,D;L1;{t޳8Dr܀c%gSFV7AjjK_XTbפ9Vb32j={rbc\j0EN8wF(e\ qd>:n=xn1|{xn}XxH['5Q,wVb8.X8qzK6nLu>Gk.bha*<_]B|iBh_"W`-TqJV''a爔DF)άi&O5}lm]>r 6~,@9r$:v(*QN ։~tP0#ݨn r+^s qH [ʄA[0\5TThU-Xl&=CR ~_8A/S$6o k" X aDy*Dٗ$M(IVOӾ hOD*^Wx'A1q3d*dΘLnϔ3LANa%:;1oWLIYI,Yߔk9IF}:绋HNRaevRJ1/kC~H˖+W# Pa4Y:nLB}GyD=wg*x ;Aɑ3歿"a[EI"xF4ig›yrcѦR\7-,)R WBKY ]^ ?K(*L BJ9GWmgU oޫ*? &0n_ߊH} /ƴJ$$^Z@͒`y+~n0|bmq)F`gSc!CS^N`F1cnfbŊ9%bǡ;0j,?;Tzu .c9N=: { lϚ7`4e9PSE \:˂GhAG) a"oJ {-]2*9[ck~tftۓՆP{fԂ a.ǝߍ.oyJ0*5eOj?4eʔ+s*UJdFcI&%w8쯿ZF5kn޼^^/suU9z(ɜgŋ8jJ/# r5c%mGgާ/õkפ ]>Ú.=ԹER am0%8K;/M:8jjRiCe¥')Ӵs̻D# rҊ34h CoذAJٿSqS4?zH Vel.صvyjS``?ٜ ΙxyXX'ȏZ+sp!-[V K.W`b 0@9u<<sEFX>S=Eң@.LhӨ)rDAɒ% ҥLe۹~jӦA1-GM+[j$qo<>ݻ0G٣@5I˾G;U]`W/'>0caX4Iפ9P~|Lj 5! D΋7]_s .^&g+r 9ґ%a0E) ͎sxDS[n+k4Or5!B[m[*sN j0cL2#Zg΢y>.>k#ٛcomxo͇"2n<'Lk1fqpڀgA8 3&ů |VSpFZ8 eigLe>aA^9}-nq@yjժX ;BLq E~Rg(sFP\R[PvmEm~9+#є/O3\ǽGxƪXV#L'mjC~cj}})$²8]v-,Y"?۶m![#/>ЈZhg! o6m yHmֹqƸ|w::]0Ug =.d/̕tX!7UT1~4s\-&-6IY)ySN1Q}̹-mݺ:gTsyڏH`}$}D_-[HPݤKI*j4qmXq ]~ ]FNB4]xU= kB5 HGE@EHAIDA@ҋ:"H JBL6d}vwv9;;7xHn5 A}~> }Lq}ǨI2&o#֟Ǖ؎]cޗ|gݻ7;AdsVH[gdر2Mwzxpcs-vQ᳞Cjco$ɱ*r,~^ ƑWŸ+~<*ؤ=G7>NvSZF˨+c.~3(k5>Z,))ҙWsT>$mw==Li9ao%ju``n4Çz=Mq>Z9|ֱ$ɋqշNi$-EU^Y#q[GԱ7*ڶwt Մ^.bh# wE"u#68qg3` ao, K/"Z/hÀ,.*mB]SI?{lyGuv]b ۡC!`ʹHkNAVXAi/`&6*3fɓ'8=z9w}'/=pEkd,\kڴ?(s(as$D^Ba^d?Hӥhٲe]JH?^+*g9s0;ĕn7sL#{pzW_˹sʹ,w^ypT7=Ihā ].NTQApK7ZӝSN%uNkQJK#'ʉ_mjo7d yc޽{wdɒEih11|(ݕ 㿶j8R Pq$$V %yT-|1)]fHOP9),Hxr!ʝI2>tވ," A:E՞вIB)J夽O>hժd$,,>?ؙ bdiĞ1R~Zm^u,Y_pAJv Z֭6/^,'8B{-+Fkbm Tڶm+ӀPqa* T/_. .-?FAk6*l_.oRRA?*<' RdY`VVn;|q,c 8={ Ąxb ߬?~ 0@*RlP^ VĐu)gQb[?Tƍ'f͚%I~l.R瞓vݵױ;u{PuAm׵ *`];jZRp偫>)Hѝ7,w(RĀTӺIa8o|*obYhCO>U3Tp5JIC^ WF9C^(Ν;5_ZϽp옳欄aK)i߰0Z.[ӆp|F91BQ[ڸغ;K15|ZlP4!']he*2T5jH.krѢE&*ZuUG9*T@h]xayM0,͛7l^zx駥ŕf͚iULc )6 Q[fms 1tP#hg5M%$ LzÜO2E޷,Ѷ?SaٲeM}s'鱢G 8iEkѢČ8R$*ĊLC^Ì^B/I}259ׅ;Ux"v+S\ESTDєKE][r5gpږ8nI̛ .ruHOޠk׮-e,pzy{8ҥOS r&>w;xr"dJ.جUT~i5FO:U%9窩WIs>Ok"^wbh!gIWmG]{AXkA%<~o#^_TQ86BYً!Y09QThB%N$Q86]DWA*C~B+-@ ?_vO.Xj=11V.ImThGMhaRNz#ܱZhO_Gf  bH[ۥuqyG7ɓ'KŔV(#'NVAِ7m%~WDW@ P9rmYͻ]g$U"ęq1d~^d|є˗rsd?W`S vnY~Ʊ^re;-2Q Vtw$kHpptT\ITP$fš&b\/niD, iո_;6xVS9n|Fyhu_;f}Fw;Gq&׮>rK.%_2Qy4h׌m&T֭[']PQB޸pK2~cvGa<:tT*o~A.*FJS-l.zC:u*OEK4Gs4#L=ZZШg9G\߾}e8Q5%)-prhla Dhd|8cƌ-_7JNL%Gؠs䟓*qiUЬUv~"Mmr)R`ZM:9"@Zxt|!. fyIqR'Lԛ&x[-TkMUY܅{MS˽օY +R=y6Z]Z,#qqzVé"Urcr*RWc)t颫-'lZ 'TF2Q3HВ> ō/h!S,-<2aIƾoWI?㇀ޫyIђ)&X;4C$~JXO:mz)ۏ-I1֞_~"N9y2k U\0L.2siarzM,ӎY$V]#RQ;{Z]Ι}Gl~G֧Ҭ?u0ny$?;Um'D7*yc$ť'KX2,p`GrcDm=l 3Փ)NJ*1u.}Õ2׎c[_d~PIYs6'=wWa C:ZdNjlj;,sOJEcF:ȲjA g/ 2$k#)zE> D"oPi$VEF;gG?)vO">y}cIbG5}P+VmFxf^oQ;M ]:~'- I(IlRɔ>pKK(jJcZ?)7?>쵸 K-WZI; RJ 'gW7tI;n# _؄ t-[@Zf*/Ή sp%[ZE Z[.j$idS̭ƒGE<ot kDK}쵞۳g{k(W4+īM N{rgYQ0t|^=6-׻RlV];&3 :wj+RxUp ܌^4,$hiӦ |2恹 '\k|.\'Z2i2X!CyWz„N*APddɛA!h6[(̴sX."1B}T\}g`6-ZS]MI yaX&FIhQVJc꽫%ED.0M&,=!bdmSrZsq̽X &;~l"tc ӘR-G+;o `j >vlGûJYI:plb{4WdG(i!p+IRr 5?)Z(B%G{RL\\ib5y}2p[cJC**K\``ywdI化( -U (쟁7}O{QUlEuXK@$,"uw14mg1vt㗜>pq%y2Ir߶7bܾg Ib,{d(YO&ס$/9Ri>SKb_~Uz jt@T[HqM~-zP}~FoN>m0K:%&tb%  tIy'@k_d ;jqnz\ *Z֧.'鲧 P2K1?p."t4N5&EL7cғ,r<$#Bb%w*OP zۨKvmxzIO> A s=]U;q99=GirB1_iriivC xGM;BoDR']e ۥ 'EyN5!}-/^NWxi%pgKk% "2H0c *K勊'UCŇ׭L%R.ӲQgx*k͏*iٷR]gQRp}Ց-=9}r#l*3lkjTs֞߈nEn5.}Z BÊ~X4 F$\x `s%S!TŪ렠.[~Cy徭 csAe0Jܩf-9)\ ^Bq1,>pT}v3P>A@/|$NpBJv,P1u‘JO4l~u,J+6m0.挓үXT9u.3{*GnYG& y뭷L.&df%cXsE%E}2 @1^.h ITH%RnMb*TIdW4^"0aBWhvWxqIN8_|Q*$TVM~-]n_vpԅ[XҘNj+a+tN]? nD?B.L ASrJd2ʌøk=TvD^?A0t>®A|zb.~y>[ ]"m+Ox AXsDRH@`ħ|6".L[ԌW\9Iٛ^ Tssp"8)f8)KZO݊Lg#GgϞ;ʕoV&_Fݬ{=p`EI:/Rvϊ+uyT(tk׮Vo fUxX^GLXI:ÇhmƋebJ4/.h$5[ Sj¸(}yE-Sz|bcʙU4reYD$Isc Vʃ/F(^ 2d?ϡN˜Q|:86hWrL_xQ*\$ÖSzWTNO dwдCT+tVOPpg ;1ab4a3rӟ*<hlXTNo#s1RѱkEEqXH83~ISiH*s Zhy2-cOx^tIZSѥB԰ [b䉧m>;-I6i4o+ZɮANqVXW8گ`ҍ\ ii&+zH ߁#=ѰT#D9}{!ZYZg65_YkBZ]RSϟ?_Z iL}W$,SLR(<
R=iörsܻ SƑSԫ̓hjʝIk&^vAP׮ ,eu(,̖fCeS>PnGO0viiefpv)6"5+o1U=ywOGcUo005q.p,p*\"^~e!谆ϘUc͛']HL]ZޠW^yEӵnVf|&kV/K;>S'*(MBVJ(\G1O'Yt D,1c RR)jPjqGZQHeJøoWӀekI/3yH1 JU[-lEk`6dl$dv2Ŭ L7_Z4a| _ƍKR Ѫ4gFH2ƾPH685R?^!] ~dUCWIDP΄=Z=lȖ1}X-\UNx7=b~./DGwW!?W&zFZ21!pTX1j ~>|]>H"EമH ?/ [Du[I1և% cQHkNW({y<aÆaرY2Ƹb !Rsq Pb-gJX5>v)"=?-O˔|r%2?\!`"lR9weܫ/|(b%, m5p) 8]r${\3(emCF;x(jJXOiaS*N2L"랫)˽"/4UD`|(  Rf"xWTmMpjV3*,re7 o{sPK##"}HvEv~ q3# 8p$*֦ pxyP">|i{{}MQ)hYCdfkBU(Ae#rjPhVl=W( B@!6p2F7?\8GX9i_ }1[Rl缄z D#7/ŊP\(]:PCXB q {_ӦMUD;<ׯ_G5P%0'vٳ xDr>{ca('3"be*kTh[ >|E}Ó mdj[WP m kb(Yb:D~)eE+DV 2e(U!uց9x%v!gsUً СCXQd@"W"Eޏ7"G#}gN2{C/&Ԟ##Qd.z[>SQ`D?LuU=_ @6˲TEWEЬ&- DkrbWOKT_@ "WPB1_{reqjB@!P(LϾ+E>K3N_;tP,y{i;-R$'$zsn9ȉcJ5MNi$*3rhVV]ftA[¯ð\s ^/R9Ѩ6tl_m]W1kIaʁ|)'ZD(R߯$Qv]c}Z Mrլtro>~EnjC!P( TRRfO:͛7]؇>N*kָɲ}xWi]xjSnbI@#+Lcdˈ[eha2 mNkh,X' %=,^}+Edx &XϟD{}qr$ 4O|Dg(Q( B m"`9IEczWAph\5/7%3ճ5SL.,fkC7gDF |\GBVב: B@!Pe*H رcعs'yg w=o_Iv:'e߯Oe*44j^*#pN后ڎYR~{IVtfy$m‘u񟧝=EȀkE§ 1_Ǐ=AaC!2P=I*RvR?zΝ+đyqe)0Ɖ'41HY2rK^Sg6c>l(ǽ[;qj2iuM /.iȔ1$8 7_v8{b`dP/,i|ەYd( )ZxCqQZ.:6CS!PiS?EnQ߿ 6H lɫV*n߾U'(esF"Zڴi???\{dVDL SMxR[RI59iG%Z)6Fo/b?z?v>Os{(=Z)|D!n̙rBǎ,IK߿yŀPL ̎;6͛cʔ)W_}%?gϞKZj=pBi1c^x}e_~eo!MRDكSњ9sTHԫW/ȫ9j(kϤm۶I-]t8{,jU`ʺw?ڃR\7㤲e&W\ӢwB 2+I|TJ B9V\) &f0-E'~=S5kt cw[f͚ÇMM6nf*uMo:66"n~bh+VWb? 3РQD!^k:]ļ \=›'eO=U2|xru( w!@:7=zYd;#˃NoI;Z&N`g jLo.oXL*ij۶-h_>oe%xQ7A Y(Ud>:9Sn%.z )8'1؇-62IXy h۱(_Vр:5*{1޸qClW,BdNկJ*vU B u!qF\pA1P J;wnG8{N:r}ΜAb >}Z6>?$26-㱨TUbѫHW]O>2۴*hܵu{bX|=+gB\ZyZG8)s5JlX]Tfx?![B@SL,iҹsg :TZF!w7lKTG_-?_/G7>!10.Q8p7D!(atKd`ĒoUր)0d͛%/&VQU`[H,6R ׯ_/M͚5_ߞYolkU14$d/|%YS701W3,$^+T(lA=s- ݢ_ s#sux?ȅH=N%XsJ|>h }ZyG?JΜIǠqGL2f(%m=AvΪ@IDAT_Łq_Ō)^BlH>?( ^/=?s^EWֈ*e 2elB@!H3/Pb>BXڧ?ȶHRAPI *Sbd}ǀ/>WLkuQHъ•H9ޫ/ cb{kȟ/ ?%E;wAªZS( B p(R‹o"ߕ4E$ "mm˟hܨɍY B&9׮p~J B@!P\Lm@߮qi$O9-;wdo6/ajRBT,mi p%U q0X)Sqx-B@!-lȍ#/a͚5xR\t-8p@J6jw Yc2%w>N~w0R_rkWB@!Pw,Z.&IHƺGncS1b1Pʓ F @r"2tFDJJbU_{"|r8]ҧWEzhѢEX`m5HPݻ֫%5{vWN^!Pen}ׅcٮa1\X|7' ?`XӸ(7zI,R|>hApXzpH}iWci9W8ӵkע^z Xw|݀OFk=m1O3Y ,Տ4|эa$g1k˩ B@!W"1}I t/ 15PAt ]6HI;p]s b$ke<1ะ<={)w9rMksBeJK}&3)S? :1Vgʔ#4E*[lRJ,# ˗O-i7dqU L]$Vas΁|X˖-86G$((~+o̤lٲ9s^U!P(\wK!@Nl[5BʹM] y2VR`rhVV]ʚoK^.ly`hrEa*](.[8z`^M}W$ vSf̋ŴQsRMnn+ްv۶mY[]J$NER ]HIҳ:/R8k֭[ȑ#1cHw޼yxWn:\w!֨QCDժUȑ#h޼le?j2]#Ŋm߾]v2VΑk4hP(8u*4sd̀>J) gG Qa0_[> {7UإL]!bP&AqEY K;H͛7#wܨ^WO8[&#a,Yl8x ڷohfyK`@Hxj-Py*<<<2 מ={j*ɲ,}T-ZѣGKezΜ9Rq0`broÇuUQ_MՆB@!P8@P9,xSb?0jQ!<10Z,UHox"H ȆiUߌ} #`@Eƍy&z쭊iWʹkJ''߭ )5n8$ZyYŢٗ}b1gA,ySm@.}XxS:q,Q޽{7V^--T*%&kז"1f̘!ZYfI%nڴi1b;vL;> BI>z Ȁkp߫&"1INϏh9?v.c4iPBq۰O2te.՛B 2+$ +߅I.ݮUyC)RlV\YHm'|Z 'J,)_I4ep5FO!X4 `^(]yϞ=u",,LL2(.za|RJ 4rsn(Q(ROF hY2 |G98ε~J*6Pn{ ^wոrZ=HCq=oar0YA)܄aր 'T!uI֭[Ħ+VL]uSncU~}Gk2'c,VW #2.o޼XN>-~IZ%c[1Q"TZ5iyڸqXX"43~~~4^ &M1[\jէB@!J" cgx.9ephpy:zŢsPj^8j1j%ـ*p16ݍ6m];iQbDԦMPD nI#닖*Z=9饗쎓 tlceT,PlA 8sTzIDA#V#s7tT((?՛B %IZG,u2 KfH|ddF`u)N醦uP"6 qe`NۈX''9x?/W<{lIFC%I˱FN$:IVԩSr?K(Q(RL7 ϓ'OB@!fH/<8]~])R:Hm}JҁM^oBGlhRZ5-*N|q2D&FK #m?!kn>3/']@"GDm+Rgpqo>72:~75J@ZG Iejz1}"H&.'ZH1H⪭ÇEB4!*V!tsBEF˿2suƚ0 V씧ބEr3!Ebb7ȓ36EgնB #p90}_LݲeK؉S`1ӷ? B@!i$LOU[E`-RT *`q1\%ݱct$5a_*UJ:"w,ڴb^FE`s *vx]n-Gnep'Hr 9q SWǥD/`Qc.*Z~jLErH:$,.&{G^|%EJѯCI_rtLm(d\p!)":tH`r֥ӧOǪUyK^ԩ$atg*Z{ɒ%|e-[+&&F&gv}N:&_l.\AJ $woYfI*%FHO&H'I 8zT*mLpwVTƽV΄ogGPa_LVLobԥhk t]0+"BSugX:yF=G#>2#L凌 ER~2^ >~Ϸh^ :wު^uGQ`Ѳ|W:td_%7N˘L}3s='Ay믿iH J J $: +eӴFq_WJE7lH窠kqRFKg\l+[Vwpp^Sl=:Cm5{jTs֞ ݈nEn5Elúii|TYTfX51^m_,󎛎Yhٲ8@Gt8iб}|:1ZrR6qQXJ2N7ԼڧHY=T̝;o&ڵk2Q6OvRi2/Üsҽ{wWjժ|~27sıX)F({p8zTǎQb&L9L"7B@!(Z\vHĈ)&"/_>!k0olhr=V䛲(R]GE#kv=uG9fA,|3!*,}Ds̟+<\d.l{w>(܂WK0'R98&"gbQ+ZkH' Y0((T^Wn]ܸqCFQia vbKgzɪZۧ2D?9Qx? f ZHO䳗J֕+ƕ/*a|fPr-?՛B@!p)4+q>astnj6WJ^@EHGC>˗O2_PdQaJrpGXs.^,nş|gBdܔNgH"ߚƸ/͇7_@YhxFKֽ`-rA6ӆrWHv<]+v ؘU\W@6GVU}* [b,R.]ҪU+Dwttͣc,1o)tXa}7懭~e믿~M$^?A+-۶m^xJɴqLCwUKq=$jk$Q(*RRR+_x}n2e,W/فhא:}SR5*t(^yrdw^ =›ī}y$m‘ug>Ϟ_ )0 h+S&mnX.l l˞|}P**_9+fڮcexcگ _h!{Wcþx`l!9'zS:GOJ(P@NdZnT,1%QWV-ILA aI4%L4 {ԩS8hS:~'[oQ]K$"WΝ'#DžUo*K[|- xx9cCUʛ)1nРCgqf͠=4EAE;&^n6.=ԛV3}Gpz5N'E,Rw=dgJf܌~(2m߭QFk>F>ڥvc?^(=>m!wg@s%N)䫹ψ3'~fN^T=gݜ9tabbuA>eØ{Y/c~gB5h#e>QFI$wMbt|бcGtRiq -$;X=o^27 hƇ~(Ǝ+YYD%jhݺ5~wO>ra43g$(we_n\0B| yr~?seҎ?^Zx>}_|!I¹N% q(^L_KХ}?~e˖ŀPhQz!{5`NvT,Z?KB=+ZLy }ꩧ7GΝ+ySrVb9;C,9:zdIX&A%I/LX V~K'H8-[zjPjqG+㣶>\6I,H!g!g3FUҕt#F" b4*'d奢P Z]kO*Sʏdqa5uI2*h!!!RhѢ4veoҤd$yL?| FW_0^& tÇ"8g! *IOXi(Ā4gϞgyA`D#Z{^DYL`q jP [bC3W׮]e (TRHOzRh 8pT`h҄V"@?ȣ -;(5o\VP rd.:1U6mG$$bTb¾,'y.tdPiclٳCs 7n,}x9}$6lК3=.L6F,I3kָjie{oP, OJ WO2*pӦM~%[ɓ'ٖA4:u~SΝ;'σ$繤t_2dq$ŠdX+_]E{ )g-hs+nE>_Lq.F>K*sGc&X*և\M-ӽ2Ic_[F%~l]4 Hl8M.l>)6G%Sn[>]]|^C h;: [͌  v$0l~IAhEHUTP, S b,>.hk\ -fʔ*_8hhMaÆ6EI[@HeV!Z(s yciBwх,7nEb^Ȥd@ \%t42&P>aRM?EƉ2)2 f+Z'GR`K.GKzn ƱS69i"pU&`RsZ<nj4*tNLxjݝcTm+d!WZ>"u^\$)h+8 :Zbh [Pɇr%V^d X,5>Ni񡅆 rE Z(Tvh Ejղ5ٻwl 9ieb` 2DmڴpLG厊6ǑS&۷oL`ӯV /XwIc)Z w+EJLpG?]~dk=h7ښVʃjQ!|3!}:0fXktu.he#ꘚOox'kC#}8SS |LK}Z *0 _ǹ@ yйTmO@%)W-K4iTPh!/"-?$4-}bi"3 MOk&ݧLoL"'}ei}.#Hqp5LJ7;K<~gĄn}1qGjժDZ'2r1qO0+t5$]:)Xゔ{iMFx2 b7GEOCSnޭoGGș--M"'4mdWp">9jTV>|߳2:5)t 4J+a^dˑ5 R RΝYӥT\Ȝ=#vp6$.jHzjѹ2$+FY-[n.$}xg,}ӿ Zʃ&YkKW؂)S4i0Ν+,PRbkPg.43Ίg}VҽNS\XB 2cNGSX3_*Aݻw1[ZyOkI< t Hik&u~kkR_c혧~zl.~~Bm]')R!_|:<HK(67 ֝Q)Et]r7&EuV:u3ҼBy< t1} gp 5:gXb֯׳TZ_W8-3鞷Ċ?47IRګD!Rӂ!k`)ᢹxp-T~q|]9=:D?K9'H'\|3wf `T:)9u Jn͡APXGdMb+8ثHZR KBEf鶄YZ=o*}j_4?'=^E]g]v@j/|ɍuZ#ԫl ]xtn3? ,}OAL},a ;H7?wj̍*T#$r3^޼-yZ "9(OO:;p K٧] S3P*mqctW*tbpOUb;HU)Z i!KbOloX-f5箿(4Rc/JrI92䨓Ɂ9q6Kr @VW<5c랫 NBC?WᓚF09S@?{%;HUTwcR# {H꬐im"aK=WvM1gǀoBGl18ܖ++^xQR3_m˛]Lճ *.Hslk!RCTttVVg2U:-"8گ+nE2 -Q76R柸pǽ-/EW`keτɃǦg[BV8WC-p%W4Qbbp]BK߹2oEo_R.o6-,)SY0C*eYWA4u!*ViuY_߮Zöͧ?d&-k,>929QxvjǮwGpܸ@&A<5ٲ๚y`%Ȍdbgx^GYKRĒAG?hYVX>DIqs#:D~ӎqfxP21NW)'GBdZ憹eXAj;fdAń@l< 1n;ey´RPjtTq3E@8w&y5 E8~W[mu6YGÈUKc}"a:) Ğ#\rX0&whqRϛ7B&{|݋[`ZhA`Rj% W!۩-}`K) `VJLihOoAVb{z)imF炍y_C*_6]0)t6ԶBx2Ewpd1!Cy޵.~fTrѸV(s?G⩠ŭj%l$)daփvcx؀RrKZ a$hB֚"B~% ӽvd)Swߪ>~]&)O"ٱrT| 9V}]Ce¥2ŸCjKK糏cQA(|¶}Z MF(r9.ddPF5مqRtm`.nѿWTZ FLvűp{ bk˛\9^ nƅ8q: #dUDA5t"S؞?2e 'c? pþx8%yX_]ۏ?Ν;QL4'e_`ByJ̋'3gN\vM̥%1ԎT'mk7c?_(rTJ&<*ׄШ=i*RZ#˿+eTA &fgf"*iÓ~h^r{@T,-ITp _4͙+d1s4EKBF5sn,>o T/k<^Fk>F>ڥv8Y>CBB4jaτs{h,BD],_z@^|hD_,mN.o޼huP!` ^׶.[bt(У'QS \bmXj;{% ݷa] X1&܉EþDGۑUI @O\l_:=2 JFFL;N>(/"1g1oVoٱoG)\>X\x|`q`4LN9s """3x"nD4g)iqReߴOLpOX/`)׮̜/B1F6B @%Ekp?Z0RT<2f*g>N:%f.TG&A\8Cy M1!8)V$--0Fʕ{cQeIm#={"*~*QxUQw0-:Z[S(\@ͤ]=rlUP$!taT2&l) DjX\90đe{V-&x8K8?_j #ByEraLIܹAˬ@jF c@@ _n#B@!R(e*~'Ek I'Yj ׌MTCOAQ&8asE o 7}XXe -TTQ.-^ {ιR*M W!(e?'N 22jJ'vOWb&"Dq6̀ޱvh+ji !k6{mA(2pV,RT˱iwØI)SSERw7+ogĢ-H|U oDIK8;vRJ^'e|!3ǖ:LR=Xh$PS YRZ}ZjVf-zv:)*ܾ}[_sJU K_]m0p~A $FH2~z?^jUiIԲ0,[ {&tڵ+6m ~~wJ*D@)Sv' ~ I#J+*N,k@G· Pp*\&&l߳Џm@~xY|pQ=RJm*^r+,QN#?kעsgJI`` ,XVrP;:XtK~>|6l7dEJ֭[ (QNt'"卍%ȑM73`sנJU޼y%H}KN[RYoʕa<;Xb!_|kb NVE$Iqvw@횱uדN޽?37o.,j>Ӯ];L2E~n߾]&Bf1A(_~AN0k,9.Z)Q$RCGs _,-$@B~R*N2='ߴf$u ߊ0Kfc uڊ9 dk3o.'$W;{Z(эי;l~)y"E !QlѢ\\~:@}x\ݻ7N5kbϞ=xMϞ=%iUFr3|+VL*\Hb=K,?7W5J~ғ)'Oƍ1m4(P3f… 1ٻ(. z ]&"" EPO)JG) E"]{;z}slw%ypٽٙ73Λ2<pnZ3FY] ?,ȗ Hq=wAE9_4 p>0t|Osuu>=Sz^K@ M"^ߚm?ElAc|2Pj=+UI#/0t5@#Ы*qGF ,hA0X=NJ?-plMod#WG g1a ej׮-[LGohiLݻwJ1XhG ۷oٳ^qIL>.\g jkԨ_Uݙ3g4!4Pz05`pYwp%V:}.͖ɂ_s4i;?Y+ }ϋAa޼yJ#UdI7Ġ1:t/FdٳggϞ@m`{Zj 5G+yNN0çSh8qbr wh@Nf5?03#h`~TTIISqp[H]- veE,XM}M#'~2 ۾ W_D)J5 %5F gA`y?z  :/`ÇUWS60ꘅF#Ahr9l.+5e͠?]y`P"Hqf_kk͔slz7j~r'GW:珟J9qDD^WF>3B M&!0y|G[_C Ex5AS$&@tA]֊k74=ĎQpF3 R;#r&Cb9C"/g3^դ0#)3atFaS̋#]!F]V 8~+}GNIURui%fwl7;/A&u>/Z$$+n"SF "{1n(mQ@SD>}^|<\Kv퐲4F@ S, Qtie IڰAVBf#2-Z@C90:MWFjx 27U@NsLeQ6S 1.oFa(R&cRj(هim#vU!P/dC?o +ս{VO||. @IDATwVt'BN A`Hޓ,cuʚF#0k1P}4eLE- ;4>KCH}&Ù+[$bːn;'rP+bȑJؼy"C!D!e jժI(cƌ^LAnr *l T?{L j=(fg'_:o2.;vL` ;Æ nܸ"E +m`^ W =o>?[!y8Su^aᶫTZdL%hۏFקơPpj\ Ăe>x̊NeU.=U+!U8H!!,:u<_3g0B@kX{UVU 57>8ŋJC!ZjM/Q5uTF%216bqj(08LcOKu_LbGL2X|)H}J@d8ԱcǪ8Gy1>f!91ԩh -n,*ۊ-aU *ѬDiLn } Q~'N~ K&I^:s+*> >t#@X"Yyv #Z(?b;OPc)|~޶`˨b (<tC|~=Em=w5a=L9SRO<!bĶ }mi|@X!5Sa_KNisF*Q5=n͌FFpf~:<==VHGAFn1cƨٳuH49djD$w;yzQp (o…/ 2(aÆ*8iH^xD{b}'ʔPw㲆,hX X:Vx!LQhc4Z ek}=r:wm;EKūVܼe;/=Ȏ+!IBy'ObGz 2{dWe $ w#/Es$US-J{X2GPJX_i^ J$V”}ݗ"V7O”0>)ä)LBCu>J۷oGʕ u͋ݻM6ʔ>NNd(V\ߔFBj1:"jkOɠ#E0_GNF3Ƃ($$9&Qa)SZ!eAd@z`7D%>XĢ)QTLY'[ÂA[<3\FEYE.hOZKq-~N(KTh~V|;d  ^LČCfgU=j_[H_UB^S>W!GBD#褽nD74Cރ2=YaH\@#*e`+E+.%䮦ËgKO rftaK拊~k".o#i/CW7DDj87 /òqU6@l,&A"V"EKqGv%\/LcCtq^` D^N΅Ѭr䯻VQ(jt߆*%Ң[ךI鑅7Nګ5S ?;F44AV|-y*H.,Hq2{[&1)Au>F.lǬ a#3G?n,>y5NuU]k^(S< rgJ#J#sgxo=@8Xj+gˆygCKi4၀e݇F@#h4h@҄!vY1 ulO+bĉ&!fo3]E P1KAθB@ Sal0R-Cik&f 7vu9gNa]wϩ(rFWIy̓Tkh4F r"гz%Ʋi$$m[S]ʗ98.8VFyE(1;F 8"\/7f+vO{'QMYc8cvR]k4F@# LCha-|NoΩ$sFLV7yE#{UimʪဧYgdLUg1ҟͩZ*؆G!{kߟ[%c9;A6R^gB>|f;xMo`i=sS|~սw[xU&v9 ЬVV^5OCBkh4F@#/ @ eωDZhidΕc'3@1my^cSUbeul[ ?O9",#[x4b/./je·vc>g8~BVI"@q0talX7Wm-On,zF*$}1fyE{QQ{O3NTJ5ϺSN2$yoh.!O9g^"FL H8]V`9=v'û)y9.?D& :V0h#QkK8aM1~}h4F@#-L]ZyŞOmZcBB-םz?'`Ӹ0;Z]S4-fE Gr/,z)BBՐc}Z%hϪ*tڄi$+b"H6t}}$!Ǟb'"9 d9cɐ vK,Obw%aeU=`VR]N=&sFٰNI> &|)bꤶ,$sSމ F@#h4@(T( N-A%(H>(:j> @ʒ.䊲%"AxHuYh?d7Nm݈=)j{x>a6%O?EIp`~[%rޖ`/[2KY J&$KΓIğO_cz $9r3$Q2O u`f"@hh1 -Al௓)1aQ}Z%|$^i쫼\*ˇ#|s&7j ˡX:f\7oa [(~_Rev.㋚1x`Tׁ끵b]I` ʋk[FYHefQ>/g|pK46L"UJ *jUR%|8^f-b& zZQ rdq6}w.Ol{3̢UҤD~,V!Gx) 6}?0ҵkք7obTRh_TIQ"jW4Yd9i[eߞTTE4 vl Tͱ&F r"ض,rEZ#VK%T7K@N'Y17(IԩL dz&UD!D}x -Dqh܇@4M.놾Vܺ>oӁ0bt &M­[bBFrbLz0_[.jזh@&f˖Mhf\]eG@ S/&rɒ%X~8ҥK j͜)Ts$hb*V~_om6ъac]xCkBw.kQ4-h!^ YiʕZ*~Gl߾={ć~eJ 6G}䐗ɓ'FB KӧF ˧>#)7@#F ԬYSY%RBQ7 ,\@`:૾tj |-R tog15|]궹ԭoؽςClQځfps]sk?+]dxݻwW]vaǎ믿PZ5Ċ Tرcq˖-x{~֭C{E-PBtSZݻw/ T &5 z{g#E/s%\$c|SNZZ¡CoJ7ng}ܷo_5ݻzqmڴa?]pڵSm m;W{Aƍmذaj^O}||]_~6ٝp7n9s? \ϟG#Ǧ)ha**O"y7ql+-`6`wza]9J%,=K黢% ?DS¸/ȎF `L`_k6\w}2eR kԨ4D E~p/T;bܸq(Vv܉/]CKj;(_ $u9sҴi*BZOyzJf9RpqNr/7w,F&@H`lbp%0v~d )'N#<$kE#Յ0d)ZX&9դC%`Ûh]|jZjxQ00 =)xQH₟Z(<5iDM5DWB'ji䑈:5 ^(P3aLRQsCA j(pS*3YF8q"9}Z$Sx'|r9rDͯsʷyf6Na2HJ93gΨO ~5h)LBѭ ڂq:(k'%?jkcUm{DҥC]-Zy+f T2 4?Ҥ|oPBv4;32pD~0`2dȀɓ///Pa]P3k,4jH J''CH88F3ݽ+jt!cL}z@ܸiyߴW^[Bd(Eb޼yj=D4{c 1/^YdQ\3|jh*زeKa@d,ϩ١c$ͬԹqZ%/67E@,g_իj6˕+ &vʕ++"Kɓð$Õr^ \agI\}|}}OďG+&H5 Phmv׮] §)R"Q`h*U zꪜ*[̝;͚5we_F nn<'PDFR ~ޅbx|+P h[Z0rD֒1;M=(0?#gKDLYj.!0~!+ZǓQ2^k. hsumnNY)]\Л9ق9 -}'X(ݰU4 b2ua>4x?}憌ܺe7s!/¾?Gc#eAo/lmڵk+MmTG{W&sMf}ǏW7܌Ĉ3T25V%΀o­K4NX7B Ry)g`7{L\x G4Jdedg h͕_ߩU*,Yp^ كcNCu~/I=b7xNKnqb"T"w #H^qxŢ-L&B?)ZXd/sp 0hXqc4g\EՎ+o6;tۯ o:OnɃNo9ʑ%F^kDmӼNΣv'bY`܌blE1sg?mL!QxqaJ'd#݇U67*jCUn2hp!t@<@<L'x3%蹛6Zbwh}PSINL>3Wnsx؊ UҸX:=k_%BzRJ#Ġ B<06 ˴h" 8H +Pre<2 H1߁#թ=_@ahC kLɓQM.|5`ʨH<hF&Uz+)sTҥLΧ/?!XK5մLˆVBpu}b|Ft]!R1b[flǤڪ7p%+UJ4>_sޫ4S_5-τ?+s"|7m*hZ1s'~)Yߗ1Ec|*E 0Aaz+M5S@sXC@>x>p`MTCG_ .?V1w?U'\l&vK]?'[SV]Ăl}^,:Pkgl)NuT!yʜLi!m}B9 KZGU]*K* n3^-d5( IV1`ɓEr/uׂSJS6c9׋i~LN%BX1Ց}^;6gϞ+yE艑'߶'Kl4M9^h3(W@;cR%yŇmLeZ=CJg1U O/A3+ӾPBԨ+7Wקjʀn5y\Y>ccL?M [4%0ʒ(E<U45lhHUIX&G\F*%+`Gf9MTUiV3zŸ*ݩ#MTK7CD{/^,D^CȎUL.T@IZʂEJ"ݹ+lBbesUU>_$i3")}_\vdH~?v؀._ps_aH%뱓#W2z?+^>`G7e|P;{e+yem+M~K 8lm4S;s#Ȇ eԧkrgG]pVWG_E_ɽw&N;-w H {/"գk"KƏk{,招";U6FH l:iEh(6tp"#cn"]>(1#/gAts˧o"D tFUP 1C1)][yןc+lx76gJ3Vg|H1M]bcS" :$7-b"sV >CZ,v lA4PRV]r]Fad +Oo>D޲/T%& fYezA|-ZɩAМ;krDٸUg|oxV(e8aҦKsbcsչso"pjc[<50 i_CZϤ2<6/2Rs۶)Ra i#:ʇ35l\{W_msqb=BI1p14j̏fsc?KʑAv^93c4C $뛢Lzh)LHMHc '~\sɕN$@`.Fe1jN>~efæjN6EߟNȿZ:_ǿ* aDh  b "9oTOp3{d <TE1mZfLz7j_1v.^-ĎNe+}BtlEn54:n6KsP+aH!ڱY81ЬJPsǘ Y'/?r牶u)iTGQ׵՛?e?hۅŤ%c!!X?^81d*㟦_B?D=eė&v:grvUfGw_/ 몟+ L!5Qu6ntUUg|16i⍅1+!Y%[);NfU=jnぎ.g?xu ,$%%UElI#/Es6-y?1~_Ї*1iDp"xU{G-;VwcȔX~1^Y/bQkvP(~7n-LE+3?755:D0ыm9TRݗb'Flx_# =yC7sUPg\p{ \YXa˫(I(!gAx 9ӕuΞ,u0F){ *3b2g/brajT4L^i|}~,?b?ԯ>M/FK&misVӹz( t<+>mDGpWLH~l&E Kv J.wRDBJ$ @AQW 8r~& B3Dmi?"\5Q j)_70c{#&+M{S_4IG Jb& oJȂk7Ey rysQ)0c~ӗNJ\L V Z$Iˊcb3]bVKٽW,c;zc[8pƶ^LoO]x*S6 XT+: 9w"$[Dr]Pc f C$ HGxN˃>w)rUiXg۠}0#w\U/|b1YzjauD^pʖ)gH {A#0:, esב G?fA|-s egΝj=v;e)hdaI$ubʋ&nJPiBH'X"Я\vB~ݺ7{-W!5Qu6!Pr>p!|}~|U/䁊 c1+*ꪹI|PkP6-Uςݷ8zP+KΠz&Gw3瀝jg\7olz/Gw}죰wk^Z{YĢ@2Y S)G+b=,6FN<s^kr98->̹R(g#ߕ<;m.d/eSy\Z?+~y/Jbi *qci3 nKY)u)xDngڜ'?,sd)M#WGW;MȈ@B\Il~A1|tQjwE+rKfEJO> 9=-/~'EN:&{&ntfBD*U^aU5QF=-h:j.eJTaZLezfE|YT(5I$M椣IA_1OEG0ޑGV=a#l ŀk'Ǐ^sTS#)qc!"gyNAfQ#WpL4ȝ) (̩ ASMq,UE#$p}0+ʶ\ j=kS?=)m\Ɲ1h!L3L\~c˫./6m+œ_˃ab1xQmmk{bhf%Lwfw;Y|u9r>~ zEv*$vԃ~:GB<'zMG#/etEbkqQ:,baRD3q?3xKERi٤AcKMQF6l_'PS,Եcj bQXo qD9=jI G,zΊ%_1 *I&@b eÊe3f'0h`& rj/돑31Zdϣ :ҍ3'VdH+ZS"3C܍{6{:D2|3Hd8g RJVG:@c{гKSo-li^_1zG;I8'wdg9*j'\%KS1܂_fA*0Y@'Mݯ%ɘgo3S6/.:9 l1Q k $5ȁ@0dsPJߒbg|-`Q*$Cҟ}K .ьP隢 I ͻe3pϯ+"ёw^S?Dj9!nŔC$X )={ͤqGߓGĘ梪@_K7~Y>ѯc#4֌*vG&I/?S ^ a-+2,7C;\^#Hns.}5D.1ws%ٿ1&JMJ n4;@H)pM)04(Q"34R5{[tiL4 1*UBBV;v,ڶmƵ7o@`C%R|}մ3rd/ 7nnKԍ4D VXHV|y8pӧOǡCQǮ]bРAQeٳU]iF"E u ύώ"vm۰~zœXσcvC`зCF@#^Ҧ_(׃Y=` @tO*P܄5Re?V|Rǵ[8w (ͦ[}/%\!Dd|G%qPjJ-ܹ/X *UJ M~ ebJ@Bȑ#չpA5E`JHa$w믿ЬY3|ת- ÇW2GeNҤI-Z->(8q.]RBcС/ѰaCG()4j~f~Gy9ٳ+a1j(TXQ Jw0JzqlܸlJFgtRYر#+\֫WSc]6 6 nb6LuK7[פdb|wwJ)BK`k"ۻ~!HqLeFE lZBng QW&hB@x</'?C6 r J &dJXz5>s%`pqNS3.?:ݫ 47YD_~ȓDzJȚC.]fƌ)S`Μ9~?geʔ [nUsFF›3v3C J$>6l@+W.%L5mT 6ӦMSի(S㌷}9B޽GAԊѤD; ܷukfAu+~_$}hڬI#Gw9+ݴhFBpvd4@x#?~׸qcO HtHwQz\٠ٙ3:uҦMCӧO7`DbW(8* ͱcPN%9\uj׮*f{Զ4{̗/F:OOOpn̙3c`x$j樅ƍ'pt_F\%jH|4yN<ѤDSD饠4r-sI/S\΃V3t5h\r%t}n#/Ch4[D R7C/c.jM#;%.e޼yfʔ̿ }wE36aÏU>SL՚%:<%K} {b+ 0H:YdI͛WifΜ j8O)UV)*jwc`(C(L'}h*Iy׌ $hٲ(TH˕#?NJ)W\ih4QbtB xe$G5xF^歰H4 MNsxIgrFUV~S8g Q0₝4` \r̉~ b ƸN"-.@IDATa | gϞUB5{&v4 䢝աPaԣNԠD7B LJG2'G  a4sfŢ"1Tf.]:PkEy؏}}}U $ '~hݺe6ygBßYQkπf7F7nuQ#FɅH(iïx iH]]r3 ]d`d>WmǏ&X)Ͼ/S1'sTfsg}p\f܀i G!xoϏ8.=?~/e_7w}s݂>6}M#tk 7oދy_5ͱxkD{{G{ 7{SX5CilC"HqLnRĒ48[PG91j4F  )'S c0YV[WxQ[5S잻va?4B#pCF@#h#?aֿ:CDtB9!km{ZQK/nn8h}0u#*{=h4F n.T/u`ш36=@X!0e>G]s ^DE~F=0֠KE#h"7u`1ŇjKEkC`J 2Ăڕ0HmΫtM@"` ^4wF "#pU\t!2󋅆Ֆ"oT\gG= ,zϞ=Uyn„ *¤}k5Ȱ<5ưS0ZB[tkaٛ_IШ=WM*hcEa&Lqg@ MCa3:}^2>=F |4h^6sL?#FZh [n. qɫ[h^pAlP8% :7nPIǙК(wysl+G`0\)z N 5/OE`VY`b1Vb5 ?lZ\+4o҂tEʕ+Xx2ebd#TO{zz*۷oƍ{aݺuJTbwy5kTcժU(^8ʖ-kJbm`8ԛ;&&dߞ>vĉ*!w,YT3?iڴsqʕȚ5+Mo^HnժyʕKJJٷS/3Y7tSdm*ٳs4l2d0QנAc _b/Q䤞hjfk? Ҧl JHuM!j i@Ra70LæoPh@Tʔ)t .z~Ec /t*(zJDA'MYfP5d۶mț7/Ο?/*ϼyEv2ef!)ҹsPB%<_h֮]; "YG} Yf߿?~w5v~J*Lի;*ZZlraΝF:s jԲq5_?SK EU-]Ta_dI55رCaթS'ܞHSN.O<_Τc}3f*`_ݻȟ?AAA[ [@+Cq4”0Q՗}Ve vQ;+/pUGŸ~ځ/h ?|c RD*5SA wxӤOۂ{vs, tyw#5q1{/_5r%^^^XlbڵΑ#rjz \,n;vҤtU [ԤDV\YrC9닚toP`?_+ጂDjp~g(r T|' 6NΉ(j9p1Q{bEL˯XbJ4+b߾}6lJ3y䝜_|_nX;^@7j( 8P4Ҕ%5|9Ξ=UG~I<6P _%@ižK+$U$ώ$M%x*˷$;Vܽg=?"}Z eX(FnD*)PI#P+ju_ɟQxo!*n*д+[l 3/3gάʉ d, ?(QCE>Έfb>"|O 9\ۓMVU7˜a:gxO!&MbA Q w'>'R.^~_KWV-P@Fs;R.tC;~~~NEa5"/.U|iE:5W}qVp[3QC-h.uVa{j\)⯵b;Mya}Q ͛cc*Tfu)g}#8'Nƍ¾ݻM9g 6Z6{rԞl#}JO?)>^Ԙ=7(hQ;w.>30}EwԎ UBڵѺuk %K{(lڴiFuu`kAM4Q̒4jc3Ҥx;D h3yێwmÒ1Qŝ;whA**yanĢuG$ .9{7|(PP#A3=.ΩAEʷ~L؀fBџ~1R eD`` O?f~K4=Af}Nh7q8:˸n>RyRAy%0dP`D|̦iY{jy"Ğ~WE? XL(RkF 5Vw'~~fr&Վ<'yH"n4#_~*3ω~np)DS`2}ܓmVe\GF "`3^lNJ^xj>hNgݐ ͖=V-\:__Psa5aA?1cmce IG#4#BUF-FH|$+b7exuCSYbe_FYLu4BB dž m}Dܼim}LaM29}` mGIM('\.ܞ~]'۽{2 b&>9_n& XV6<I;jY_>?_O]3x4G5͔y0!F˛o;s]}0#)D%%"%h| J/ϼQXA1h-z3]ĂmW] Pz<'cܳ7AQ% 0/n2- 8e2cAO344 LB RK͖;/qqԬ0 Aux CP|9 < R5p7u]܆!iGX`}F]3Q#T`0ƛ+_ܱw&>ك.rzC,~r&;$+Z֬[:Q|BeVzUMUX/?Ģmא5CB)n> ~H<.JNei,cT*\Fnѳѝ>_Cp0" +Bщ aE13*MG#%L',93Maus]~؉LS`#h}* 7PX6يީ1i-FbwS܍ '/>h&Ie|P܀WN7s"|&I@x1zo݁q\M j4i4E SoݻF b ;ic؝6jN]z W!vX?U|> d"vm<{+?Y$Q :ﺌ-rw*$M+g@ШAN-V4e0SJ:z2}G+Qlwe酣n{K#S,ui4F "(iE~hn;b>W2O N/#Mxɐ2.bgЩCfA$q"yׂOt D7Y<ĉϟID;X-;.+2Ҥb %a Ma5!qiF@#\D1QjMcrvK0t]$ʾZ]LOp羘ʙ6+ΡdX勦oKTU+T4>vFd%=R\ ~d2>@tʼB{Q0*۰aTN*3JSĜT!:tȭ+$v+#%Y}U xò>wWF@#xhambq;$-w Q.}\oQD_^eF٦+3A,ůyضލV`J+eĶňXl;*i\U[A,,=I!»FF3gÉ@o|B{U gDA ! (6Gjhlʕ+klgެ1I.֯_?]OJ*8}tȂ.3pP OxZيsZQ_h4D@@\#Ȝ:oq)R2+?9:?ËjEKmWA"]Cxhx%l=lO2 X߼v)h:hP)I^ --uku'~-,1`qmL_ub40DNpY>|ԊȑիWW4M9sLL8k3br]1w\x{{f۷W|;t蠒2l6m@Fjsk׮U0&e{1q/+Wt(Q (a ,ŋ={TQFjƖ-[6naqc,fx&͜90yd+V’y|}}b׮]شiŒ0W_}0-G"Dٲe_b0e {lԗߙ4Hkn[BhϾ(32qhƏɌ5?18!S8sނu,}HkNH")+J d vؗia*1=h;C;]sVƐuKWvx9H{Lk,e g:u/*I{"gb(G,_ 4PСCQF 0al^Ɖn4i$0Pɒ RĶFRZ8qB]~@/_>?ulOa~… B AAB^Bmh w(VvΟ?=zrٶmИwjΝXt)o V1-[6œZ /^TBz߀ȁ ?3?^[֨7/&LU>ƍ2eʀjܹ*ccOܖ9(X7"43$>>>?s<leŊM=~%[P 7PiRT ~/F h.=m= n1]#VImA\@j@,ArG -LҝK. )) * X(AQPJ0HP) ɥfn;ٷ3.ۙW7=;S!Eӆ@J|4|]ؓ'Ç[nofvFR8p :wr_~8'l[uٳJѫW/5iggBȠA "Hfjϲ'Ƀ (-yF@DD$4W7+"ȢfjpiE:$GSV"p!t(4AuE޽U`UHeE޾;7F@HsJʏ H:!_βv* t]fmZ5&u%?U|EH@7 NZ4e4)B4U~[',`Y\ @aKFS-#h@LklahyCIқG@Y{ڏLO9_cێ\$v|[.pX;m%e8&o4#QDXt>sԨQs5:e%z ,fBd1ihvFHjh^G*cƌKYfMD4pɒ%Sˎ}jHurC Q3{ǏW@Q4飙%[?5f:}=i(6~Nm75bJe uO>hTk[,cՐiHH $# &hԜҊ!9@%hB9Yt)6nܨ|&VkIߐ;͆ Tt@>&NX&jDڵ|jS~~=.nNJ7\Di`m(v6񋲛ܮUXnvORYw^̙B@F⛿fO+eR =I#kX8|᥼/;ϡxThX>>>)EsƊByk^A\?d/ϫWhk->iڥُG$I/L61f4 sGmSCC>dh5Sٳg;Q4l߾=䁑 BH/b +i`=׶m[4mTirGlL$jz7o q#OTZ[E$+9D`KA3Gy@ΕlgO_jC˛חb')jȻ 70zrՉ9g$%Նͻ:yw0u{? ._(%loBpX0v,{mi^J~+w;Oj"}u$T)1`vLV%䚕e2w^m j ϔ̄Y|h-tJt]/Cd+][Io{[+{fC S'E: ~5$JD%eh;>UMl@н/.†>[j2dMj~Qx0qxeZfet-m9׷M- C{#vmcč~XBь&{Gbn)S-882eXiG-o }jf7!wS;W^UYDD~zq}?P^#E{%nȀ@z?z4 E ЄW@[0z @ OFFb+M'@vxheLV Y2$S]$N+GU‘qteG @jа@TmA֫I]KXXYI +[51Ц0~}ѯQ or|IBF9јſ#&޺Wm?-<=%QqSOaҤI7mޗcOmX`&zRFY"vț7@R+YD+o{ X֝l7A3Efm<ǛdAlhX'm͘vIp98R1f~QiH F$-Wj/A"vCf en=MGA Iۃ7}`)}{f$M I&v"2sqꔺ3wf|`'ad`L{m_] ٥Axډlb_? eN XDQV6|U/\>&2uVcdVH#ߦLE^v@J &4~9Rcej`,ԩ]T&=HzTx:\>u7ļH>]UE&saϵQlF"1yKeRmW C+\G^KH|T‚1g^ݵMߑS7ߥj3w$j_?S馝6 GOW^ ̊BQNbTEf* Ďv9=UR]@aȏ;Qd()/('_rZe~ H0֯9%[ɁO] /bt_*_}:|7T$_S WP9^Nsg2/|9UA2J"M*Cx{1Ŋ1  '@62E+U SP.љH&,8]"G?Q2>sCq0I?^rXei0W|(!@Oy;rC3f~4s`BوIٔNpږ&1&=En~""k}3 gtQL)t|,￘M֏%.msܙ?[)H,ʀԑ%}Om32 %ҦK|pBvIzi߹}U^T{_}g MSK|2/!8|0g&eXt&5d$%D| l"Et 7< `$Crsc ^Flc>`|&$L9bITtA{45 A6Uޑt?`M(0/,2GtP37 `Cϟs-&O0s}>}pvD2o<͊ "ǎ "fnC/y ~=z$h 2*u]VI!aƝp@J_y˒R>,"=fΧwP$wjtiEoO)zcƌ#Ly'6S*IGH|/Gfc\ Y^r5ԙRaʀT4#Ĝy8RMŠ; Hla̗p5t!w =62%G~kp]PͶ_~h͔_> |5,ݎA* +&L2?cq~.6}g[oS̵O|1-ǐ@\UyM-ƨҵ'kՇfv6"}vZ~dT46Fp]}gII-OHLخ]0ak*k| tDN88G 2l7wd}ITLq#eG0wFrf˖obɖ p9zա-v36JSZ9,:EzfG$h ~>3gfsNi믿O?U9q_ )KpDbwfZ_to_x0||%&HiГ1cFP+i۶m 1K='?zq2㼕B'0ҡnל?3Inٳ':t& 7TR?'@|a3$speI+\\ W^{&R\VZ29Rxuſ9gspEY3jc$Q iԈ\좹1LʕߣtujqBԌSO0D_X.XqApjч}.9tY׹sg]bV\"#ժU+*C3uM?LjU_H(b?H#Q}I!a$x(*)("H  "eHTmKRvRuy}+QLV|;i'DJ88scpg1c(JWW$jώiww˪dԢj[e00$й0iP"ϛEoě7$ lG-hE 4P6:_T ,PZ:"FXڡ֭[+ M<i5YBOzh*Wz1b/ݻwɓjᕷ^?}2gZR%-ZTM8Y 2ĉ3x\ɼՏ˹  P@&'^bѓ&]\75O|~w ٣99iA~<>ʹyMԞ_CF-gH ꐥ`F,wU_S$+:7"mޢ|$ǻ}WĹAݾ_G܄T?W? w𿏪z _Y ]2cTCC &Q E;"f} BMXEkK}g$O2r18q3{lೌYIҚ##O)>Wݕuz|wpmʔZ/A>7F1% 2ٴ] B*iBh\lίzU],&wWY2.lLב6 />9H푦غM7wBMoS1c$@;^/wTudfh-WX˳NZ9j|${*07"˂C#vtԆq`}HQSɚȺom088af=} D*j˒&Mӹ_fx%|ݱ1+_CɱZehGꏲ`_x ۹}€ mpʴm$7 x SGvy],&Y~\ gE|Γ%)H~sY}>- 6L@⳸bŊjaiРA}c x@`x`D?OצV[4% .Pľvб@XWIV.w~AQ݆>8)nK XǓ83loxc ouWQufHHH &$=,<ș:_wwz:wȾ Tee$I \tn݂_$0ՌH / ,])88(pUԐg Xsy.'NĸqmLs6T(iTJִ4H/¦@)RɔY l.nTJٴJBIH"\8rT)g%4j eջwo|EYؑ)#X㘵ɓu,}"G :"* .;E)o$ ApZ>ٺk9_2ed6d۾}IRC$WI[^l2Afa[…m5jpwm˖-ۖ#G$ETW^yQΝ;m%#˗/wޭQD СCC Eܹsիg?GV-[VO~+WV_՘ҥKmT<hnҤjC"ٙf$G$0vw<[+kJ  x/3m_z.M^Uα(w9Oɒ%m+VP[ÇWsU2$p)f_hTB40a<>``D[@}$Kx@:γ<`Μ9c-TrRu`aÆ>}؎?&[w֭[Q)I؋QLL]#xm8'OUf{7<2D``,)m:x;VXcハ"yuSjKPI>H염ׯ813eH+j0jlCAkE+ lӦk׮<&p'B*ůD䆌MLE(MCF7`W:\$ݻwO-"/\P󜫟>}Z-"H9܀f?p1],ilb(z j iX2#2ׯLÇՂ:a\H <0H~l1N2V}f'u R[ɒ%SUxq_X1pqs1*THI4+e)rW&/&MP@̙Cׯ|>|||'Ou^`{W$K-`4Sq4 ̒%⋕46FW[ fĉ~\EPn$h8Wi(+8ׯ+9k{Cǎ),Iqejc-rVJ.N,i׳> Q|oC#ڶSW˰MXt^;4+O"h.ozDN }?~?L_>j}Ü]pB[fݣYdab^h/ H"X&gΜՄssXo  8K YR3cg*} ޽;4L`E3&!R~ V{X1(['VUK7nTHV-Ex^19^I6Û~TR $%& q~9Xu8R"-?7\W(&́@80E8aѣ2fp |Dԍкukt.o,F#O\Ȼt*vPU |LFd͚5T}f6@[+_jDGd}]9}Moŧ bcp|lGՖ/1M)5S|t2`\]q'Hl͚5Sy1ett&1CT+A-A&` jĴP=xA"FQ$~X kƨu%&umY``/>$HӧCLMq;ex4M[]xf8S*r6d%_|<,~*_lEUnWPr7ԘYu`&{݆?|wAl� V nŅ]x qPq1py"ZUTIY"]Y)9bG[91FJGn|é<]?aUyR3Cͅ;f7٢•Ĺ.QMߜSCC&СCeGhH`gEP|v u pu!j^u릺at+S׼8<[bUR&ĺ#P>4yWj#m+P NsAmHΕ(j;#J⺵yN'|O|0wD{`؈us3,IU*| կ"sՉ1|/N\Ž+qxE~߃Ʊ3phK uKaiW?*{*!׌T'/N3/`Ġu,%˒ gu'Qj.Xԟie|w7W:cwJ-e }fp\g_Dpm\{T@|KON)'/^۬4PbYנm3዁kZAsf5Q=@ z?eQuэZ2LS[iU_B"v_FRek5%Q^)SZ; J,1$ .M9)Z x%fk5|-;^/_%e'&~VMIdKڔv=u0JUȁB>ӥNW-ꋲ< sVc^#,1{gmGf[ONeӒ@KS~E^gˍ =,OMLD.p׵xذa`yq!b;eat5pe9spKAtb+  DUѧs*'C\Q+Ic$K(,GQFwRA:y'ՔI0cs]|"LJ)N=CjkY2wGvXyH"xr=z7_)Jsiŋ}vr8X|Sid)؃%[NK&B\7@*Em:a teY&p :e.k含~<eYzܶ96 L#8*>\ EXC]I`)נZH5|h9Hf{1JgƳ3RHO>_ɿ@1sP*2jߴwii5 {6Fk1ß2ğSwcH*)fm 9 q=c6Amh)~^kyWAhu!yVw<l(f Сd͓+(2m_|r5ںBbO-7M?hCFF[•fpKw&848ի6A nAFGoYE$c~\ @#Iy6$_at?L>oy{J؜O/&WTșM˚!yru٧a(h_;FjK\{O暑*Px?A ߿DcAO;F{)رcG&~74iD s1'$C * oF>huE#ntky2%@ E)|DXy"X+W@"XYPJB ^yǐ@@`"\:%22 .L\H6rE ijLFb.!Faܹss v|}}UK1 mr)u:3&06\x'Oc36pp9!7 #~Yv*/S޽U`qdZƕZjv3ӎ{9NJԮ]KT$Ȥ$yvp^|eP̻D0X# *A/###@4 Cў@"_($`9pWR$һh[3ϢCTP@@h*"?UUZJ'`"Vٳg+ Κ5!ɦM*mPj$yt(ɤFkJ 0.\㭷Re˖'*P>ua]9&C֮]aݱcG|keA;C2ss4d̵X 11A'®7&֏XW2gSeB`U朑@lI>.zFcO\<}ʶGݺ붰b%QbgZ'?9|}p pټpb$bE3E}8gXٳ+G|A"CңGL04#_*) @Xnwbnk7۷o2a\ Dn|a3F8`;r0ڴiJǼiJЛ|oCboӧOGL"KG5pܹeʔQ=1TB:P U|)5{>1eF6O?5vS2FFF)ZD6M$pJ&d .9yR|>x)r,H#Wѵ[AXŞzyΗKʢ`Rj;/P(g*i7 +OcB xANIfyrHᇂvǢxjuf((h`j%Os]V gt8}:&/N9*o!a\Oª!2u%J;ڶ-sv0mVdKjKt&^aO@J>4 0/q5Εe|c|%tݡb&&׹IcFˣ3X< J|LjfrZ#jzI ĶbQ+0Pe[}=_ըEI W6nܨjL+K1j OΔ',޽[4bEQJ͟ Zu% Sw=T|W Ԭ'cZF\i0On  5[qm ^J`zLYplW [DV֮6R_/P(IKN)CdJkO.]/%H6CO8Ljko΍81@*w ?)Tp繱%XS!ء_M*UoռB @34y-ܹ,C 524yEQÇʂΤ5Q־'E# vEK S˖-S~_+.UVU~N:sLrN*ZB&R!4 e <g7˓5,=PJkgo!cZ}ZGO_é#xc|8r'R6)݂lԪXI]9sӄ}˖!G2!0tKO ʱ).ߛ.'67} DFP64H`h򧉦jzlM5N2J>ϲ[lU0g@ӠQU\kta_ڏ4G5_GoJk_۫Q|G(}7'T=HW 8#Ԥ82!Wtn wua0x`ş˙+NXuȨۢ3񾠉,A;UGmrq_Q]N%!$M?VCY}S&ہ' @.+1/ԶֹPp@cjjaȹ|RͨX)|'^LF +y&.Ub={[U۵TʛsOx/X(-  W pa.A19o5TDLqA9M'\aH,*8{;$0 Iǭ,k-a=m+k^yШupS>*1 sڏ1mqO|E,/GlE ͠iJOamn9>s/APŨq9޷j^tzr#:݀$C4SESVEd0 :1r5_!%ޓ."#.h&3qE-2`-r NoPܗe5<&XL}q_ucH &yݴoH;U2ŵKcEnذa]&FJ?Ldu92gάU46+&2iψk*#h2 5 HW)#s2мPܒ+-dd8djoFgHxM+f?3m DiJ. Vbdu0_$>O ޯ*K_;=p˴*ytː;P7靖ֺc M}0N:΍raֲޮK.Q#Uň^)cP՘N"_lF*O|g$!|"~'-Fv/Gw⧞~ރ]hf=#cڰaXݣ6:qg.ϋNaނc(X<#&N=_VF)_Ap5}&$fT[BϖyUD PH|"6ƏFLڂ08~ P&U M}#x,zfrL}I I'eDhVH$*0?gϞjHZ3f8LbRT=-_\F?:*8!' Li&JH,CF6q\3UPS dɝˆWQ&?/>(ZPS)YҪqt!LZա-rTaԃ}!TTVx>C}4lI_JfG֠EѭYnl;vU`}<ꕲk3ŏ a&m?iiC&?7  x3D"'F"pq6ӛ7o|MiZ'kZjjwOG\rj+U^]UN8h߾=@O4͜9SE;w24 ) eDf2003bbX~{jD EJ2 .^MM|3= KtUxwܖw?>m_EҩSKC QhD5o$ݿuͿ0j$Y~!&L|0QTQ$Y&uENj׮yȐ/W (>}y Y0&?8/j+I:p b OYӬIk޼>HHHi#ŴV2f՛.G'A#|գ;+j5ФJ)౰\{)I]FD Crg"my*35/?"qj+[֔8r:m8K'G72f~o85(ʟʹCsfz,Gv:$K,8uZiS=}ͺSNH~vTn]GѩS: 4џʚ7M_ckͫ>.1w]7-tt5?fk$`$`$TLʄ)=//V;) @SY pl,ډOUEu1h4 {8IR#ꓕ[ɁGg۳$珒Oz?~^EP˷Ms¤-#xuy2`*:h0@h o-ceHYyRrQ'_uH=&67%GMO&IHgQx܍Qy=GTԶfE_1dUՌ-0EptL<[W*$$+꼳:Ԁ>|O煁 W"Tk]U11>y2#}j;@c]k*/ҬH%L '1󋿿ù#SW3rαPbn u.|;w[ձ:l9t 6GYw&Wct.c=hyk]Wo 8]bPX4爚~;vxSI/U0EHȝW#Q"A}RPWmK4{&+[y}Ni cX uF3`*|FFFF1,S]ÏO1ےD%gkD jG1hio)W'.=ۮUpcF!褊v=\"Xfκ _DP1l1PE"s`̼L>,JI~9W<yc?ސƶuc9LYx<(xV75^o+YA^a + WCPמmT5WܟvFy/W˂R-( rYYz4w7#6 Q ܖ{$ǻ(,bkH ^K^H+;'%'?"W!^1qCY = w1$W`޴xAudE|rĘUX5+w~y[ȑ=%"pJFF 5; USL!bϵ0q\=zPqlmM kVfKo%'ϚfQȲuY똼8- `R}wc F0b.vujו*opGS۶@=Tw^{@۠.ɊO-9~QY_C%trt&^aOhlk!gCnSpLTȻ[3 3Kۀ+hjRs{/جhxKr ZxKpDطh$_^kvM7_G_W^gĎ*VΆTR@j֊&ı{/WLSe'@vxheLV Y QRhFunup@^4mVB!)YBAX}VPT_>¿;.d D*If8mjgCIUB4R;=#"}ow!@jHY9vA%vpT^ˬ+DzX/'M7$H+Q)JAҾ)cζdB.AGw"SZ{5'޽p%Ib 'ϝz!5ZN>E\vry/* qlx%=>ObÝsT)φ>lV4B >HiIAj#F}ضw;2s&>I Yd*~xt-`w3$IM{aw}{:hHdRV4W*UyE{h 2$ǕЯv FH*V.~'$^"˒Wlꐟfk4m$~g6 ?Eb8[$N3^ϽJ[. 옚fMEi^Wk潩|  ۊua$Q>#OZG_o2ޚ_!lʺkj+{Im$I H^RRhJ ~eTJɏ!#;AOsQQ( "KL iB6>Ok/aDX8&VHn+#~9Rcu_M;rh/ωۨ\;W/X0*K27Q~nفAwWw쾌0NR[cjblf@*kJV9}.Q[.(M]7@:cP2AG2y{ҢV*ey3#vʷћb(-7i`s>cGBW\oC@^y\sU}1}5mp۱^GeiLkg9CBgF}.Y^x.=q{ם崙!3 *rV1}!+;v?{L.NQ`dK0[ /fc3˷&ҼJx @]~; Qio7{Kκ>.P|GPX2t):Rmv_Cg( *wY>wHo/ P$$2z_feZB$&9 sb~b$p=yՈ;!{Deq˜;L)ScOTp@ϲrVhcBtn\ROamn9>U۷_@aȏ;QdY)ϋdG+Юu5 /!俩RTjegMtn,F`ؤFv|&&Hw]-O4OjdU7sN^Zʏy\஼KESV^+܈N}7 IBfG)nX'(#qJJ`zi.u!?c=vYy!H/̕) WuYG0A"8U<@g#j܌ѵdߵ+~7&-8*9Loi9x/W W𣵪9#h^\/fb׸J06\РX|~L/cLc՞k$V`(A]VMж?HVח.Cp=\rB7bx?Hr|^y>sK&W{m~_rڎ۠9IڭWޮɢ}˱[ˌMly`dl 鹑'+7aA)KY{1sI;C[n>>V<=v~9 x<O\SN,i`K$+ޝgqwuܝiF6sp>b* bU\ݯMy>]ֳg-`eE YUĜ)F0d$].WrY;!G8/kl[ )& X%3^?BSӊYIiR!3Hc0Mi%Q9qM!H\9D9$k?}PF@.y00$wqTyF|c8/l U$۲ C@[#o\]OĞݸT\Z/;y&>h6l%tilQky0+^In<'Y҅ا}0ֹQ.=ԑ|]6H4Swu%Rfd.w^\l䚢^ilxy)ëEJ2tUbVvt!LZ%@mQЙ3jZI==F0mx5eI|e|=ryH(_j*b*~X R_%GѾh_^.|׽:5x~t{(5˭4XEϖyU1+Oz CْH%ļo~iGwYerYqKK>70~2@ }̞DsgpH8zDɛM-G0L>VgaC&]UyO=P0L:n0?6¦? 9T+fv]D!q)rȀkOlf%?.2=V2,@}X<:Z[ǯ`q_^L[J + âGQtV4Coo攘e-˓FuvMl_l FP^9 FNޅ7zܘYU0jJ_s+:8^{bAv-K"YUAtUz~~б4>Sy5eĠJ\s.ݿ\W¨wʪ񸝘~nCj1*'z{ </7p/<+2GΙw8;'LNH(~y?*>4vEWy!yԪUqUکȂ)݋smv$?.U{$}FFqJʆ% m@ғ\t;_ ųh$ zDC<&.ycvMh'l oU(VY﹀\+SBJ#Ԣzr/AWU/R=Qy|I=yxB?VѓtJ|l̉7pZV!Z4 x*p(U2 Eg6U_|iVVbk/ /KTxN^z:A2밐sbx)`˸ԙQ8}5e;pLV% Glyǐe悃D.W߅7쿌z-A|xUV?gN7)3GoQy_<J[:ܕq狩}ӊcyQez9d`iCj+̞%T|h8Z -Y֬/A]ɥeX:')#x,DGo4٪Bb7 \0O'J"D"OERp+[kz*$FWyN]~[eٱiIf|R&E" `o޹XQT($vÚ>1eJdQڣn*3G9z89].TDʈ]bYcJ#(=|P-zV5bN٬rv\nx4]+N-yuNA5}Ƥ=99fbFjaja5}{X{9"&@MYj>VUm:2_^6 ޵GQ]||ZWB @yHU@@EAKA`+jAQyP^+?P#*R2|ivwfݜcΝ{{s?qӪR_(;rkYk+у,1ԧlM-#,Ep85Ƕ~~vLJnEqk>Lތ~ C~|=> +Cf+XQuŔsjYC-ʫpEd]3ĊaLC2QVip/>VM,  ۳N^h’ߗ97Ĵ<k㮮u-Qbhd^] ѻSWsX"[TH.([%vу+ldԓe ^!;Wסx&:w2쿙xBsZiHNE회TBvzN|?7ߓ*I:ntcdL G_8#zxdLL~i?I;o Y\)TԄ< >? ܅.=#_w&/2TDЫS=vzٛnr#v:HK!wB],gܽ2'}R3$2hz /i8UqϜZ@>ӌ/PO+Yd.eg]n2!`JBBFTQVrHdwq7r7~0`4ϋEd,WkEUdjҰf8v<1vs^iSz}@*S[9L|w2`[+tk_S'H -Ad n\PP<: 4>so'5cİt1t9o}xP "IC= 32xaHBk,HdÉR^DqHɵDVs"ew"`}ow+Bxc#:qNtjrƵ~IK7_vIn}n~$JxsPUZsBwwd1EmShIII=4JEUB)mZH5LH"SsY |# ϛSEq`h0nTvKoOs'@k+nJ,_13ч?yIJ;D{h0T+Sq0`hgYwgDA5Zv1?)#Xї>_whޠ"68]k,XUT³sxQg?!QI뫽>|ֱ:".'~@IEF{-z.1l ۴+ݷW(C2\X`ZJc^RvEͺRg3ُ&M үzR(ad2[cHןBgW. w# GROLx-"/6tlqC9:Dx&&E xq5|ۀ1gkRpq<3E( d6Bq A󇓤wxjp+`J5 82˱8֘]iB@HN>oM?%ƹg_5҆@4_!䊔`ٶ0&: coF@d͙T)|iA&zw}+e24~{v .1SG#(E|:H"&27?R9<=CCGuviUE A@,¼]Tq# gOڶ"qm7@Sϓ')N:-?[?*z"Y&ڶ"%4 Ld,bъle2}p)R$v U"dCgp+R"Ս쏘lɪXB@Z벲L/"%c/3%8|MͮFN nJ@&i|ՋTڏ" 2%ZͨIZeҍ}9ū̡#!#QH 8xW]F?^gi$X X7|aTPt gPi)ѧD"Д m35dFctNEmɌR{&&7GM4{7hR\ץCMpфʢB@,I&wmK|߁9dH%|.E XXG uRT[qćjJxHۃy/3pf# £u2J&fM0pY5oEΣ{:4S&,,.w ZxB@7$[Mog~@e*+\v34hӜDVID*򘠻Ƌlמ= k ~jfumZw<2#2e-|UK⏜kQ(yΝg2g37hÿ.9z4e2[ [|M4]TD7kݒG ˉn XPȀSJU b~CH!.֊9>=d&~euȢ9(@r%'W`aU|3^"H)S@27sş82j8z(g|' -߭:w-k5"*F;ߟ\e T(犴\5nX즵8D`v;w{M =@:TҋDs_B&xsRJ=#/®LYpEGsW%uIVű*9  $Qì^ͺB{$XEqy&Nj7'cM\@X/B}{%(VW\}("ֿ_w=L.#UK1WĦ܎8GfM \Ik#IIG*y0 ;d{89Fw8t&/|KP )SvԎv3_ eIJcߘkE H6pEm[Юϱ7c$ν|s5p&.\u/^4#P,PZj`zq֊WJt4W4|yE uZF dĖM%AhIK+@(e*\vE@PE@PE@E@PE@PE@P UԱ("("(@/\#Ч-IENDB`chk/NAMESPACE0000644000176200001440000000710214744734003012244 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(abort_chk) export(backtick_chk) export(cc) export(check_data) export(check_dim) export(check_dirs) export(check_files) export(check_key) export(check_length) export(check_names) export(check_values) export(chk_all) export(chk_all_equal) export(chk_all_equivalent) export(chk_all_identical) export(chk_array) export(chk_atomic) export(chk_character) export(chk_character_or_factor) export(chk_chr) export(chk_compatible_lengths) export(chk_complex) export(chk_complex_number) export(chk_count) export(chk_data) export(chk_date) export(chk_date_time) export(chk_datetime) export(chk_dbl) export(chk_dir) export(chk_dirs) export(chk_double) export(chk_environment) export(chk_equal) export(chk_equivalent) export(chk_ext) export(chk_factor) export(chk_false) export(chk_file) export(chk_files) export(chk_flag) export(chk_function) export(chk_gt) export(chk_gte) export(chk_has) export(chk_identical) export(chk_in) export(chk_integer) export(chk_is) export(chk_join) export(chk_length) export(chk_lgl) export(chk_list) export(chk_logical) export(chk_lt) export(chk_lte) export(chk_match) export(chk_matrix) export(chk_missing) export(chk_named) export(chk_no_missing) export(chk_not_any_na) export(chk_not_empty) export(chk_not_missing) export(chk_not_null) export(chk_not_subset) export(chk_null) export(chk_null_or) export(chk_number) export(chk_numeric) export(chk_off) export(chk_on) export(chk_orderset) export(chk_proportion) export(chk_range) export(chk_raw) export(chk_s3_class) export(chk_s4_class) export(chk_scalar) export(chk_setequal) export(chk_sorted) export(chk_string) export(chk_subset) export(chk_superset) export(chk_true) export(chk_tz) export(chk_unique) export(chk_unused) export(chk_used) export(chk_valid_name) export(chk_vector) export(chk_whole_number) export(chk_whole_numeric) export(chk_wnum) export(chkor) export(chkor_vld) export(deparse_backtick) export(deparse_backtick_chk) export(err) export(expect_chk_error) export(is_chk_on) export(message_chk) export(msg) export(p) export(p0) export(unbacktick_chk) export(vld_all) export(vld_all_equal) export(vld_all_equivalent) export(vld_all_identical) export(vld_array) export(vld_atomic) export(vld_character) export(vld_character_or_factor) export(vld_chr) export(vld_compatible_lengths) export(vld_complex) export(vld_complex_number) export(vld_count) export(vld_data) export(vld_date) export(vld_date_time) export(vld_datetime) export(vld_dbl) export(vld_dir) export(vld_double) export(vld_environment) export(vld_equal) export(vld_equivalent) export(vld_ext) export(vld_factor) export(vld_false) export(vld_file) export(vld_flag) export(vld_function) export(vld_gt) export(vld_gte) export(vld_identical) export(vld_integer) export(vld_is) export(vld_join) export(vld_length) export(vld_lgl) export(vld_list) export(vld_logical) export(vld_lt) export(vld_lte) export(vld_match) export(vld_matrix) export(vld_missing) export(vld_named) export(vld_no_missing) export(vld_not_any_na) export(vld_not_empty) export(vld_not_missing) export(vld_not_null) export(vld_not_subset) export(vld_null) export(vld_number) export(vld_numeric) export(vld_orderset) export(vld_range) export(vld_raw) export(vld_s3_class) export(vld_s4_class) export(vld_scalar) export(vld_setequal) export(vld_sorted) export(vld_string) export(vld_subset) export(vld_superset) export(vld_true) export(vld_tz) export(vld_unique) export(vld_unused) export(vld_used) export(vld_valid_name) export(vld_vector) export(vld_whole_number) export(vld_whole_numeric) export(vld_wnum) export(wrn) import(lifecycle) import(rlang) importFrom(lifecycle,deprecated) chk/LICENSE0000644000176200001440000000006014654722452012033 0ustar liggesusersYEAR: 2024 COPYRIGHT HOLDER: Poisson Consulting chk/NEWS.md0000644000176200001440000001321014744734003012120 0ustar liggesusers # chk 0.10.0 - Added `chk_complex()` and `vld_complex()`. (#158). - Added `chk_raw()` and `vld_raw()` (#157). - Added `check_length()`. - Soft-deprecated `chk_lgl()` for `chk_scalar()` and `chk_logical()`. - Fixed nested backticks so that error messages only have one set of backticks. # chk 0.9.2 - No longer officially supports R 3.6 as dependency `evaluate` of suggested dependency `testthat` switched to 4.0. - `check_key()` now preserves active status of `sfc` column of `sf` object. - Fixed `vld_join(by = NULL)` with R 4.5. # chk 0.9.1 - Fixes incorrect error message with `chk_null_or()` when `vld = chk::vld_xx`. # chk 0.9.0 - Added `chk_compatible_lengths()` and `vld_compatible_lengths()` to check that lengths of objects are 'strictly recyclable'. - Added `inclusive = TRUE` argument to `chk_range()`. - Added `upper` argument to `chk_length()`. - `vld_sorted()` and `chk_sorted()` now ignore missing values. - Soft deprecated `.subclass` for `class` argument in `err()`, `wrn()` and `msg()`. # chk 0.8.1 - Fixed bug where`check_key()` failing on sf objects. # chk 0.8.0 - Updated deprecated argument `.subclass` to `class` in rlang function calls - Added `chk_valid_name()`. - Fixed `chk_join()` with `sf` data frames. # chk 0.7.0 ## Added - Added `chkor_vld()` as faster replacement for soft-deprecated `chkor()`. - Sped up `chk_null_or()` by soft-deprecating `chk` argument for `vld` argument. - Un-deprecated `chk_count()` and `chk_length()` because so useful. - Updated error messages to precede objects which are described by their class by 'the y object of class'. ## Fixed - `chk_null_or()` now returns (invisible) x. ## Deprecated - Soft deprecated `chkor()` for `chkor_vld()` as slow. - Soft deprecated `chk` argument of `chk_null_or()` for `vld` argument. - Soft deprecated `chk_chr()`, `chk_dbl()` and `chk_wnum()` and `vld_` equivalents. - Warn deprecated `chk_count()`, `chk_dirs()`, `chk_files()`, `chk_has()`, `chk_in()`, `chk_length()`, `chk_no_missing()`, `vld_no_missing()`, `chk_proportion()` - Stop deprecated `chk_off()`, `chk_on()`, `is_chk_on()`, # chk 0.6.0 - All `chk_xx()` functions now return invisible copy of x (if passes check). - Fixed bug in `check_key()` and `check_data()` when key is undefined for `sf `objects. - `chk_whole_numeric()` now accepts `Inf` values. - Removed `LazyData: true` for DESCRIPTION file to avoid CRAN check note. # chk 0.5.0 - Added `chk_null_or()`. - Added `chk_wnum()` to check whole numeric scalars. - Added `chk_dbl()` to check double scalars. - Added `chk_chr()` to check character scalars. - Added `chk_not_subset()` to check not a subset. - Added `chk_factor()` to check factor vector. - Added `chk_character_or_factor()` factor or character vector. - Added `check_files()` and `check_dirs()` to check if all files or directories exist (or not). - Added `chk_setordered()` to check order of elements in set. - `check_values()` now checks factor levels. - Undeprecated `chk_is()` as useful for R6 objects. - Soft-deprecated `chk_datetime()` for `chk_date_time()`. # chk 0.4.0 - Added following checks - `check_names()`. - `check_dim()`. - `check_values()`. - `check_key()`. - `check_data()`. - Added following typeof chks - `chk_logical()` and `vld_logical()`. - `chk_double()` and `vld_double()`. - `chk_integer()` and `vld_integer()`. - `chk_character()` and `vld_character()`. - Added miscellaneous chks - `chk_data()` and `vld_data()`. - `chk_join()`. - Fixed - `chk_vector()` and `vld_vector()` so ignores attributes. # chk 0.3.1 - Added `expect_chk_error()`. - Added `chk_matrix()` and `vld_matrix()`. - Added `chk_array()` and `vld_array()`. - `abort_chk` now allows original arguments to be attached. - Added `chk_tz()` and `vld_tz()`. - Added `chk_matrix()` and `vld_matrix()`. - Added `chk_array()` and `vld_array()`. - Added `expect_chk_error()`. # chk 0.3.0 - Added `chk_sorted()` and `vld_sorted()`. # chk 0.2.1 ## Minor Changes - Removed `chk-benchmarking.Rmd` vignette that was causing problems for many CRAN checks. # chk 0.2.0 ## Major Changes - Added `x_name = NULL` argument to relevant `chk_` functions. - Replaced `err = FALSE` variant with `vld_` variant. - Switched from `stop()`, `warning()` and `message()` to rlang variants `abort()`, `warn()` and `inform()`. - All error messages now start with x_name. - Err capitalizes first character and adds missing period (tidyverse style). ## New Functions - `chk_all()` - `chk_atomic()` - `chk_environment()` - `chk_ext()` - `chk_has()` - `chk_not_empty()` - `chk_s3_class()` - `chk_s4_class()` - `chk_setequal()` ## Newly Exported Functions - `backtick_chk()` - `unbacktick_chk()`. ## New Arguments - `formals` argument to `chk_function()`. - `tidy = TRUE` argument to errors, warnings and messages. - `n = NULL` and `call. = FALSE` args to error message generating functions. - `ellipsis = 10L` argument to `cc()`. - `sep = ", "` arg to `cc()`. - `incomparables = FALSE` argument to `chk_unique()`. - `%y` to sprintf-like types. ## (Soft) Deprecated Functions - `chk_no_missing()` for `chk_not_any_na()`. - `chk_files()` and `chk_dirs()` for `chk_all(x, chk_file)` etc. - `deparse_backtick()` for `deparse_backtick_chk()`. - `chk_length()`, `chk_proportion()` and `chk_count()`. - `chk_on()`, `chk_off()` and `is_chk_on()`. ## Minor Changes - Changed `chk_match()` so ignores missing values. - Changed `chk_true()` (and `chk_false()`) to same behavior as `isTRUE` in R >= 3.5. - Extended `chk_unique()` to handle `incomparables != FALSE` with data frames. - Changed to `range = c(0,1)` for `chk_range()`. # chk 0.0.1 - Initial release. chk/inst/0000755000176200001440000000000014744765207012014 5ustar liggesuserschk/inst/doc/0000755000176200001440000000000014744765207012561 5ustar liggesuserschk/inst/doc/chk.Rmd0000644000176200001440000001170314743771503013767 0ustar liggesusers--- title: "Get Started with chk" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Get Started with chk} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Introduction R functions and packages are great for sharing code, but it's hard to predict how end-users will implement them. Users might pass inputs that your function wasn't designed to handle, leading to incorrect results or errors. For example, if a function expects a numeric vector (e.g., `c(1, 2, 3)`) but receives a character vector (e.g.,` c("1", "2", "3")`), it may return an error. The `chk` package provides a set of functions that check user-provided arguments and deliver meaningful error messages to guide users when something goes wrong. Including `chk`'s specially designed functions when developing your R package will help improve user experience, prevent errors, and make your code more robust by ensuring consistent behavior across different inputs. This enhances the reliability and reusability of your code. Additionally, it can help with performance optimization by ensuring that your functions receive inputs of the appropriate size, thereby avoiding time-consuming calculations. ## Goal `chk` is an R package for developers to check user-supplied function arguments. It is designed to be simple, customizable and fast. ## `chk` Functions Based on the function prefixes, we can classify `chk` functions into three categories: 1. `chk_` Functions 2. `vld_` Functions 3. `check_` Functions ### 1. `chk_` Functions `chk_` functions check the properties of individual objects. For example, `chk_flag(x)` checks whether `x` is a flag, i.e., a non-missing logical vector of length 1. `chk_` functions are called for their side-effects, i.e., they throw an informative error if the object fails the check. Although do return an invisible copy of the first argument so they can be used in pipes. ```{r, error=TRUE} library(chk) y <- TRUE chk_flag(y) y <- NA chk_flag(y) ``` The error messages, which follow the [tidyverse style guide](https://style.tidyverse.org/errors.html), are designed to allow the user to quickly identify the problem with the argument value(s) they are providing. The errors are [rlang errors](https://rlang.r-lib.org/reference/abort.html) of subclass `'chk_error'`. ### 2. `vld_` Functions Each `chk_` function has a matching `vld_` function which returns a flag indicating whether the object passed the check. ```{r, error=TRUE} vld_flag(TRUE) vld_flag(NA) ``` The `vld_` functions allow developers to provide their own error messages. ```{r, error=TRUE} if (!vld_flag(NA)) abort_chk("`NA` is not TRUE or FALSE!!") ``` ### 3. `check_` Functions The `check_` functions are more complex then the `chk_` functions which make them slower but makes doing some general tests easier. ## Using chk The `chk_` functions are designed to be used within functions. Consequently, when constructing an error message they use the name of the object that they received as this is expected to be the name of the argument. ```{r, error = TRUE} fun1 <- function(x) { chk_whole_number(x) # use x } fun1(1) y <- 1.3 fun1(x = y) ``` If this is not the case, developers can provide a different name using the `x_name` argument. ```{r, error = TRUE} x <- NA chk_flag(x, x_name = "`zzz`") ``` **IMPORTANT NOTE** As the `chk_` (and `vld_`) functions are not expected to be directly exposed to users they don't check any of their arguments (other than the object of interest of course!) to ensure that they are as fast as possible. ## Extending chk The `chk_flag()` function illustrates the general structure of a `chk_` function. ``` r chk_flag #> function(x, x_name = NULL){ #> if(vld_flag(x)) return(invisible(x)) #> if(is.null(x_name)) x_name <- deparse_backtick_chk(substitute(x)) #> abort_chk(x_name, " must be a flag (TRUE or FALSE)") #> } #> #> ``` A `chk_` function initially checks the object (using its `vld_` partner) and if the object passes the check immediately returns an invisible copy of the object. If, and only if, the object fails the check does the `chk_` function construct and then throw an informative error message. The `deparse_backtick_chk()` and `abort_chk()` functions are exported to make it easy for programmers to develop their own `chk_` functions. The [chk-lgl.R](https://github.com/poissonconsulting/chk/blob/master/R/chk-lgl.R) script illustrates the general template to use when developing your own `chk_` functions. ### `abort_chk()` The `abort_chk()` function converts multiple arguments to a string using `paste0(..., collapse = '')` and provides number sensitive `sprintf`-like types. By default it also capitalizes the first character and adds a missing period. ```{r, error=TRUE} abort_chk("There %r %n problem director%y%s.", n = 1) abort_chk("there %r %n ", "problem director%y%s", n = 2) ``` chk/inst/doc/chk-families.html0000644000176200001440000161063614744765206016017 0ustar liggesusers chk Families

chk Families

chk_ Functions

Overview

Classification of the chk functions by family

Missing Input Checker

Check if the function input is missing or not

chk_missing function uses missing() to check if an argument has been left out when the function is called.

Function Code
chk_missing() missing()
chk_not_missing() !missing()

... Checker

Check if the function input comes from ... (dot-dot-dot) or not

The functions chk_used(...) and chk_unused(...) check if any arguments have been provided through ... (called dot-dot-dot or ellipsis), which is commonly used in R to allow a variable number of arguments.

Function Code
chk_used(...) length(list(...)) != 0L
chk_unused(...) length(list(...)) == 0L

External Data Source Checkers

Check if the function input is a valid external data source.

These chk functions check the existence of a file, the validity of its extension, and the existence of a directory.

Function Code
chk_file(x) vld_string(x) && file.exists(x) && !dir.exists(x)
chk_ext(x, ext) vld_string(x) && vld_subset(tools::file_ext(x), ext)
chk_dir(x) vld_string(x) && dir.exists(x)

NULL checker

Check if the function input is NULL or not

Function Code
chk_null(x) is.null(x)
chk_not_null(x) !is.null(x)

Scalar Checkers

Check if the function input is a scalar. In R, scalars are vectors of length 1.

Function Code
chk_scalar(x) length(x) == 1L

The following functions check if the functions inputs are vectors of length 1 of a particular data type. Each data type has a special syntax to create an individual value or “scalar”.

Function Code
chk_string(x) is.character(x) && length(x) == 1L && !anyNA(x)
chk_number(x) is.numeric(x) && length(x) == 1L && !anyNA(x)

For logical data types, you can check flags using chk_flag(), which considers TRUE or FALSE as possible values, or use chk_lgl() to verify if a scalar is of type logical, including NA as element.

Function Code
chk_flag(x) is.logical(x) && length(x) == 1L && !anyNA(x)
chk_lgl(x) is.logical(x) && length(x) == 1L

It is also possible to check if the user-provided argument is only TRUE or only FALSE:

Function Code
chk_true(x) is.logical(x) && length(x) == 1L && !anyNA(x) && x
chk_false(x) is.logical(x) && length(x) == 1L && !anyNA(x) && !x

Date or DateTime Checkers

Check if the function input is of class Date or DateTime

Date and datetime classes can be checked with chk_date and chk_datetime.

Function Code
chk_date(x) inherits(x, "Date") && length(x) == 1L && !anyNA(x)
chk_date_time(x) inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x)

Time Zone Checker

Also you can check the time zone with chk_tz(). The available time zones can be retrieved using the function OlsonNames().

Function Code
chk_tz(x) is.character(x) && length(x) == 1L && !anyNA(x) && x %in% OlsonNames()

Data Structure Checker

Check if the function input has a specific data structure.

Vectors are a family of data types that come in two forms: atomic vectors and lists. When vectors consist of elements of the same data type, they can be considered atomic, matrices, or arrays. The elements in a list, however, can be of different types.

To check if a function argument is a vector you can use chk_vector().

Function Code
chk_vector(x) is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x)

Pay attention that chk_vector() and vld_vector() are different from is.vector(), that will return FALSE if the vector has any attributes except names.

vector <- c(1, 2, 3)
is.vector(vector) # TRUE
#> [1] TRUE
vld_vector(vector) # TRUE
#> [1] TRUE

attributes(vector) <-  list("a" = 10, "b" = 20, "c" = 30)
is.vector(vector) # FALSE
#> [1] FALSE
vld_vector(vector) # TRUE
#> [1] TRUE
Function Code
chk_atomic(x) is.atomic(x)

Notice that is.atomic is true for the types logical, integer, numeric, complex, character and raw. Also, it is TRUE for NULL.

vector <- c(1, 2, 3)
is.atomic(vector) # TRUE
#> [1] TRUE
vld_vector(vector) # TRUE
#> [1] TRUE

is.atomic(NULL) # TRUE
#> [1] FALSE
vld_vector(NULL) # TRUE
#> [1] FALSE

The dimension attribute converts vectors into matrices and arrays.

Function Code
chk_array(x) is.array(x)
chk_matrix(x) is.matrix(x)

When a vector is composed by heterogeneous data types, can be a list. Data frames are among the most important S3 vectors, constructed on top of lists.

Function Code
chk_list(x) is.list()
chk_data(x) inherits(x, "data.frame")

Be careful not to confuse the function chk_data with check_data. Please read the check_ functions section below and the function documentation.

Data Type Checkers

Check if the function input has a data type. You can use the function typeof() to confirm the data type.

Function Code
chk_environment(x) is.environment(x)
chk_logical(x) is.logical(x)
chk_character(x) is.character(x)

For numbers there are four functions. R differentiates between doubles (chk_double()) and integers (chk_integer()). You can also use the generic function chk_numeric(), which will detect both. The third type of number is complex (chk_complex()).

Function Code
chk_numeric(x) is.numeric(x)
chk_double(x) is.double(x)
chk_integer(x) is.integer(x)
chk_complex(x) is.complex(x)

Consider that to explicitly create an integer in R, you need to use the suffix L.

vld_numeric(33) # TRUE
#> [1] TRUE

vld_double(33) # TRUE
#> [1] TRUE
vld_integer(33) # FALSE
#> [1] FALSE

vld_integer(33L) # TRUE
#> [1] TRUE

Whole Number Checkers

These functions accept whole numbers, whether they are explicitly integers or double types without fractional parts.

Function Code
chk_whole_numeric is.integer(x) || (is.double(x) && vld_true(all.equal(x[!is.na(x)], trunc(x[!is.na(x)]))))
chk_whole_number vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x))))
chk_count vld_whole_number(x) && x >= 0

If you want to consider both 3.0 and 3L as integers, it is safer to use the function chk_whole_numeric. Here, x is valid if it’s an integer or a double that can be converted to an integer without changing its value.

# Integer vector
vld_whole_numeric(c(1L, 2L, 3L)) # TRUE
#> [1] TRUE

# Double vector representing whole numbers
vld_whole_numeric(c(1.0, 2.0, 3.0)) # TRUE
#> [1] TRUE

# Double vector with fractional numbers
vld_whole_numeric(c(1.0, 2.2, 3.0)) # FALSE
#> [1] FALSE

The function chk_whole_number is similar to chk_whole_numeric. chk_whole_number checks if the number is of length(x) == 1L

# Integer vector
vld_whole_numeric(c(1L, 2L, 3L)) # TRUE
#> [1] TRUE
vld_whole_number(c(1L, 2L, 3L)) # FALSE
#> [1] FALSE
vld_whole_number(c(1L)) # TRUE
#> [1] TRUE

chk_count() is a special case of chk_whole_number, differing in that it ensures values are non-negative whole numbers.

# Positive integer
vld_count(1) #TRUE
#> [1] TRUE
# Zero
vld_count(0) # TRUE
#> [1] TRUE
# Negative number
vld_count(-1) # FALSE
#> [1] FALSE
# Non-whole number
vld_count(2.5) # FALSE
#> [1] FALSE

Factor Checker

Check if the function input is a factor

Function Code
chk_factor is.factor(x)
chk_character_or_factor is.character(x) || is.factor(x)

Factors can be specially confusing for users, because despite they are displayed as characters are built in top of integer vectors.

chk provides the function chk_character_or_factor() that allows detecting if the argument that the user is providing contains strings.

# Factor with specified levels

vector_fruits <- c("apple", "banana", "apple", "orange", "banana", "apple")

factor_fruits <- factor(c("apple", "banana", "apple", "orange", "banana", "apple"),
                levels = c("apple", "banana", "orange"))


is.factor(factor_fruits) # TRUE
#> [1] TRUE
vld_factor(factor_fruits) # TRUE
#> [1] TRUE

is.character(factor_fruits) # FALSE
#> [1] FALSE
vld_character(factor_fruits) # FALSE
#> [1] FALSE

vld_character_or_factor(factor_fruits) # TRUE
#> [1] TRUE

All Elements Checkers

Check if the function input has a characteristic shared by all its elements.

If you want to apply any of the previously defined functions for length(x) == 1L to the elements of a vector, you can use chk_all().

Function Code
chk_all(x, chk_fun, ...) all(vapply(x, chk_fun, TRUE, ...))
vld_all(c(TRUE, TRUE, FALSE), chk_lgl) # FALSE
#> [1] FALSE

Function Checker

Check if the function input is another function

formals refers to the count of the number of formal arguments

Function Code
chk_function is.function(x) && (is.null(formals) || length(formals(x)) == formals)
vld_function(function(x) x, formals = 1) # TRUE
#> [1] TRUE
vld_function(function(x, y) x + y, formals = 1) # FALSE
#> [1] FALSE
vld_function(function(x, y) x + y, formals = 2) # TRUE
#> [1] TRUE

Name Checkers

Check if the function input has names and are valid chk_named function works with vectors, lists, data frames, and matrices that have named columns or rows. Do not confuse with check_names.

chk_valid_name function specifically designed to check if the elements of a character vector are valid R names. If you want to know what is considered a valid name, please refer to the documentation for the make.names function.

Function Code
chk_named(x) !is.null(names(x))
chk_valid_name(x) identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)]))

vld_valid_name(c("name1", NA, "name_2", "validName"))  # TRUE
#> [1] TRUE
vld_valid_name(c(1, 2, 3))  # FALSE
#> [1] FALSE


vld_named(data.frame(a = 1:5, b = 6:10))  # TRUE
#> [1] TRUE
vld_named(list(a = 1, b = 2)) # TRUE
#> [1] TRUE
vld_named(c(a = 1, b = 2)) # TRUE 
#> [1] TRUE
vld_named(c(1, 2, 3)) # FALSE 
#> [1] FALSE

Range Checkers

Check if the function input is part of a range of values. The function input should be numeric.

Function Code
chk_range(x, range = c(0, 1)) all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])
chk_lt(x, value = 0) all(x[!is.na(x)] < value)
chk_lte(x, value = 0) all(x[!is.na(x)] <= value)
chk_gt(x, value = 0) all(x[!is.na(x)] > value)
chk_gte(x, value = 0) all(x[!is.na(x)] >= value)

Equal Checkers

Check if the function input is equal or similar to a predefined object.

The functions chk_identical(), chk_equal(), and chk_equivalent() are used to compare two objects, but they differ in how strict the comparison is.

chk_equal and chk_equivalentchecks if x and y are numerically equivalent within a specified tolerance, but chk_equivalent ignores differences in attributes.

Function Code
chk_identical(x, y) identical(x, y)
chk_equal(x, y, tolerance = sqrt(.Machine$double.eps)) vld_true(all.equal(x, y, tolerance))
chk_equivalent(x, y, tolerance = sqrt(.Machine$double.eps)) vld_true(all.equal(x, y, tolerance, check.attributes = FALSE))

In the case you want to compare the elements of a vector, you can use the check_all_* functions.

Function Code
chk_all_identical(x) length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]]))
chk_all_equal(x, tolerance = sqrt(.Machine$double.eps)) length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance))
chk_all_equivalent(x, tolerance = sqrt(.Machine$double.eps)) length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance))
vld_all_identical(c(1, 2, 3)) # FALSE
#> [1] FALSE
vld_all_identical(c(1, 1, 1)) # TRUE
#> [1] TRUE
vld_identical(c(1, 2, 3), c(1, 2, 3)) # TRUE
#> [1] TRUE

vld_all_equal(c(0.1, 0.12, 0.13))
#> [1] FALSE
vld_all_equal(c(0.1, 0.12, 0.13), tolerance = 0.2)
#> [1] TRUE
vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.13)) # TRUE
#> [1] TRUE
vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.4), tolerance = 0.5) # TRUE
#> [1] TRUE

x <- c(0.1, 0.1, 0.1)
y <- c(0.1, 0.12, 0.13)
attr(y, "label") <- "Numbers"
vld_equal(x, y, tolerance = 0.5) # FALSE
#> [1] FALSE
vld_equivalent(x, y, tolerance = 0.5) # TRUE
#> [1] TRUE

Order Checker

Check if the function input are numbers in increasing order chk_sorted function checks if x is sorted in non-decreasing order, ignoring any NA values.

Function Code
chk_sorted(x) !is.unsorted(x, na.rm = TRUE)
# Checking if sorted
vld_sorted(c(1, 2, 3, NA, 4))  # TRUE
#> [1] TRUE
vld_sorted(c(3, 1, 2, NA, 4))  # FALSE
#> [1] FALSE

Set Checkers

Check if the function input is composed by certain elements

The setequal function in R is used to check if two vectors contain exactly the same elements, regardless of the order or number of repetitions.

Function Code
chk_setequal(x, values) setequal(x, values)
vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE
#> [1] TRUE
vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE
#> [1] FALSE
vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE
#> [1] FALSE
vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE
#> [1] TRUE

First, the %in% function is used to check whether the elements of a vector x are present in a specified set of values. This returns a logical vector, which is then simplified by all(). The all() function checks if all values in the vector are TRUE. If the result is TRUE, it indicates that for vld_ and chk_subset(), all elements in the x vector are present in values. Similarly, for vld_ and chk_superset(), it indicates that all elements of values are present in x.

Function Code
chk_subset(x, values) all(x %in% values)
chk_not_subset(x, values) !any(x %in% values) || !length(x)
chk_superset(x, values) all(values %in% x)

# When both function inputs have the same elements,
# all functions return TRUE

vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE
#> [1] TRUE
vld_subset(c(1, 2, 3), c(3, 2, 1)) # TRUE
#> [1] TRUE
vld_superset(c(1, 2, 3), c(3, 2, 1)) # TRUE
#> [1] TRUE

vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE
#> [1] TRUE
vld_subset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE
#> [1] TRUE
vld_superset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE
#> [1] TRUE

# When there are elements present in one vector but not the other,
# `vld_setequal()` will return FALSE

vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE
#> [1] FALSE
vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE
#> [1] FALSE

# When some elements of the `x` input are not present in `values`,
# `vld_subset()` returns FALSE
vld_subset(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE
#> [1] FALSE
vld_superset(c(1, 2, 3, 4), c(3, 2, 1)) # TRUE
#> [1] TRUE

# When some elements of the `values` input are not present in `x`,
# `vld_superset()` returns FALSE

vld_subset(c(1, 2, 3), c(3, 2, 1, 4)) # TRUE
#> [1] TRUE
vld_superset(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE
#> [1] FALSE

# An empty set is considered a subset of any set, and any set is a superset of an empty set.
vld_subset(c(), c("apple", "banana"))  # TRUE
#> [1] TRUE
vld_superset(c("apple", "banana"), c())  # TRUE
#> [1] TRUE

chk_orderset() validate whether a given set of values in a vector x matches a specified set of allowed values (represented by values) while preserving the order of those values.

Function Code
chk_orderset vld_equivalent(unique(x[x %in% values]), values[values %in% x])
vld_orderset(c("A", "B", "C"),  c("A", "B", "C", "D")) # TRUE
#> [1] TRUE
vld_orderset(c("C", "B", "A"),  c("A", "B", "C", "D")) # FALSE
#> [1] FALSE
vld_orderset(c("A", "C"),  c("A", "B", "C", "D")) # TRUE
#> [1] TRUE

Class Checkers

Check if the function input belongs to a class or type.

These functions check if x is an S3 or S4 object of the specified class.

Function Code
chk_s3_class(x, class) !isS4(x) && inherits(x, class)
chk_s4_class(x, class) isS4(x) && methods::is(x, class)

chk_is() checks if x inherits from a specified class, regardless of whether it is an S3 or S4 object.

Function Code
chk_is(x, class) inherits(x, class)

REGEX Checker

Check if the function input matches a regular expression (REGEX).

chk_match(x, regexp = ".+") checks if the regular expression pattern specified by regexp matches all the non-missing values in the vector x. If regexp it is not specified by the user, chk_match checks whether all non-missing values in x contain at least one character (regexp = “.+”)

Function Code
chk_match(x, regexp = ".+") all(grepl(regexp, x[!is.na(x)]))

Quality Checkers (Miscellaneous)

Check if the function input meet some user defined quality criteria.

chk_not_empty function checks if the length of the object is not zero. For a data frame or matrix, the length corresponds to the number of elements (not rows or columns), while for a vector or list, it corresponds to the number of elements.

chk_not_any_na function checks if there are no NA values present in the entire object.

Function Code
chk_not_empty(x) length(x) != 0L
chk_not_any_na(x) !anyNA(x)
vld_not_empty(c()) # FALSE
#> [1] FALSE
vld_not_empty(list()) # FALSE
#> [1] FALSE
vld_not_empty(data.frame()) # FALSE
#> [1] FALSE
vld_not_empty(data.frame(a = 1:3, b = 4:6)) # TRUE
#> [1] TRUE


vld_not_any_na(data.frame(a = 1:3, b = 4:6)) # TRUE
#> [1] TRUE
vld_not_any_na(data.frame(a = c(1, NA, 3), b = c(4, 5, 6))) # FALSE
#> [1] FALSE

The chk_unique() function is designed to verify that there are no duplicates elements in a vector.

Function Code
chk_unique(x, incomparables = FALSE) !anyDuplicated(x, incomparables = incomparables)
vld_unique(c(1, 2, 3, 4)) # TRUE
#> [1] TRUE
vld_unique(c(1, 2, 2, 4)) # FALSE
#> [1] FALSE

The function chk_length checks whether the length of x is within a specified range. It ensures that the length is at least equal to length and no more than upper. It can be used with vectors, lists and data frames.

Function Code
chk_length(x, length = 1L, upper = length) length(x) >= length && length(x) <= upper
vld_length(c(1, 2, 3), length = 2, upper = 5)  # TRUE
#> [1] TRUE
vld_length(c("a", "b"), length = 3)  # FALSE
#> [1] FALSE

vld_length(list(a = 1, b = 2, c = 3), length = 2, upper = 4) # TRUE
#> [1] TRUE
vld_length(list(a = 1, b = 2, c = 3), length = 4) # FALSE
#> [1] FALSE

# 2 columns
vld_length(data.frame(x = 1:3, y = 4:6), length = 1, upper = 3)  # TRUE
#> [1] TRUE
vld_length(data.frame(x = 1:3, y = 4:6), length = 3)  # FALSE    
#> [1] FALSE

# length of NULL is 0
vld_length(NULL, length = 0) # TRUE
#> [1] TRUE
vld_length(NULL, length = 1) # FALSE
#> [1] FALSE

Another useful function is chk_compatible_lenghts(). This function helps to check vectors could be ‘strictly recycled’.

a <- integer(0)
b <- numeric(0)
vld_compatible_lengths(a, b) # TRUE
#> [1] TRUE

a <- 1
b <- 2
vld_compatible_lengths(a, b) # TRUE
#> [1] TRUE

a <- 1:3
b <- 1:3
vld_compatible_lengths(a, b) # TRUE
#> [1] TRUE

b <- 1
vld_compatible_lengths(a, b) # TRUE
#> [1] TRUE

b <- 1:2
vld_compatible_lengths(a, b) # FALSE
#> [1] FALSE

b <- 1:6
vld_compatible_lengths(a, b) # FALSE
#> [1] FALSE

The chk_join() function is designed to validate whether the number of rows in the resulting data frame from merging two data frames (x and y) is equal to the number of rows in the first data frame (x). This is useful when you want to ensure that a join operation does not change the number of rows in your main data frame.

Function Code
chk_join(x, y, by) identical(nrow(x), nrow(merge(x, unique(y[if (is.null(names(by))) by else names(by)]), by = by)))
x <- data.frame(id = c(1, 2, 3), value_x = c("A", "B", "C"))
y <- data.frame(id = c(1, 2, 3), value_y = c("D", "E", "F"))
vld_join(x, y, by = "id") # TRUE
#> [1] TRUE

# Perform a join that reduces the number of rows 
y <- data.frame(id = c(1, 2, 1), value_y = c("D", "E", "F"))
vld_join(x, y, by = "id") # FALSE
#> [1] FALSE

check_ functions

The check_ functions combine several chk_ functions internally. Read the documentation for each function to learn more about its specific use.

Function Description
check_values(x, values) Checks values and S3 class of an atomic object.
check_key(x, key = character(0), na_distinct = FALSE) Checks if columns have unique rows.
check_data(x, values, exclusive, order, nrow, key) Checks column names, values, number of rows and key for a data.frame.
check_dim(x, dim, values, dim_name) Checks dimension of an object.
check_dirs(x, exists) Checks if all directories exist (or if exists = FALSE do not exist as directories or files).
check_files(x, exists) Checks if all files exist (or if exists = FALSE do not exist as files or directories).
check_names(x, names, exclusive, order) Checks the names of an object.

References

Wickham, H. (2019). Advanced R, Second Edition (2nd ed.). Chapman and Hall/CRC.

chk/inst/doc/chk-families.Rmd0000644000176200001440000005153214743771503015562 0ustar liggesusers--- title: "chk Families" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{chk Families} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(chk) ``` ## Introduction The `vld_` functions are used within the `chk_` functions. The `chk_` functions (and their `vld_` equivalents) can be divided into the following families. In the code in this examples, we will use `vld_*` functions If you want to learn more about the logic behind some of the functions explained here, we recommend reading the book [Advanced R](https://adv-r.hadley.nz/) (Wickham, 2019). For reasons of space, the `x_name = NULL` argument is not shown. For a more simplified list of the `chk` functions, you can see the [Reference](https://poissonconsulting.github.io/chk/reference/index.html) section. ## `chk_` Functions ### Overview ```{r chk_, echo = FALSE, out.width= "100%", fig.align='center', fig.alt = "Classification of the chk functions by family"} knitr::include_graphics("chk_diagram_II.png") ``` ### Missing Input Checker Check if the function input is missing or not `chk_missing` function uses `missing()` to check if an argument has been left out when the function is called. Function | Code :- | :--- `chk_missing()` | `missing()` `chk_not_missing()` | `!missing()` ### `...` Checker Check if the function input comes from `...` (`dot-dot-dot`) or not The functions `chk_used(...)` and `chk_unused(...)` check if any arguments have been provided through `...` (called `dot-dot-dot` or ellipsis), which is commonly used in R to allow a variable number of arguments. Function | Code :- | :--- `chk_used(...)` | `length(list(...)) != 0L` `chk_unused(...)` | `length(list(...)) == 0L` ### External Data Source Checkers Check if the function input is a valid external data source. These `chk` functions check the existence of a file, the validity of its extension, and the existence of a directory. Function | Code :- | :--- `chk_file(x)` | `vld_string(x) && file.exists(x) && !dir.exists(x)` `chk_ext(x, ext)` | `vld_string(x) && vld_subset(tools::file_ext(x), ext)` `chk_dir(x)` | `vld_string(x) && dir.exists(x)` ### NULL checker Check if the function input is NULL or not Function | Code :- | :--- `chk_null(x)` | `is.null(x)` `chk_not_null(x)` | `!is.null(x)` ### Scalar Checkers Check if the function input is a scalar. In R, scalars are vectors of length 1. Function | Code :- | :------ `chk_scalar(x)` | `length(x) == 1L` The following functions check if the functions inputs are vectors of length 1 of a particular data type. Each data type has a special syntax to create an individual value or "scalar". Function | Code :- | :------ `chk_string(x)` | `is.character(x) && length(x) == 1L && !anyNA(x)` `chk_number(x)` | `is.numeric(x) && length(x) == 1L && !anyNA(x)` For logical data types, you can check flags using `chk_flag()`, which considers `TRUE` or `FALSE` as possible values, or use `chk_lgl()` to verify if a scalar is of type logical, including NA as element. Function | Code :- | :- `chk_flag(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x)` `chk_lgl(x)` | `is.logical(x) && length(x) == 1L` It is also possible to check if the user-provided argument is only `TRUE` or only `FALSE`: Function | Code :- | :- `chk_true(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x) && x` `chk_false(x)` | `is.logical(x) && length(x) == 1L && !anyNA(x) && !x` ### Date or DateTime Checkers Check if the function input is of class Date or DateTime Date and datetime classes can be checked with `chk_date` and `chk_datetime`. Function | Code :- | :------ `chk_date(x)` | `inherits(x, "Date") && length(x) == 1L && !anyNA(x)` `chk_date_time(x)` | `inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x)` ### Time Zone Checker Also you can check the time zone with `chk_tz()`. The available time zones can be retrieved using the function `OlsonNames()`. Function | Code :- | :------ `chk_tz(x)` | `is.character(x) && length(x) == 1L && !anyNA(x) && x %in% OlsonNames()` #### Data Structure Checker Check if the function input has a specific data structure. Vectors are a family of data types that come in two forms: atomic vectors and lists. When vectors consist of elements of the same data type, they can be considered atomic, matrices, or arrays. The elements in a list, however, can be of different types. To check if a function argument is a vector you can use `chk_vector()`. Function | Code :- | :--- `chk_vector(x)` | `is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x)` Pay attention that `chk_vector()` and `vld_vector()` are different from `is.vector()`, that will return FALSE if the vector has any attributes except names. ```{r} vector <- c(1, 2, 3) is.vector(vector) # TRUE vld_vector(vector) # TRUE attributes(vector) <- list("a" = 10, "b" = 20, "c" = 30) is.vector(vector) # FALSE vld_vector(vector) # TRUE ``` Function | Code :- | :--- `chk_atomic(x)` | `is.atomic(x)` Notice that `is.atomic` is true for the types logical, integer, numeric, complex, character and raw. Also, it is TRUE for NULL. ```{r} vector <- c(1, 2, 3) is.atomic(vector) # TRUE vld_vector(vector) # TRUE is.atomic(NULL) # TRUE vld_vector(NULL) # TRUE ``` The dimension attribute converts vectors into matrices and arrays. Function | Code :- | :--- `chk_array(x)` | `is.array(x)` `chk_matrix(x)` | `is.matrix(x)` When a vector is composed by heterogeneous data types, can be a list. Data frames are among the most important S3 vectors, constructed on top of lists. Function | Code :- | :--- `chk_list(x)` | `is.list()` `chk_data(x)` | `inherits(x, "data.frame")` Be careful not to confuse the function `chk_data` with `check_data`. Please read the `check_` functions section below and the function documentation. ### Data Type Checkers Check if the function input has a data type. You can use the function `typeof()` to confirm the data type. Function | Code :- | :--- `chk_environment(x)` | `is.environment(x)` `chk_logical(x)` | `is.logical(x)` `chk_character(x)` | `is.character(x)` For numbers there are four functions. R differentiates between doubles (`chk_double()`) and integers (`chk_integer()`). You can also use the generic function `chk_numeric()`, which will detect both. The third type of number is complex (`chk_complex()`). Function | Code :- | :--- `chk_numeric(x)` | `is.numeric(x)` `chk_double(x)` | `is.double(x)` `chk_integer(x)` | `is.integer(x)` `chk_complex(x)` | `is.complex(x)` Consider that to explicitly create an integer in R, you need to use the suffix `L`. ```{r} vld_numeric(33) # TRUE vld_double(33) # TRUE vld_integer(33) # FALSE vld_integer(33L) # TRUE ``` ### Whole Number Checkers These functions accept whole numbers, whether they are explicitly integers or double types without fractional parts. Function | Code :- | :--- `chk_whole_numeric` | `is.integer(x) || (is.double(x) && vld_true(all.equal(x[!is.na(x)], trunc(x[!is.na(x)]))))` `chk_whole_number` | `vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x))))` `chk_count` | `vld_whole_number(x) && x >= 0` If you want to consider both 3.0 and 3L as integers, it is safer to use the function `chk_whole_numeric`. Here, `x` is valid if it's an integer or a double that can be converted to an integer without changing its value. ```{r} # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE # Double vector representing whole numbers vld_whole_numeric(c(1.0, 2.0, 3.0)) # TRUE # Double vector with fractional numbers vld_whole_numeric(c(1.0, 2.2, 3.0)) # FALSE ``` The function `chk_whole_number` is similar to `chk_whole_numeric`. `chk_whole_number` checks if the number is of `length(x) == 1L` ```{r} # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE vld_whole_number(c(1L, 2L, 3L)) # FALSE vld_whole_number(c(1L)) # TRUE ``` `chk_count()` is a special case of `chk_whole_number`, differing in that it ensures values are non-negative whole numbers. ```{r} # Positive integer vld_count(1) #TRUE # Zero vld_count(0) # TRUE # Negative number vld_count(-1) # FALSE # Non-whole number vld_count(2.5) # FALSE ``` ### Factor Checker Check if the function input is a factor Function | Code :- | :------ `chk_factor` | `is.factor(x)` `chk_character_or_factor` | `is.character(x) || is.factor(x)` Factors can be specially confusing for users, because despite they are displayed as characters are built in top of integer vectors. `chk` provides the function `chk_character_or_factor()` that allows detecting if the argument that the user is providing contains strings. ```{r} # Factor with specified levels vector_fruits <- c("apple", "banana", "apple", "orange", "banana", "apple") factor_fruits <- factor(c("apple", "banana", "apple", "orange", "banana", "apple"), levels = c("apple", "banana", "orange")) is.factor(factor_fruits) # TRUE vld_factor(factor_fruits) # TRUE is.character(factor_fruits) # FALSE vld_character(factor_fruits) # FALSE vld_character_or_factor(factor_fruits) # TRUE ``` ### All Elements Checkers Check if the function input has a characteristic shared by all its elements. If you want to apply any of the previously defined functions for `length(x) == 1L` to the elements of a vector, you can use `chk_all()`. Function | Code :- | :--- `chk_all(x, chk_fun, ...)` | `all(vapply(x, chk_fun, TRUE, ...))` ```{r} vld_all(c(TRUE, TRUE, FALSE), chk_lgl) # FALSE ``` ### Function Checker Check if the function input is another function `formals` refers to the count of the number of formal arguments Function | Code :- | :------ `chk_function` | `is.function(x) && (is.null(formals) || length(formals(x)) == formals)` ```{r} vld_function(function(x) x, formals = 1) # TRUE vld_function(function(x, y) x + y, formals = 1) # FALSE vld_function(function(x, y) x + y, formals = 2) # TRUE ``` ### Name Checkers Check if the function input has names and are valid `chk_named` function works with vectors, lists, data frames, and matrices that have named columns or rows. Do not confuse with `check_names`. `chk_valid_name` function specifically designed to check if the elements of a character vector are valid R names. If you want to know what is considered a valid name, please refer to the documentation for the `make.names` function. Function | Code :- | :-- `chk_named(x)` | `!is.null(names(x))` `chk_valid_name(x)` | `identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)]))` ```{r} vld_valid_name(c("name1", NA, "name_2", "validName")) # TRUE vld_valid_name(c(1, 2, 3)) # FALSE vld_named(data.frame(a = 1:5, b = 6:10)) # TRUE vld_named(list(a = 1, b = 2)) # TRUE vld_named(c(a = 1, b = 2)) # TRUE vld_named(c(1, 2, 3)) # FALSE ``` ### Range Checkers Check if the function input is part of a range of values. The function input should be numeric. Function | Code :- | :--- `chk_range(x, range = c(0, 1))` | `all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])` `chk_lt(x, value = 0)` | `all(x[!is.na(x)] < value)` `chk_lte(x, value = 0)` | `all(x[!is.na(x)] <= value)` `chk_gt(x, value = 0)` | `all(x[!is.na(x)] > value)` `chk_gte(x, value = 0)` | `all(x[!is.na(x)] >= value)` ### Equal Checkers Check if the function input is equal or similar to a predefined object. The functions `chk_identical()`, `chk_equal()`, and `chk_equivalent()` are used to compare two objects, but they differ in how strict the comparison is. `chk_equal` and `chk_equivalent`checks if x and y are numerically equivalent within a specified tolerance, but `chk_equivalent` ignores differences in attributes. Function | Code :-- | :- `chk_identical(x, y)` | `identical(x, y)` `chk_equal(x, y, tolerance = sqrt(.Machine$double.eps))` | `vld_true(all.equal(x, y, tolerance))` `chk_equivalent(x, y, tolerance = sqrt(.Machine$double.eps))` | `vld_true(all.equal(x, y, tolerance, check.attributes = FALSE))` In the case you want to compare the elements of a vector, you can use the `check_all_*` functions. Function | Code :-- | :-- `chk_all_identical(x)` | `length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]]))` `chk_all_equal(x, tolerance = sqrt(.Machine$double.eps))` | `length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance))` `chk_all_equivalent(x, tolerance = sqrt(.Machine$double.eps))` | `length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance))` ```{r} vld_all_identical(c(1, 2, 3)) # FALSE vld_all_identical(c(1, 1, 1)) # TRUE vld_identical(c(1, 2, 3), c(1, 2, 3)) # TRUE vld_all_equal(c(0.1, 0.12, 0.13)) vld_all_equal(c(0.1, 0.12, 0.13), tolerance = 0.2) vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.13)) # TRUE vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.4), tolerance = 0.5) # TRUE x <- c(0.1, 0.1, 0.1) y <- c(0.1, 0.12, 0.13) attr(y, "label") <- "Numbers" vld_equal(x, y, tolerance = 0.5) # FALSE vld_equivalent(x, y, tolerance = 0.5) # TRUE ``` ### Order Checker Check if the function input are numbers in increasing order `chk_sorted` function checks if `x` is sorted in non-decreasing order, ignoring any NA values. Function | Code :- | :-- `chk_sorted(x)` | `!is.unsorted(x, na.rm = TRUE)` ```{r} # Checking if sorted vld_sorted(c(1, 2, 3, NA, 4)) # TRUE vld_sorted(c(3, 1, 2, NA, 4)) # FALSE ``` ### Set Checkers Check if the function input is composed by certain elements The `setequal` function in R is used to check if two vectors contain exactly the same elements, regardless of the order or number of repetitions. Function | Code :- | :--- `chk_setequal(x, values)` | `setequal(x, values)` ```{r} vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE ``` First, the `%in%` function is used to check whether the elements of a vector `x` are present in a specified set of values. This returns a logical vector, which is then simplified by `all()`. The `all()` function checks if all values in the vector are TRUE. If the result is TRUE, it indicates that for `vld_` and `chk_subset()`, all elements in the `x` vector are present in `values`. Similarly, for `vld_` and `chk_superset()`, it indicates that all elements of `values` are present in `x`. Function | Code :-- | :-- `chk_subset(x, values)` | `all(x %in% values)` `chk_not_subset(x, values)` | `!any(x %in% values) || !length(x)` `chk_superset(x, values)` | `all(values %in% x)` ```{r} # When both function inputs have the same elements, # all functions return TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_subset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_subset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_superset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE # When there are elements present in one vector but not the other, # `vld_setequal()` will return FALSE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE # When some elements of the `x` input are not present in `values`, # `vld_subset()` returns FALSE vld_subset(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_superset(c(1, 2, 3, 4), c(3, 2, 1)) # TRUE # When some elements of the `values` input are not present in `x`, # `vld_superset()` returns FALSE vld_subset(c(1, 2, 3), c(3, 2, 1, 4)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE # An empty set is considered a subset of any set, and any set is a superset of an empty set. vld_subset(c(), c("apple", "banana")) # TRUE vld_superset(c("apple", "banana"), c()) # TRUE ``` `chk_orderset()` validate whether a given set of `values` in a vector x matches a specified set of allowed `values` (represented by `values`) while preserving the order of those values. Function | Code :-- | :-- `chk_orderset` | `vld_equivalent(unique(x[x %in% values]), values[values %in% x])` ```{r} vld_orderset(c("A", "B", "C"), c("A", "B", "C", "D")) # TRUE vld_orderset(c("C", "B", "A"), c("A", "B", "C", "D")) # FALSE vld_orderset(c("A", "C"), c("A", "B", "C", "D")) # TRUE ``` ### Class Checkers Check if the function input belongs to a class or type. These functions check if `x` is an S3 or S4 object of the specified class. Function | Code :- | :--- `chk_s3_class(x, class)` | `!isS4(x) && inherits(x, class)` `chk_s4_class(x, class)` | `isS4(x) && methods::is(x, class)` `chk_is()` checks if x inherits from a specified class, regardless of whether it is an S3 or S4 object. Function | Code :- | :--- `chk_is(x, class)` | `inherits(x, class)` ### REGEX Checker Check if the function input matches a regular expression (REGEX). `chk_match(x, regexp = ".+")` checks if the regular expression pattern specified by `regexp` matches all the non-missing values in the vector `x`. If `regexp` it is not specified by the user, `chk_match` checks whether all non-missing values in `x` contain at least one character (regexp = ".+") Function | Code :- | :-- `chk_match(x, regexp = ".+")` | `all(grepl(regexp, x[!is.na(x)]))` ### Quality Checkers (Miscellaneous) Check if the function input meet some user defined quality criteria. `chk_not_empty` function checks if the length of the object is not zero. For a data frame or matrix, the length corresponds to the number of elements (not rows or columns), while for a vector or list, it corresponds to the number of elements. `chk_not_any_na` function checks if there are no NA values present in the entire object. Function | Code :- | :-- `chk_not_empty(x)` | `length(x) != 0L` `chk_not_any_na(x)` | `!anyNA(x)` ```{r} vld_not_empty(c()) # FALSE vld_not_empty(list()) # FALSE vld_not_empty(data.frame()) # FALSE vld_not_empty(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = c(1, NA, 3), b = c(4, 5, 6))) # FALSE ``` The `chk_unique()` function is designed to verify that there are no duplicates elements in a vector. Function | Code :- | :-- `chk_unique(x, incomparables = FALSE)` | `!anyDuplicated(x, incomparables = incomparables)` ```{r} vld_unique(c(1, 2, 3, 4)) # TRUE vld_unique(c(1, 2, 2, 4)) # FALSE ``` The function `chk_length` checks whether the length of `x` is within a specified range. It ensures that the length is at least equal to `length` and no more than `upper`. It can be used with vectors, lists and data frames. Function | Code :- | :-- `chk_length(x, length = 1L, upper = length)` | `length(x) >= length && length(x) <= upper` ```{r} vld_length(c(1, 2, 3), length = 2, upper = 5) # TRUE vld_length(c("a", "b"), length = 3) # FALSE vld_length(list(a = 1, b = 2, c = 3), length = 2, upper = 4) # TRUE vld_length(list(a = 1, b = 2, c = 3), length = 4) # FALSE # 2 columns vld_length(data.frame(x = 1:3, y = 4:6), length = 1, upper = 3) # TRUE vld_length(data.frame(x = 1:3, y = 4:6), length = 3) # FALSE # length of NULL is 0 vld_length(NULL, length = 0) # TRUE vld_length(NULL, length = 1) # FALSE ``` Another useful function is `chk_compatible_lenghts()`. This function helps to check vectors could be 'strictly recycled'. ```{r} a <- integer(0) b <- numeric(0) vld_compatible_lengths(a, b) # TRUE a <- 1 b <- 2 vld_compatible_lengths(a, b) # TRUE a <- 1:3 b <- 1:3 vld_compatible_lengths(a, b) # TRUE b <- 1 vld_compatible_lengths(a, b) # TRUE b <- 1:2 vld_compatible_lengths(a, b) # FALSE b <- 1:6 vld_compatible_lengths(a, b) # FALSE ``` The `chk_join()` function is designed to validate whether the number of rows in the resulting data frame from merging two data frames (`x` and `y`) is equal to the number of rows in the first data frame (`x`). This is useful when you want to ensure that a join operation does not change the number of rows in your main data frame. Function | Code :- | :-- `chk_join(x, y, by)` | `identical(nrow(x), nrow(merge(x, unique(y[if (is.null(names(by))) by else names(by)]), by = by)))` ```{r} x <- data.frame(id = c(1, 2, 3), value_x = c("A", "B", "C")) y <- data.frame(id = c(1, 2, 3), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # TRUE # Perform a join that reduces the number of rows y <- data.frame(id = c(1, 2, 1), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # FALSE ``` ## `check_` functions The `check_` functions combine several `chk_` functions internally. Read the documentation for each function to learn more about its specific use. Function | Description :- | :-- `check_values(x, values)` | Checks values and S3 class of an atomic object. `check_key(x, key = character(0), na_distinct = FALSE)` | Checks if columns have unique rows. `check_data(x, values, exclusive, order, nrow, key)` | Checks column names, values, number of rows and key for a data.frame. `check_dim(x, dim, values, dim_name)` | Checks dimension of an object. `check_dirs(x, exists)` | Checks if all directories exist (or if exists = FALSE do not exist as directories or files). `check_files(x, exists)` | Checks if all files exist (or if exists = FALSE do not exist as files or directories). `check_names(x, names, exclusive, order)` | Checks the names of an object. ## References Wickham, H. (2019). Advanced R, Second Edition (2nd ed.). Chapman and Hall/CRC. chk/inst/doc/chk-families.R0000644000176200001440000001623214744765206015243 0ustar liggesusers## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(chk) ## ----chk_, echo = FALSE, out.width= "100%", fig.align='center', fig.alt = "Classification of the chk functions by family"---- knitr::include_graphics("chk_diagram_II.png") ## ----------------------------------------------------------------------------- vector <- c(1, 2, 3) is.vector(vector) # TRUE vld_vector(vector) # TRUE attributes(vector) <- list("a" = 10, "b" = 20, "c" = 30) is.vector(vector) # FALSE vld_vector(vector) # TRUE ## ----------------------------------------------------------------------------- vector <- c(1, 2, 3) is.atomic(vector) # TRUE vld_vector(vector) # TRUE is.atomic(NULL) # TRUE vld_vector(NULL) # TRUE ## ----------------------------------------------------------------------------- vld_numeric(33) # TRUE vld_double(33) # TRUE vld_integer(33) # FALSE vld_integer(33L) # TRUE ## ----------------------------------------------------------------------------- # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE # Double vector representing whole numbers vld_whole_numeric(c(1.0, 2.0, 3.0)) # TRUE # Double vector with fractional numbers vld_whole_numeric(c(1.0, 2.2, 3.0)) # FALSE ## ----------------------------------------------------------------------------- # Integer vector vld_whole_numeric(c(1L, 2L, 3L)) # TRUE vld_whole_number(c(1L, 2L, 3L)) # FALSE vld_whole_number(c(1L)) # TRUE ## ----------------------------------------------------------------------------- # Positive integer vld_count(1) #TRUE # Zero vld_count(0) # TRUE # Negative number vld_count(-1) # FALSE # Non-whole number vld_count(2.5) # FALSE ## ----------------------------------------------------------------------------- # Factor with specified levels vector_fruits <- c("apple", "banana", "apple", "orange", "banana", "apple") factor_fruits <- factor(c("apple", "banana", "apple", "orange", "banana", "apple"), levels = c("apple", "banana", "orange")) is.factor(factor_fruits) # TRUE vld_factor(factor_fruits) # TRUE is.character(factor_fruits) # FALSE vld_character(factor_fruits) # FALSE vld_character_or_factor(factor_fruits) # TRUE ## ----------------------------------------------------------------------------- vld_all(c(TRUE, TRUE, FALSE), chk_lgl) # FALSE ## ----------------------------------------------------------------------------- vld_function(function(x) x, formals = 1) # TRUE vld_function(function(x, y) x + y, formals = 1) # FALSE vld_function(function(x, y) x + y, formals = 2) # TRUE ## ----------------------------------------------------------------------------- vld_valid_name(c("name1", NA, "name_2", "validName")) # TRUE vld_valid_name(c(1, 2, 3)) # FALSE vld_named(data.frame(a = 1:5, b = 6:10)) # TRUE vld_named(list(a = 1, b = 2)) # TRUE vld_named(c(a = 1, b = 2)) # TRUE vld_named(c(1, 2, 3)) # FALSE ## ----------------------------------------------------------------------------- vld_all_identical(c(1, 2, 3)) # FALSE vld_all_identical(c(1, 1, 1)) # TRUE vld_identical(c(1, 2, 3), c(1, 2, 3)) # TRUE vld_all_equal(c(0.1, 0.12, 0.13)) vld_all_equal(c(0.1, 0.12, 0.13), tolerance = 0.2) vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.13)) # TRUE vld_equal(c(0.1, 0.12, 0.13), c(0.1, 0.12, 0.4), tolerance = 0.5) # TRUE x <- c(0.1, 0.1, 0.1) y <- c(0.1, 0.12, 0.13) attr(y, "label") <- "Numbers" vld_equal(x, y, tolerance = 0.5) # FALSE vld_equivalent(x, y, tolerance = 0.5) # TRUE ## ----------------------------------------------------------------------------- # Checking if sorted vld_sorted(c(1, 2, 3, NA, 4)) # TRUE vld_sorted(c(3, 1, 2, NA, 4)) # FALSE ## ----------------------------------------------------------------------------- vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE ## ----------------------------------------------------------------------------- # When both function inputs have the same elements, # all functions return TRUE vld_setequal(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_subset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1)) # TRUE vld_setequal(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_subset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE vld_superset(c(1, 2), c(1, 1, 1, 1, 1, 1, 2, 1)) # TRUE # When there are elements present in one vector but not the other, # `vld_setequal()` will return FALSE vld_setequal(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE vld_setequal(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE # When some elements of the `x` input are not present in `values`, # `vld_subset()` returns FALSE vld_subset(c(1, 2, 3, 4), c(3, 2, 1)) # FALSE vld_superset(c(1, 2, 3, 4), c(3, 2, 1)) # TRUE # When some elements of the `values` input are not present in `x`, # `vld_superset()` returns FALSE vld_subset(c(1, 2, 3), c(3, 2, 1, 4)) # TRUE vld_superset(c(1, 2, 3), c(3, 2, 1, 4)) # FALSE # An empty set is considered a subset of any set, and any set is a superset of an empty set. vld_subset(c(), c("apple", "banana")) # TRUE vld_superset(c("apple", "banana"), c()) # TRUE ## ----------------------------------------------------------------------------- vld_orderset(c("A", "B", "C"), c("A", "B", "C", "D")) # TRUE vld_orderset(c("C", "B", "A"), c("A", "B", "C", "D")) # FALSE vld_orderset(c("A", "C"), c("A", "B", "C", "D")) # TRUE ## ----------------------------------------------------------------------------- vld_not_empty(c()) # FALSE vld_not_empty(list()) # FALSE vld_not_empty(data.frame()) # FALSE vld_not_empty(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = 1:3, b = 4:6)) # TRUE vld_not_any_na(data.frame(a = c(1, NA, 3), b = c(4, 5, 6))) # FALSE ## ----------------------------------------------------------------------------- vld_unique(c(1, 2, 3, 4)) # TRUE vld_unique(c(1, 2, 2, 4)) # FALSE ## ----------------------------------------------------------------------------- vld_length(c(1, 2, 3), length = 2, upper = 5) # TRUE vld_length(c("a", "b"), length = 3) # FALSE vld_length(list(a = 1, b = 2, c = 3), length = 2, upper = 4) # TRUE vld_length(list(a = 1, b = 2, c = 3), length = 4) # FALSE # 2 columns vld_length(data.frame(x = 1:3, y = 4:6), length = 1, upper = 3) # TRUE vld_length(data.frame(x = 1:3, y = 4:6), length = 3) # FALSE # length of NULL is 0 vld_length(NULL, length = 0) # TRUE vld_length(NULL, length = 1) # FALSE ## ----------------------------------------------------------------------------- a <- integer(0) b <- numeric(0) vld_compatible_lengths(a, b) # TRUE a <- 1 b <- 2 vld_compatible_lengths(a, b) # TRUE a <- 1:3 b <- 1:3 vld_compatible_lengths(a, b) # TRUE b <- 1 vld_compatible_lengths(a, b) # TRUE b <- 1:2 vld_compatible_lengths(a, b) # FALSE b <- 1:6 vld_compatible_lengths(a, b) # FALSE ## ----------------------------------------------------------------------------- x <- data.frame(id = c(1, 2, 3), value_x = c("A", "B", "C")) y <- data.frame(id = c(1, 2, 3), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # TRUE # Perform a join that reduces the number of rows y <- data.frame(id = c(1, 2, 1), value_y = c("D", "E", "F")) vld_join(x, y, by = "id") # FALSE chk/inst/doc/chk.R0000644000176200001440000000205314744765207013451 0ustar liggesusers## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ## ----error=TRUE--------------------------------------------------------------- try({ library(chk) y <- TRUE chk_flag(y) y <- NA chk_flag(y) }) ## ----error=TRUE--------------------------------------------------------------- try({ vld_flag(TRUE) vld_flag(NA) }) ## ----error=TRUE--------------------------------------------------------------- try({ if (!vld_flag(NA)) abort_chk("`NA` is not TRUE or FALSE!!") }) ## ----error = TRUE------------------------------------------------------------- try({ fun1 <- function(x) { chk_whole_number(x) # use x } fun1(1) y <- 1.3 fun1(x = y) }) ## ----error = TRUE------------------------------------------------------------- try({ x <- NA chk_flag(x, x_name = "`zzz`") }) ## ----error=TRUE--------------------------------------------------------------- try({ abort_chk("There %r %n problem director%y%s.", n = 1) abort_chk("there %r %n ", "problem director%y%s", n = 2) }) chk/inst/doc/chk.html0000644000176200001440000004600714744765207014223 0ustar liggesusers Get Started with chk

Get Started with chk

Introduction

R functions and packages are great for sharing code, but it’s hard to predict how end-users will implement them. Users might pass inputs that your function wasn’t designed to handle, leading to incorrect results or errors. For example, if a function expects a numeric vector (e.g., c(1, 2, 3)) but receives a character vector (e.g.,c("1", "2", "3")), it may return an error.

The chk package provides a set of functions that check user-provided arguments and deliver meaningful error messages to guide users when something goes wrong. Including chk’s specially designed functions when developing your R package will help improve user experience, prevent errors, and make your code more robust by ensuring consistent behavior across different inputs. This enhances the reliability and reusability of your code.

Additionally, it can help with performance optimization by ensuring that your functions receive inputs of the appropriate size, thereby avoiding time-consuming calculations.

Goal

chk is an R package for developers to check user-supplied function arguments.

It is designed to be simple, customizable and fast.

chk Functions

Based on the function prefixes, we can classify chk functions into three categories:

  1. chk_ Functions
  2. vld_ Functions
  3. check_ Functions

1. chk_ Functions

chk_ functions check the properties of individual objects. For example, chk_flag(x) checks whether x is a flag, i.e., a non-missing logical vector of length 1.

chk_ functions are called for their side-effects, i.e., they throw an informative error if the object fails the check. Although do return an invisible copy of the first argument so they can be used in pipes.

library(chk)
y <- TRUE
chk_flag(y)
y <- NA
chk_flag(y)
#> Error:
#> ! `y` must be a flag (TRUE or FALSE).

The error messages, which follow the tidyverse style guide, are designed to allow the user to quickly identify the problem with the argument value(s) they are providing. The errors are rlang errors of subclass 'chk_error'.

2. vld_ Functions

Each chk_ function has a matching vld_ function which returns a flag indicating whether the object passed the check.

vld_flag(TRUE)
#> [1] TRUE
vld_flag(NA)
#> [1] FALSE

The vld_ functions allow developers to provide their own error messages.

if (!vld_flag(NA)) abort_chk("`NA` is not TRUE or FALSE!!")
#> Error:
#> ! `NA` is not TRUE or FALSE!!

3. check_ Functions

The check_ functions are more complex then the chk_ functions which make them slower but makes doing some general tests easier.

Using chk

The chk_ functions are designed to be used within functions. Consequently, when constructing an error message they use the name of the object that they received as this is expected to be the name of the argument.

fun1 <- function(x) {
  chk_whole_number(x)
  # use x
}

fun1(1)
y <- 1.3
fun1(x = y)
#> Error in `fun1()`:
#> ! `x` must be a whole number (non-missing integer scalar or double equivalent).

If this is not the case, developers can provide a different name using the x_name argument.

x <- NA
chk_flag(x, x_name = "`zzz`")
#> Error:
#> ! `zzz` must be a flag (TRUE or FALSE).

IMPORTANT NOTE

As the chk_ (and vld_) functions are not expected to be directly exposed to users they don’t check any of their arguments (other than the object of interest of course!) to ensure that they are as fast as possible.

Extending chk

The chk_flag() function illustrates the general structure of a chk_ function.

chk_flag
#> function(x, x_name = NULL){
#>   if(vld_flag(x)) return(invisible(x))
#>   if(is.null(x_name))  x_name <- deparse_backtick_chk(substitute(x))
#>   abort_chk(x_name, " must be a flag (TRUE or FALSE)")
#> }
#> <bytecode: 0x7fe802835670>
#> <environment: namespace:chk>

A chk_ function initially checks the object (using its vld_ partner) and if the object passes the check immediately returns an invisible copy of the object. If, and only if, the object fails the check does the chk_ function construct and then throw an informative error message.

The deparse_backtick_chk() and abort_chk() functions are exported to make it easy for programmers to develop their own chk_ functions. The chk-lgl.R script illustrates the general template to use when developing your own chk_ functions.

abort_chk()

The abort_chk() function converts multiple arguments to a string using paste0(..., collapse = '') and provides number sensitive sprintf-like types. By default it also capitalizes the first character and adds a missing period.

abort_chk("There %r %n problem director%y%s.", n = 1)
#> Error:
#> ! There is 1 problem directory.
abort_chk("there %r %n ", "problem director%y%s", n = 2)
#> Error:
#> ! There are 2 problem directories.
chk/inst/WORDLIST0000644000176200001440000000041714643076125013200 0ustar liggesusersAlls Amies Backtick CMD Codecov codecov Galonski Lifecycle NULLs ORCID POSIXct Tidyverse Typeof Un Unbacktick Undeprecated alls arg args backticked backtraces brac checkr customise customizable datacheckr funder ie lgl pkgdown rlang sprintf testthat tidyverse typeof vld chk/README.md0000644000176200001440000000631414743771503012315 0ustar liggesusers # chk chk logo of completed tick mark [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) [![R-CMD-check](https://github.com/poissonconsulting/chk/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/poissonconsulting/chk/actions/workflows/R-CMD-check.yaml) [![Codecov test coverage](https://codecov.io/gh/poissonconsulting/chk/graph/badge.svg)](https://app.codecov.io/gh/poissonconsulting/chk) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/license/mit) [![CRAN status](https://www.r-pkg.org/badges/version/chk)](https://cran.r-project.org/package=chk) ![CRAN downloads](https://cranlogs.r-pkg.org/badges/chk) `chk` is an R package for developers to check user-supplied function arguments. It is designed to be simple, customizable and fast. ## Demonstration `chk` provides simple commonly used checks as (`chk_` functions) which can be combined together for more complex checking. ``` r library(chk) y <- "a" chk_string(y) chk_flag(y) #> Error: #> ! `y` must be a flag (TRUE or FALSE). data <- data.frame(x = 1:2) chk_range(nrow(data), c(3, 8)) #> Error: #> ! `nrow(data)` must be between 3 and 8, not 2. ``` Or used inside functions to test user-provided arguments. ``` r my_fun <- function(x) { chk_flag(x) x } my_fun(TRUE) #> [1] TRUE my_fun(NA) #> Error in `my_fun()`: #> ! `x` must be a flag (TRUE or FALSE). ``` Error messages follow the [tidyverse style guide](https://style.tidyverse.org/errors.html) while the errors themselves are [rlang errors](https://rlang.r-lib.org/reference/abort.html) of class `chk_error`. ## Information For more information see the [Get Started](https://poissonconsulting.github.io/chk/articles/chk.html) vignette. ## Installation ### Release To install the release version from [CRAN](https://CRAN.R-project.org/package=chk). ``` r install.packages("chk") ``` The website for the release version is at . ### Development To install the development version from [GitHub](https://github.com/poissonconsulting/chk) ``` r # install.packages("remotes") remotes::install_github("poissonconsulting/chk") ``` or from [r-universe](https://poissonconsulting.r-universe.dev/chk). ``` r install.packages("chk", repos = c("https://poissonconsulting.r-universe.dev", "https://cloud.r-project.org")) ``` ## Inspiration - [datacheckr](https://github.com/poissonconsulting/datacheckr/) - [checkr](https://github.com/poissonconsulting/checkr/) - [err](https://github.com/poissonconsulting/err/) - [testthat](https://github.com/r-lib/testthat/) ## Contribution Please report any [issues](https://github.com/poissonconsulting/chk/issues). [Pull requests](https://github.com/poissonconsulting/chk/pulls) are always welcome. ## Code of Conduct Please note that the chk project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/0/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. chk/build/0000755000176200001440000000000014744765207012136 5ustar liggesuserschk/build/vignette.rds0000644000176200001440000000034714744765207014501 0ustar liggesusersuM0ˏ5<@/ pcԅJh,` qZcI\Mw!d"6iAi-am'N!#6H%wRX%WAjAS2c0vژ\\^ÜQ =1hZ3#%) tЎpc+sP1>ipOV5h}WWmdoNHA?%Y t1chk/man/0000755000176200001440000000000014744734003011600 5ustar liggesuserschk/man/params.Rd0000644000176200001440000000436314743771477013377 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/params.R \name{params} \alias{params} \alias{parameters} \alias{arguments} \alias{args} \title{Parameter Descriptions for chk Package} \arguments{ \item{...}{Additional arguments.} \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} \item{y}{An object to check against.} \item{chk}{A flag specifying whether to check the other parameters.} \item{chk_fun}{A chk_ function.} \item{tolerance}{A non-negative numeric scalar.} \item{ext}{A character vector of the permitted file extensions (without the .).} \item{exists}{A flag specifying whether the files/directories must (or must not) exist.} \item{value}{A non-missing scalar of a value.} \item{range}{A non-missing sorted vector of length 2 of the lower and upper permitted values.} \item{inclusive}{A flag specifying whether the range is exclusive.} \item{regexp}{A string of a regular expression.} \item{values}{A vector of the permitted values.} \item{class}{A string specifying the class.} \item{length}{A count of the length.} \item{upper}{A count of the max length.} \item{formals}{A count of the number of formal arguments.} \item{incomparables}{A vector of values that cannot be compared. FALSE means that all values can be compared.} \item{by}{A character vector specifying the column names to join x and y on. If named the names are the corresponding columns in x.} \item{exclusive}{A flag specifying whether x must only include columns named in values.} \item{order}{A flag specifying whether the order of columns in x must match names in values.} \item{nrow}{A flag or a whole numeric vector of the value, value range or possible values.} \item{key}{A character vector of the columns that represent a unique key.} \item{vld_fun}{A vld_ function.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Default parameter descriptions which may be overridden in individual functions. } \details{ A flag is a non-missing logical scalar. A string is a non-missing character scalar. } \keyword{internal} chk/man/check_dim.Rd0000644000176200001440000000212414744734003013774 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-dim.R \name{check_dim} \alias{check_dim} \title{Check Dimension} \usage{ check_dim(x, dim = length, values = numeric(0), x_name = NULL, dim_name = NULL) } \arguments{ \item{x}{The object to check.} \item{dim}{A function returning a non-negative whole number of the dimension.} \item{values}{A flag or a whole numeric vector of the value, value range or possible values.} \item{x_name}{A string of the name of object x or NULL.} \item{dim_name}{A string of the name of the dim function.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks dimension of an object. } \examples{ check_dim(1) try(check_dim(1, values = FALSE)) try(check_dim(1, values = c(10, 2))) try(check_dim(data.frame(x = 1), dim = nrow, values = c(10, 10, 2))) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_count.Rd0000644000176200001440000000267714743771477014077 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-count.R \name{chk_count} \alias{chk_count} \alias{vld_count} \title{Check Count} \usage{ chk_count(x, x_name = NULL) vld_count(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-negative whole number using \code{vld_whole_number(x) && x >= 0} } \section{Functions}{ \itemize{ \item \code{vld_count()}: Validate Count }} \examples{ # chk_count chk_count(1) try(chk_count(1.5)) # vld_count vld_count(1) vld_count(0L) vld_count(-1) vld_count(0.5) } \seealso{ \code{\link[=vld_whole_number]{vld_whole_number()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} Other whole_number_checkers: \code{\link{chk_whole_number}()}, \code{\link{chk_whole_numeric}()} } \concept{scalar_checkers} \concept{whole_number_checkers} chk/man/chk_not_missing.Rd0000644000176200001440000000242014743771477015262 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-missing.R \name{chk_not_missing} \alias{chk_not_missing} \alias{vld_not_missing} \title{Check Not Missing Argument} \usage{ chk_not_missing(x, x_name = "`x`") vld_not_missing(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks argument not missing using \code{!missing(x)} } \details{ Currently only checks if value is available (as opposed to whether it was specified). } \section{Functions}{ \itemize{ \item \code{vld_not_missing()}: Validate Not Missing Argument }} \examples{ # chk_not_missing fun <- function(x) { chk_not_missing(x) } fun(1) try(fun()) # vld_not_missing fun <- function(x) { vld_not_missing(x) } fun() fun(1) } \seealso{ \code{\link[=missing]{missing()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other missing_checkers: \code{\link{chk_function}()}, \code{\link{chk_missing}()} } \concept{missing_checkers} chk/man/chk_all_equivalent.Rd0000644000176200001440000000337214743771477015745 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-all-equivalent.R \name{chk_all_equivalent} \alias{chk_all_equivalent} \alias{vld_all_equivalent} \title{Check All Equivalent} \usage{ chk_all_equivalent(x, tolerance = sqrt(.Machine$double.eps), x_name = NULL) vld_all_equivalent(x, tolerance = sqrt(.Machine$double.eps)) } \arguments{ \item{x}{The object to check.} \item{tolerance}{A non-negative numeric scalar.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks all elements in x equivalent using \code{length(x) < 2L || all(vapply(x, vld_equivalent, TRUE, y = x[[1]], tolerance = tolerance))} } \section{Functions}{ \itemize{ \item \code{vld_all_equivalent()}: Validate All Equivalent }} \examples{ # chk_all_equivalent chk_all_equivalent(c(1, 1.00000001)) try(chk_all_equivalent(c(1, 1.0000001))) chk_all_equivalent(list(c(x = 1), c(x = 1))) chk_all_equivalent(list(c(x = 1), c(y = 1))) # vld_all_equivalent vld_all_equivalent(c(x = 1, y = 1)) } \seealso{ \code{\link[=length]{length()}} \code{\link[=vld_equivalent]{vld_equivalent()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_identical}()}, \code{\link{chk_equal}()}, \code{\link{chk_equivalent}()}, \code{\link{chk_identical}()} Other all_checkers: \code{\link{chk_all}()}, \code{\link{chk_all_equal}()}, \code{\link{chk_all_identical}()} } \concept{all_checkers} \concept{equal_checkers} chk/man/chk_complex.Rd0000644000176200001440000000256114743771477014406 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-complex.R \name{chk_complex} \alias{chk_complex} \alias{vld_complex} \title{Check Complex} \usage{ chk_complex(x, x_name = NULL) vld_complex(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if complex using \code{is.complex(x)} } \section{Functions}{ \itemize{ \item \code{vld_complex()}: Validate Complex }} \examples{ # chk_complex chk_complex(1i) try(chk_complex(1)) # vld_complex vld_complex(1i) vld_complex(complex()) vld_complex(NA_complex_) vld_complex(1) vld_complex(TRUE) } \seealso{ \code{\link[=is.complex]{is.complex()}} For more details about the use of this function, please read the article \href{https://poissonconsulting.github.io/chk/articles/chk-families.html}{chk families}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_equivalent.Rd0000644000176200001440000000305414743771477015112 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-equivalent.R \name{chk_equivalent} \alias{chk_equivalent} \alias{vld_equivalent} \title{Check Equivalent} \usage{ chk_equivalent(x, y, tolerance = sqrt(.Machine$double.eps), x_name = NULL) vld_equivalent(x, y, tolerance = sqrt(.Machine$double.eps)) } \arguments{ \item{x}{The object to check.} \item{y}{An object to check against.} \item{tolerance}{A non-negative numeric scalar.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is equivalent (equal ignoring attributes) to y using \code{vld_true(all.equal(x, y, tolerance, check.attributes = FALSE))} } \section{Functions}{ \itemize{ \item \code{vld_equivalent()}: Validate Equivalent }} \examples{ # chk_equivalent chk_equivalent(1, 1.00000001) try(chk_equivalent(1, 1.0000001)) chk_equivalent(1, 1L) chk_equivalent(c(x = 1), c(y = 1)) vld_equivalent(c(x = 1), c(y = 1L)) } \seealso{ \code{\link[=vld_true]{vld_true()}} \code{\link[=all.equal]{all.equal()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()}, \code{\link{chk_equal}()}, \code{\link{chk_identical}()} } \concept{equal_checkers} chk/man/expect_chk_error.Rd0000644000176200001440000000753514436206156015430 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/expect-chk-error.R \name{expect_chk_error} \alias{expect_chk_error} \title{Expect Chk Error} \usage{ expect_chk_error( object, regexp = NULL, ..., info = NULL, label = NULL, class = NULL ) } \arguments{ \item{object}{Object to test. Supports limited unquoting to make it easier to generate readable failures within a function or for loop. See \link[testthat]{quasi_label} for more details.} \item{regexp}{Regular expression to test against. \itemize{ \item A character vector giving a regular expression that must match the error message. \item If \code{NULL}, the default, asserts that there should be an error, but doesn't test for a specific value. \item If \code{NA}, asserts that there should be no errors, but we now recommend using \code{\link[testthat:expect_no_error]{expect_no_error()}} and friends instead. } Note that you should only use \code{message} with errors/warnings/messages that you generate. Avoid tests that rely on the specific text generated by another package since this can easily change. If you do need to test text generated by another package, either protect the test with \code{skip_on_cran()} or use \code{expect_snapshot()}.} \item{...}{ Arguments passed on to \code{\link[testthat:expect_match]{expect_match}} \describe{ \item{\code{fixed}}{If \code{TRUE}, treats \code{regexp} as a string to be matched exactly (not a regular expressions). Overrides \code{perl}.} \item{\code{perl}}{logical. Should Perl-compatible regexps be used?} }} \item{info}{Extra information to be included in the message. This argument is soft-deprecated and should not be used in new code. Instead see alternatives in \link[testthat]{quasi_label}.} \item{label}{Used to customise failure messages. For expert use only.} \item{class}{Must be NULL.} } \value{ If \code{regexp = NA}, the value of the first argument; otherwise the captured condition. } \description{ \code{\link[=expect_chk_error]{expect_chk_error()}} checks that code throws an error of class \code{"chk_error"} with a message that matches regexp. See below for more details. } \section{Testing \code{message} vs \code{class}}{ When checking that code generates an error, it's important to check that the error is the one you expect. There are two ways to do this. The first way is the simplest: you just provide a \code{regexp} that match some fragment of the error message. This is easy, but fragile, because the test will fail if the error message changes (even if its the same error). A more robust way is to test for the class of the error, if it has one. You can learn more about custom conditions at \url{https://adv-r.hadley.nz/conditions.html#custom-conditions}, but in short, errors are S3 classes and you can generate a custom class and check for it using \code{class} instead of \code{regexp}. If you are using \code{expect_error()} to check that an error message is formatted in such a way that it makes sense to a human, we recommend using \code{\link[testthat:expect_snapshot]{expect_snapshot()}} instead. } \examples{ expect_chk_error(chk_true(FALSE)) try(expect_chk_error(chk_false(FALSE))) } \seealso{ \code{\link[testthat:expect_no_error]{expect_no_error()}}, \code{expect_no_warning()}, \code{expect_no_message()}, and \code{expect_no_condition()} to assert that code runs without errors/warnings/messages/conditions. Other expectations: \code{\link[testthat]{comparison-expectations}}, \code{\link[testthat]{equality-expectations}}, \code{\link[testthat]{expect_length}()}, \code{\link[testthat]{expect_match}()}, \code{\link[testthat]{expect_named}()}, \code{\link[testthat]{expect_null}()}, \code{\link[testthat]{expect_output}()}, \code{\link[testthat]{expect_reference}()}, \code{\link[testthat]{expect_silent}()}, \code{\link[testthat]{inheritance-expectations}}, \code{\link[testthat]{logical-expectations}} } chk/man/chk_environment.Rd0000644000176200001440000000260714743771477015304 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-environment.R \name{chk_environment} \alias{chk_environment} \alias{vld_environment} \title{Check Environment} \usage{ chk_environment(x, x_name = NULL) vld_environment(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if environment using \code{is.environment(x)} } \section{Functions}{ \itemize{ \item \code{vld_environment()}: Validate Environment }} \examples{ # chk_environment chk_environment(.GlobalEnv) try(chk_environment(1)) # vld_environment vld_environment(1) vld_environment(list(1)) vld_environment(.GlobalEnv) vld_environment(environment()) } \seealso{ \code{\link[=is.environment]{is.environment()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_null.Rd0000644000176200001440000000174114743771477013710 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-null.R \name{chk_null} \alias{chk_null} \alias{vld_null} \title{Check NULL} \usage{ chk_null(x, x_name = NULL) vld_null(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if NULL using \code{is.null(x)} } \section{Functions}{ \itemize{ \item \code{vld_null()}: Validate NULL }} \examples{ # chk_null try(chk_null(1)) chk_null(NULL) # vld_null vld_null(NULL) vld_null(1) } \seealso{ \code{\link[=is.null]{is.null()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other null_checkers: \code{\link{chk_not_null}()} } \concept{null_checkers} chk/man/chk_gt.Rd0000644000176200001440000000243114743771477013345 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-gt.R \name{chk_gt} \alias{chk_gt} \alias{vld_gt} \title{Check Greater Than} \usage{ chk_gt(x, value = 0, x_name = NULL) vld_gt(x, value = 0) } \arguments{ \item{x}{The object to check.} \item{value}{A non-missing scalar of a value.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all non-missing values are greater than value using \code{all(x[!is.na(x)] > value)} } \section{Functions}{ \itemize{ \item \code{vld_gt()}: Validate Greater Than }} \examples{ # chk_gt chk_gt(0.1) try(chk_gt(c(0.1, -0.2))) # vld_gt vld_gt(numeric(0)) vld_gt(0) vld_gt(0.1) vld_gt(c(0.1, 0.2, NA)) vld_gt(c(0.1, -0.2)) vld_gt(c(-0.1, 0.2), value = -1) vld_gt("b", value = "a") } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other range_checkers: \code{\link{chk_gte}()}, \code{\link{chk_lt}()}, \code{\link{chk_lte}()}, \code{\link{chk_range}()} } \concept{range_checkers} chk/man/chk_unused.Rd0000644000176200001440000000161514743771477014241 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-unused.R \name{chk_unused} \alias{chk_unused} \alias{vld_unused} \title{Check ... Unused} \usage{ chk_unused(...) vld_unused(...) } \arguments{ \item{...}{Additional arguments.} } \value{ The \code{chk_} function throws an informative error if the test fails. } \description{ Checks if ... is unused \code{length(list(...)) == 0L} } \section{Functions}{ \itemize{ \item \code{vld_unused()}: Validate ... Unused }} \examples{ # chk_unused fun <- function(x, ...) { chk_unused(...) x } fun(1) try(fun(1, 2)) # vld_unused fun <- function(x, ...) { vld_unused(...) } fun(1) try(fun(1, 2)) } \seealso{ \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other ellipsis_checkers: \code{\link{chk_used}()} } \concept{ellipsis_checkers} chk/man/check_files.Rd0000644000176200001440000000167614744734003014340 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-files.R \name{check_files} \alias{check_files} \title{Check Files Exist} \usage{ check_files(x, exists = TRUE, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{exists}{A flag specifying whether the files/directories must (or must not) exist.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks if all files exist (or if exists = FALSE do not exist as files or directories). } \examples{ check_files(tempfile("unlikely-that-exists-chk"), exists = FALSE) try(check_files(tempfile("unlikely-that-exists-chk"))) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/message_chk.Rd0000644000176200001440000000242314436206156014342 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/err.R \name{message_chk} \alias{message_chk} \title{Construct Tidyverse Style Message} \usage{ message_chk(..., n = NULL, tidy = TRUE) } \arguments{ \item{...}{Multiple objects that are converted to a string using \code{paste0(..., collapse = '')}.} \item{n}{The value of n for converting \code{sprintf}-like types.} \item{tidy}{A flag specifying whether capitalize the first character and add a missing period.} } \value{ A string of the message. } \description{ If \code{tidy = TRUE} constructs a tidyverse style message by } \details{ \itemize{ \item Capitalizing the first character if possible. \item Adding a trailing . if missing. } Also if \code{n != NULL} replaces the recognized \code{sprintf}-like types. } \section{\code{sprintf}-like types}{ The following recognized \code{sprintf}-like types can be used in a message: \describe{ \item{\code{n}}{The value of n.} \item{\code{s}}{'' if n == 1 otherwise 's'} \item{\code{r}}{'is' if n == 1 otherwise 'are'} \item{\code{y}}{'y' if n == 1 otherwise 'ie'} } } \examples{ message_chk("there \%r \%n", " problem director\%y\%s") message_chk("there \%r \%n", " problem director\%y\%s", n = 1) message_chk("There \%r \%n", " problem director\%y\%s.", n = 3) } chk/man/chk_identical.Rd0000644000176200001440000000242614743771477014673 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-identical.R \name{chk_identical} \alias{chk_identical} \alias{vld_identical} \title{Check Identical} \usage{ chk_identical(x, y, x_name = NULL) vld_identical(x, y) } \arguments{ \item{x}{The object to check.} \item{y}{An object to check against.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is identical to y using \code{identical(x, y)} } \section{Functions}{ \itemize{ \item \code{vld_identical()}: Validate Identical }} \examples{ # chk_identical chk_identical(1, 1) try(chk_identical(1, 1L)) chk_identical(c(1, 1), c(1, 1)) try(chk_identical(1, c(1, 1))) vld_identical(1, 1) } \seealso{ \code{\link[=identical]{identical()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()}, \code{\link{chk_equal}()}, \code{\link{chk_equivalent}()} } \concept{equal_checkers} chk/man/chk_equal.Rd0000644000176200001440000000274714743771477014054 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-equal.R \name{chk_equal} \alias{chk_equal} \alias{vld_equal} \title{Check Equal} \usage{ chk_equal(x, y, tolerance = sqrt(.Machine$double.eps), x_name = NULL) vld_equal(x, y, tolerance = sqrt(.Machine$double.eps)) } \arguments{ \item{x}{The object to check.} \item{y}{An object to check against.} \item{tolerance}{A non-negative numeric scalar.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is equal (identical within tolerance) to y using \code{vld_true(all.equal(x, y, tolerance))} } \section{Functions}{ \itemize{ \item \code{vld_equal()}: Validate Equal }} \examples{ # chk_equal chk_equal(1, 1.00000001) try(chk_equal(1, 1.0000001)) chk_equal(1, 1L) chk_equal(c(x = 1), c(x = 1L)) try(chk_equal(c(x = 1), c(y = 1L))) vld_equal(1, 1.00000001) } \seealso{ \code{\link[=vld_true]{vld_true()}} \code{\link[=all.equal]{all.equal()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()}, \code{\link{chk_equivalent}()}, \code{\link{chk_identical}()} } \concept{equal_checkers} chk/man/chk_string.Rd0000644000176200001440000000246314743771477014246 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-string.R \name{chk_string} \alias{chk_string} \alias{vld_string} \title{Check String} \usage{ chk_string(x, x_name = NULL) vld_string(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if string \code{is.character(x) && length(x) == 1L && !anyNA(x)} } \section{Functions}{ \itemize{ \item \code{vld_string()}: Validate String }} \examples{ # chk_string chk_string("1") try(chk_string(1)) # vld_string vld_string("1") vld_string("") vld_string(1) vld_string(NA_character_) vld_string(c("1", "1")) } \seealso{ \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} } \concept{scalar_checkers} chk/man/chk_subset.Rd0000644000176200001440000000311714743771477014242 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-subset.R, R/chk-subset.R \name{vld_not_subset} \alias{vld_not_subset} \alias{chk_subset} \alias{vld_subset} \title{Check Subset} \usage{ vld_not_subset(x, values) chk_subset(x, values, x_name = NULL) vld_subset(x, values) } \arguments{ \item{x}{The object to check.} \item{values}{A vector of the permitted values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all values in values using \code{all(x \%in\% values)} Pay attention to the order of the arguments \code{value} and \code{x} in this function compared to \code{\link[=chk_superset]{chk_superset()}} } \section{Functions}{ \itemize{ \item \code{vld_not_subset()}: Validate Not Subset \item \code{vld_subset()}: Validate Subset }} \examples{ # vld_not_subset vld_not_subset(numeric(0), 1:10) vld_not_subset(1, 1:10) vld_not_subset(11, 1:10) # chk_subset chk_subset(1, 1:10) try(chk_subset(11, 1:10)) # vld_subset vld_subset(numeric(0), 1:10) vld_subset(1, 1:10) vld_subset(11, 1:10) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other set_checkers: \code{\link{chk_not_subset}()}, \code{\link{chk_orderset}()}, \code{\link{chk_superset}()}, \code{\link{vld_orderset}()} } \concept{set_checkers} chk/man/chkor_vld.Rd0000644000176200001440000000142614436206156014046 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chkor-vld.R \name{chkor_vld} \alias{chkor_vld} \title{Chk OR} \usage{ chkor_vld(...) } \arguments{ \item{...}{Multiple \code{vld_} calls. A common mistake is to pass \code{chk_} calls. \code{chkor_vld()} is relatively slow. If at all possible use \code{\link[=chk_null_or]{chk_null_or()}} or first test using the individual \code{vld_} functions and then call \code{chkor_vld()} to generate an informative error message.} } \value{ An informative error if the test fails. } \description{ Chk OR } \examples{ chkor_vld() chkor_vld(vld_flag(TRUE)) try(chkor_vld(vld_flag(1))) try(chkor_vld(vld_flag(1), vld_flag(2))) chkor_vld(vld_flag(1), vld_flag(TRUE)) } \seealso{ \code{\link[=chk_null_or]{chk_null_or()}} } chk/man/chk_raw.Rd0000644000176200001440000000233314743771477013525 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-raw.R \name{chk_raw} \alias{chk_raw} \alias{vld_raw} \title{Check Raw} \usage{ chk_raw(x, x_name = NULL) vld_raw(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if raw using \code{is.raw(x)} } \section{Functions}{ \itemize{ \item \code{vld_raw()}: Validate Raw }} \examples{ # chk_raw chk_raw(as.raw(1)) try(chk_raw(1)) # vld_raw vld_raw(as.raw(1)) vld_raw(raw(0)) vld_raw(1) vld_raw(TRUE) } \seealso{ \code{\link[=is.raw]{is.raw()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()} } \concept{data_type_checkers} chk/man/chk_unique.Rd0000644000176200001440000000265414743771477014250 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-unique.R \name{chk_unique} \alias{chk_unique} \alias{vld_unique} \title{Check Unique} \usage{ chk_unique(x, incomparables = FALSE, x_name = NULL) vld_unique(x, incomparables = FALSE) } \arguments{ \item{x}{The object to check.} \item{incomparables}{A vector of values that cannot be compared. FALSE means that all values can be compared.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if unique using \code{!anyDuplicated(x, incomparables = incomparables)} } \section{Functions}{ \itemize{ \item \code{vld_unique()}: Validate Unique }} \examples{ # chk_unique chk_unique(c(NA, 2)) try(chk_unique(c(NA, NA, 2))) chk_unique(c(NA, NA, 2), incomparables = NA) # vld_unique vld_unique(NULL) vld_unique(numeric(0)) vld_unique(c(NA, 2)) vld_unique(c(NA, NA, 2)) vld_unique(c(NA, NA, 2), incomparables = NA) } \seealso{ \code{\link[=anyDuplicated]{anyDuplicated()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other misc_checkers: \code{\link{chk_join}()}, \code{\link{chk_not_any_na}()}, \code{\link{chk_not_empty}()} } \concept{misc_checkers} chk/man/check_dirs.Rd0000644000176200001440000000161714744734003014172 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-dirs.R \name{check_dirs} \alias{check_dirs} \title{Check Directories Exist} \usage{ check_dirs(x, exists = TRUE, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{exists}{A flag specifying whether the files/directories must (or must not) exist.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks if all directories exist (or if exists = FALSE do not exist as directories or files). } \examples{ check_dirs(tempdir()) try(check_dirs(tempdir(), exists = FALSE)) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_false.Rd0000644000176200001440000000276014743771477014032 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-false.R \name{chk_false} \alias{chk_false} \alias{vld_false} \title{Check FALSE} \usage{ chk_false(x, x_name = NULL) vld_false(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Check if FALSE using \code{is.logical(x) && length(x) == 1L && !anyNA(x) && !x} } \section{Functions}{ \itemize{ \item \code{vld_false()}: Validate FALSE }} \examples{ # chk_false chk_false(FALSE) try(chk_false(0)) # vld_false vld_false(TRUE) vld_false(FALSE) vld_false(NA) vld_false(0) vld_false(c(FALSE, FALSE)) } \seealso{ \code{\link[=is.logical]{is.logical()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other logical_checkers: \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_logical}()}, \code{\link{chk_true}()} Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} } \concept{logical_checkers} \concept{scalar_checkers} chk/man/check_values.Rd0000644000176200001440000000312114744734003014520 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-values.R \name{check_values} \alias{check_values} \title{Check Values and Class} \usage{ check_values(x, values, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{values}{An atomic vector specifying the S3 class and possible values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks values and S3 class of an atomic object. } \details{ To check the class simply pass a vector of the desired class. To check that x does not include missing values pass a single non-missing value (of the correct class). To allow it to include missing values include a missing value. To check that it only includes missing values only pass a missing value (of the correct class). To check the range of the values in x pass two non-missing values (as well as the missing value if required). To check that x only includes specific values pass three or more non-missing values. In the case of a factor ensure values has two levels to check that the levels of x are an ordered superset of the levels of value and three or more levels to check that they are identical. } \examples{ check_values(1, numeric(0)) check_values(1, 2) try(check_values(1, 1L)) try(check_values(NA_real_, 1)) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_names}()} } \concept{check} chk/man/chk_dbl.Rd0000644000176200001440000000244214436206156013460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-dbl.R \name{chk_dbl} \alias{chk_dbl} \alias{vld_dbl} \title{Check Double Scalar} \usage{ chk_dbl(x, x_name = NULL) vld_dbl(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if double scalar using \code{is.double(x) && length(x) == 1L} \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \section{Functions}{ \itemize{ \item \code{vld_dbl()}: Validate Double \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} }} \examples{ # chk_dbl chk_dbl(1) try(chk_dbl(1L)) # vld_dbl vld_dbl(1) vld_dbl(double(0)) vld_dbl(NA_real_) vld_dbl(c(1, 1)) vld_dbl(1L) } \seealso{ Other deprecated: \code{\link{chk_chr}()}, \code{\link{chk_deprecated}}, \code{\link{chk_wnum}()} } \concept{deprecated} chk/man/chk_numeric.Rd0000644000176200001440000000275114743771477014402 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-numeric.R \name{chk_numeric} \alias{chk_numeric} \alias{vld_numeric} \title{Check Numeric} \usage{ chk_numeric(x, x_name = NULL) vld_numeric(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if numeric using \code{is.numeric(x)} \strong{Pass}: \code{1}, \code{1:2}, \code{NA_real_}, \code{integer(0)}, \code{matrix(1:3)}. \strong{Fail}: \code{TRUE}, \code{"1"}, \code{NA}, \code{NULL}. } \section{Functions}{ \itemize{ \item \code{vld_numeric()}: Validate Numeric }} \examples{ # chk_numeric chk_numeric(1) try(chk_numeric("1")) # vld_numeric vld_numeric(1) vld_numeric(1:2) vld_numeric(NA_real_) vld_numeric(integer(0)) vld_numeric("1") vld_numeric(TRUE) } \seealso{ \code{\link[=is.numeric]{is.numeric()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_join.Rd0000644000176200001440000000277014743771477013700 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-join.R \name{chk_join} \alias{chk_join} \alias{vld_join} \title{Check Join} \usage{ chk_join(x, y, by, x_name = NULL) vld_join(x, y, by) } \arguments{ \item{x}{The object to check.} \item{y}{A data.frame with columns in by.} \item{by}{A character vector specifying the column names to join x and y on. If named the names are the corresponding columns in x.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all rows in x match at least one in y. } \section{Functions}{ \itemize{ \item \code{vld_join()}: Validate Join }} \examples{ # chk_join chk_join(data.frame(z = 1), data.frame(z = 1:2), by = "z") try(chk_join(data.frame(z = 1), data.frame(z = 2), by = "z")) # vld_join vld_join(data.frame(z = 1), data.frame(z = 1:2), by = "z") vld_join(data.frame(z = 1), data.frame(z = 2), by = "z") vld_join(data.frame(z = 1), data.frame(a = 1:2), by = c(z = "a")) vld_join(data.frame(z = 1), data.frame(a = 2), by = c(z = "a")) } \seealso{ For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other misc_checkers: \code{\link{chk_not_any_na}()}, \code{\link{chk_not_empty}()}, \code{\link{chk_unique}()} } \concept{misc_checkers} chk/man/chk_superset.Rd0000644000176200001440000000261414743771477014610 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-superset.R \name{chk_superset} \alias{chk_superset} \alias{vld_superset} \title{Check Superset} \usage{ chk_superset(x, values, x_name = NULL) vld_superset(x, values) } \arguments{ \item{x}{The object to check.} \item{values}{A vector of the permitted values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if includes all values using \code{all(values \%in\% x)} Pay attention to the order of the arguments \code{value} and \code{x} in this function compared to \code{\link[=chk_subset]{chk_subset()}} } \section{Functions}{ \itemize{ \item \code{vld_superset()}: Validates Superset }} \examples{ # chk_superset chk_superset(1:3, 1) try(chk_superset(1:3, 4)) # vld_superset vld_superset(1:3, 1) vld_superset(1:3, 4) vld_superset(integer(0), integer(0)) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other set_checkers: \code{\link{chk_not_subset}()}, \code{\link{chk_orderset}()}, \code{\link{vld_not_subset}()}, \code{\link{vld_orderset}()} } \concept{set_checkers} chk/man/chk-package.Rd0000644000176200001440000000260114743771477014243 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-package.R \docType{package} \name{chk-package} \alias{chk} \alias{chk-package} \title{chk: Check User-Supplied Function Arguments} \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} For developers to check user-supplied function arguments. It is designed to be simple, fast and customizable. Error messages follow the tidyverse style guide. } \seealso{ Useful links: \itemize{ \item \url{https://github.com/poissonconsulting/chk} \item \url{https://poissonconsulting.github.io/chk/} \item Report bugs at \url{https://github.com/poissonconsulting/chk/issues/} } } \author{ \strong{Maintainer}: Joe Thorley \email{joe@poissonconsulting.ca} (\href{https://orcid.org/0000-0002-7683-4592}{ORCID}) Authors: \itemize{ \item Kirill Müller (\href{https://orcid.org/0000-0002-1416-3412}{ORCID}) \item Ayla Pearson (\href{https://orcid.org/0000-0001-7388-1222}{ORCID}) } Other contributors: \itemize{ \item Florencia D'Andrea [contributor] \item Nadine Hussein \email{nadine@poissonconsulting.ca} (\href{https://orcid.org/0000-0003-4470-8361}{ORCID}) [contributor] \item Evan Amies-Galonski \email{evan@poissonconsulting.ca} (\href{https://orcid.org/0000-0003-1096-2089}{ORCID}) [contributor] \item Poisson Consulting [copyright holder, funder] } } \keyword{internal} chk/man/chk_not_subset.Rd0000644000176200001440000000214714743771477015124 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-subset.R \name{chk_not_subset} \alias{chk_not_subset} \title{Check Not Subset} \usage{ chk_not_subset(x, values, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{values}{A vector of the permitted values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if not all values in values using \code{!any(x \%in\% values) || !length(x)} } \examples{ # chk_not_subset chk_not_subset(11, 1:10) try(chk_not_subset(1, 1:10)) } \seealso{ \code{\link[=any]{any()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other set_checkers: \code{\link{chk_orderset}()}, \code{\link{chk_superset}()}, \code{\link{vld_not_subset}()}, \code{\link{vld_orderset}()} } \concept{set_checkers} chk/man/chk_named.Rd0000644000176200001440000000221014743771477014012 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-named.R \name{chk_named} \alias{chk_named} \alias{vld_named} \title{Check Named} \usage{ chk_named(x, x_name = NULL) vld_named(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is named using \code{!is.null(names(x))} } \section{Functions}{ \itemize{ \item \code{vld_named()}: Validate Named }} \examples{ # chk_named chk_named(c(x = 1)) try(chk_named(list(1))) # vld_named vld_named(c(x = 1)) vld_named(list(x = 1)) vld_named(c(x = 1)[-1]) vld_named(list(x = 1)[-1]) vld_named(1) vld_named(list(1)) } \seealso{ \code{\link[=names]{names()}} \code{\link[=is.null]{is.null()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other name_checkers: \code{\link{chk_valid_name}()} } \concept{name_checkers} chk/man/chk_double.Rd0000644000176200001440000000254514743771477014213 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-double.R \name{chk_double} \alias{chk_double} \alias{vld_double} \title{Check Double} \usage{ chk_double(x, x_name = NULL) vld_double(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if double using \code{is.double(x)} } \section{Functions}{ \itemize{ \item \code{vld_double()}: Validate Double }} \examples{ # chk_double chk_double(1) try(chk_double(1L)) # vld_double vld_double(1) vld_double(matrix(c(1, 2, 3, 4), nrow = 2L)) vld_double(double(0)) vld_double(numeric(0)) vld_double(NA_real_) vld_double(1L) vld_double(TRUE) } \seealso{ \code{\link[=is.double]{is.double()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_flag.Rd0000644000176200001440000000334014743771477013644 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-flag.R \name{chk_flag} \alias{chk_flag} \alias{vld_flag} \title{Check Flag} \usage{ chk_flag(x, x_name = NULL) vld_flag(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing logical scalar using \code{is.logical(x) && length(x) == 1L && !anyNA(x)} \strong{Pass}: \code{TRUE}, \code{FALSE}. \strong{Fail}: \code{logical(0)}, \code{c(TRUE, TRUE)}, \code{"TRUE"}, \code{1}, \code{NA}. Do not confuse this function with \code{\link[=chk_lgl]{chk_lgl()}}, which also checks for logical scalars of \code{length(x) == 1} but can include \code{NA}s. } \section{Functions}{ \itemize{ \item \code{vld_flag()}: Validate Flag }} \examples{ # chk_flag chk_flag(TRUE) try(vld_flag(1)) # vld_flag vld_flag(TRUE) vld_flag(1) } \seealso{ \code{\link[=is.logical]{is.logical()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other logical_checkers: \code{\link{chk_false}()}, \code{\link{chk_lgl}()}, \code{\link{chk_logical}()}, \code{\link{chk_true}()} Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} } \concept{logical_checkers} \concept{scalar_checkers} chk/man/chk_compatible_lengths.Rd0000644000176200001440000000367414743771477016610 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-compatible-lengths.R \name{chk_compatible_lengths} \alias{chk_compatible_lengths} \alias{vld_compatible_lengths} \title{Check Compatible Lengths} \usage{ chk_compatible_lengths(..., x_name = NULL) vld_compatible_lengths(...) } \arguments{ \item{...}{The objects to check for compatible lengths.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails. } \description{ Checks objects (including vectors) have lengths that could be 'strictly recycled'. That is to say they must all be either zero length or the same length with some of length 1. } \details{ This function helps to check vectors could be 'strictly recycled.' For example the function will error if you had a vector of length 2 and length 4, even though the vector of length 2 could be 'loosely recycled' to match up to the vector of length 4 when combined. The intent of the function is to check that only strict recycling is occurring. } \section{Functions}{ \itemize{ \item \code{vld_compatible_lengths()}: Validate Compatible Lengths }} \examples{ # chk_compatible_lengths a <- integer(0) b <- numeric(0) chk_compatible_lengths(a, b) a <- 1 b <- 2 chk_compatible_lengths(a, b) a <- 1:3 b <- 1:3 chk_compatible_lengths(a, b) b <- 1 chk_compatible_lengths(a, b) b <- 1:2 try(chk_compatible_lengths(a, b)) b <- 1:6 try(chk_compatible_lengths(a, b)) # vld_compatible_lengths a <- integer(0) b <- numeric(0) vld_compatible_lengths(a, b) a <- 1 b <- 2 vld_compatible_lengths(a, b) a <- 1:3 b <- 1:3 vld_compatible_lengths(a, b) b <- 1 vld_compatible_lengths(a, b) b <- 1:2 vld_compatible_lengths(a, b) b <- 1:6 vld_compatible_lengths(a, b) } \seealso{ For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other length_checkers: \code{\link{chk_length}()} } \concept{length_checkers} chk/man/chk_range.Rd0000644000176200001440000000305714743771477014034 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-range.R \name{chk_range} \alias{chk_range} \alias{vld_range} \title{Checks range of non-missing values} \usage{ chk_range(x, range = c(0, 1), inclusive = TRUE, x_name = NULL) vld_range(x, range = c(0, 1), inclusive = TRUE) } \arguments{ \item{x}{The object to check.} \item{range}{A non-missing sorted vector of length 2 of the lower and upper permitted values.} \item{inclusive}{A flag specifying whether the range is exclusive.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks all non-missing values fall within range using If inclusive \code{all(x[!is.na(x)] >= range[1] & x[!is.na(x)] <= range[2])} else \code{all(x[!is.na(x)] > range[1] & x[!is.na(x)] < range[2])} } \section{Functions}{ \itemize{ \item \code{vld_range()}: Validate Range }} \examples{ # chk_range chk_range(0) try(chk_range(-0.1)) # vld_range vld_range(numeric(0)) vld_range(0) vld_range(-0.1) vld_range(c(0.1, 0.2, NA)) vld_range(c(0.1, 0.2, NA), range = c(0, 1)) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other range_checkers: \code{\link{chk_gt}()}, \code{\link{chk_gte}()}, \code{\link{chk_lt}()}, \code{\link{chk_lte}()} } \concept{range_checkers} chk/man/chk_data.Rd0000644000176200001440000000240114743771477013641 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-data.R \name{chk_data} \alias{chk_data} \alias{vld_data} \title{Check Data} \usage{ chk_data(x, x_name = NULL) vld_data(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks data.frame using \code{inherits(x, "data.frame")} Note that there is a similar function, \code{\link[=check_data]{check_data()}}, which checks the column names, values, number of rows, and keys of a data.frame. } \section{Functions}{ \itemize{ \item \code{vld_data()}: Validate Data }} \examples{ # chk_data chk_data(data.frame(x = 1)) try(chk_data(1)) # vld_data vld_data(data.frame()) vld_data(data.frame(x = 1)) vld_data(c(x = 1)) } \seealso{ \code{\link[=inherits]{inherits()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other id_checkers: \code{\link{chk_is}()}, \code{\link{chk_s3_class}()}, \code{\link{chk_s4_class}()} } \concept{id_checkers} chk/man/chk_gte.Rd0000644000176200001440000000242414743771477013514 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-gte.R \name{chk_gte} \alias{chk_gte} \alias{vld_gte} \title{Check Greater Than or Equal To} \usage{ chk_gte(x, value = 0, x_name = NULL) vld_gte(x, value = 0) } \arguments{ \item{x}{The object to check.} \item{value}{A non-missing scalar of a value.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all non-missing values are greater than or equal to y using \code{all(x[!is.na(x)] >= value)} } \section{Functions}{ \itemize{ \item \code{vld_gte()}: Validate Greater Than or Equal To }} \examples{ # chk_gte chk_gte(0) try(chk_gte(-0.1)) # vld_gte vld_gte(numeric(0)) vld_gte(0) vld_gte(-0.1) vld_gte(c(0.1, 0.2, NA)) vld_gte(c(0.1, 0.2, NA), value = 1) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other range_checkers: \code{\link{chk_gt}()}, \code{\link{chk_lt}()}, \code{\link{chk_lte}()}, \code{\link{chk_range}()} } \concept{range_checkers} chk/man/chk_logical.Rd0000644000176200001440000000323014743771477014343 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-logical.R \name{chk_logical} \alias{chk_logical} \alias{vld_logical} \title{Check Logical} \usage{ chk_logical(x, x_name = NULL) vld_logical(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if logical using \code{is.logical(x)} If you want to check if it is a scalar, meaning that in addition to being of logical type, it has \code{length(x) == 1}, you should use \code{\link[=chk_lgl]{chk_lgl()}} } \section{Functions}{ \itemize{ \item \code{vld_logical()}: Validate Logical }} \examples{ # chk_logical chk_logical(TRUE) try(chk_logical(1)) # vld_logical vld_logical(TRUE) vld_logical(matrix(TRUE)) vld_logical(logical(0)) vld_logical(NA) vld_logical(1) vld_logical("TRUE") } \seealso{ \code{\link[=is.logical]{is.logical()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other logical_checkers: \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_true}()} Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} \concept{logical_checkers} chk/man/chk_orderset.Rd0000644000176200001440000000225614743771477014567 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-orderset.R \name{chk_orderset} \alias{chk_orderset} \title{Check Set Ordered} \usage{ chk_orderset(x, values, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{values}{A vector of the permitted values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if the first occurrence of each shared element in x is equivalent to the first occurrence of each shared element in values using \code{vld_equivalent(unique(x[x \%in\% values]), values[values \%in\% x])}. } \examples{ # chk_orderset chk_orderset(1:2, 1:2) try(chk_orderset(2:1, 1:2)) } \seealso{ \code{\link[=vld_equivalent]{vld_equivalent()}} \code{\link[=unique]{unique()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other set_checkers: \code{\link{chk_not_subset}()}, \code{\link{chk_superset}()}, \code{\link{vld_not_subset}()}, \code{\link{vld_orderset}()} } \concept{set_checkers} chk/man/chk_wnum.Rd0000644000176200001440000000260614436206156013707 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-wnum.R \name{chk_wnum} \alias{chk_wnum} \alias{vld_wnum} \title{Check Whole Numeric Scalar} \usage{ chk_wnum(x, x_name = NULL) vld_wnum(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if whole numeric scalar using \code{is.numeric(x) && length(x) == 1L && (is.integer(x) || vld_true(all.equal(x, trunc(x))))} \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \section{Functions}{ \itemize{ \item \code{vld_wnum()}: Validate Whole Numeric Scalar \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} }} \examples{ # chk_wnum chk_wnum(1) try(chk_wnum(1.1)) # vld_wnum vld_wnum(1) vld_wnum(double(0)) vld_wnum(NA_real_) vld_wnum(c(1, 1)) vld_wnum(1L) } \seealso{ Other deprecated: \code{\link{chk_chr}()}, \code{\link{chk_dbl}()}, \code{\link{chk_deprecated}} } \concept{deprecated} chk/man/check_names.Rd0000644000176200001440000000215014744734003014325 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-names.R \name{check_names} \alias{check_names} \title{Check Names} \usage{ check_names( x, names = character(0), exclusive = FALSE, order = FALSE, x_name = NULL ) } \arguments{ \item{x}{The object to check.} \item{names}{A character vector of the required names.} \item{exclusive}{A flag specifying whether x must only contain the required names.} \item{order}{A flag specifying whether the order of the required names in x must match the order in names.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks the names of an object. } \examples{ x <- c(x = 1, y = 2) check_names(x, c("y", "x")) try(check_names(x, c("y", "x"), order = TRUE)) try(check_names(x, "x", exclusive = TRUE)) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_matrix.Rd0000644000176200001440000000220014743771477014231 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-matrix.R \name{chk_matrix} \alias{chk_matrix} \alias{vld_matrix} \title{Check Matrix} \usage{ chk_matrix(x, x_name = NULL) vld_matrix(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is a matrix using \code{is.matrix(x)} } \section{Functions}{ \itemize{ \item \code{vld_matrix()}: Validate Matrix }} \examples{ # chk_matrix chk_matrix(matrix(1)) try(chk_matrix(array(1))) # vld_matrix vld_matrix(1) vld_matrix(matrix(1)) } \seealso{ \code{\link[=is.matrix]{is.matrix()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_structure_checkers: \code{\link{chk_array}()}, \code{\link{chk_atomic}()}, \code{\link{chk_list}()}, \code{\link{chk_vector}()} } \concept{data_structure_checkers} chk/man/chk_length.Rd0000644000176200001440000000250114744734003014173 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-length.R \name{chk_length} \alias{chk_length} \alias{vld_length} \title{Check Length} \usage{ chk_length(x, length = 1L, upper = length, x_name = NULL) vld_length(x, length = 1L, upper = length) } \arguments{ \item{x}{The object to check.} \item{length}{A count of the length.} \item{upper}{A count of the max length.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks length is a particular value or range using \code{length(x) >= length && length(x) <= upper} } \section{Functions}{ \itemize{ \item \code{vld_length()}: Validate Length }} \examples{ # chk_length chk_length("text") try(vld_length("text", length = 2)) # vld_length vld_length(2:1, 2) vld_length(2:1, 1) } \seealso{ \code{\link[=length]{length()}}, \code{\link[=check_length]{check_length()}}, \code{\link[=check_dim]{check_dim()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other length_checkers: \code{\link{chk_compatible_lengths}()} } \concept{length_checkers} chk/man/check_length.Rd0000644000176200001440000000156014744734003014507 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-length.R \name{check_length} \alias{check_length} \title{Check Length} \usage{ check_length(x, values = numeric(0), x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{values}{A flag or a whole numeric vector of the value, value range or possible values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks length of an object. } \examples{ check_length(1) try(check_length(1, values = FALSE)) try(check_length(1, values = c(10, 2))) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_lte.Rd0000644000176200001440000000241614743771477013522 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-lte.R \name{chk_lte} \alias{chk_lte} \alias{vld_lte} \title{Check Less Than or Equal To} \usage{ chk_lte(x, value = 0, x_name = NULL) vld_lte(x, value = 0) } \arguments{ \item{x}{The object to check.} \item{value}{A non-missing scalar of a value.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all non-missing values are less than or equal to y using \code{all(x[!is.na(x)] <= value)} } \section{Functions}{ \itemize{ \item \code{vld_lte()}: Validate Less Than or Equal To }} \examples{ # chk_lte chk_lte(0) try(chk_lte(0.1)) # vld_lte vld_lte(numeric(0)) vld_lte(0) vld_lte(0.1) vld_lte(c(-0.1, -0.2, NA)) vld_lte(c(-0.1, -0.2, NA), value = -1) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other range_checkers: \code{\link{chk_gt}()}, \code{\link{chk_gte}()}, \code{\link{chk_lt}()}, \code{\link{chk_range}()} } \concept{range_checkers} chk/man/chk_chr.Rd0000644000176200001440000000250714436206156013475 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-chr.R \name{chk_chr} \alias{chk_chr} \alias{vld_chr} \title{Check Character Scalar} \usage{ chk_chr(x, x_name = NULL) vld_chr(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if character scalar using \code{is.character(x) && length(x) == 1L} \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \section{Functions}{ \itemize{ \item \code{vld_chr()}: Validate Character Scalar \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} }} \examples{ chk_chr("a") try(chk_chr(1)) # vld_chr vld_chr("") vld_chr("a") vld_chr(NA_character_) vld_chr(c("a", "b")) vld_chr(1) } \seealso{ Other deprecated: \code{\link{chk_dbl}()}, \code{\link{chk_deprecated}}, \code{\link{chk_wnum}()} } \concept{chk_character} \concept{deprecated} chk/man/chk_lgl.Rd0000644000176200001440000000315514743771477013515 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-lgl.R \name{chk_lgl} \alias{chk_lgl} \alias{vld_lgl} \title{Check Logical Scalar} \usage{ chk_lgl(x, x_name = NULL) vld_lgl(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if logical scalar using \code{is.logical(x) && length(x) == 1L} If you only want to check the data type (not whether \code{length(x) == 1}), you should use the \code{\link[=chk_logical]{chk_logical()}} function. } \section{Functions}{ \itemize{ \item \code{vld_lgl()}: Validate Logical Scalar }} \examples{ # chk_lgl chk_lgl(NA) try(chk_lgl(1)) # vld_lgl vld_lgl(TRUE) vld_lgl(FALSE) vld_lgl(NA) vld_lgl(1) vld_lgl(c(TRUE, TRUE)) } \seealso{ \code{\link[=is.logical]{is.logical()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other logical_checkers: \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_logical}()}, \code{\link{chk_true}()} Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} } \concept{logical_checkers} \concept{scalar_checkers} chk/man/chk_s3_class.Rd0000644000176200001440000000246314743771477014452 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-s3-class.R \name{chk_s3_class} \alias{chk_s3_class} \alias{vld_s3_class} \title{Check Type} \usage{ chk_s3_class(x, class, x_name = NULL) vld_s3_class(x, class) } \arguments{ \item{x}{The object to check.} \item{class}{A string specifying the class.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks inherits from S3 class using \code{!isS4(x) && inherits(x, class)} } \section{Functions}{ \itemize{ \item \code{vld_s3_class()}: Validate Inherits from S3 Class }} \examples{ # chk_s3_class chk_s3_class(1, "numeric") try(chk_s3_class(getClass("MethodDefinition"), "classRepresentation")) # vld_s3_class vld_s3_class(numeric(0), "numeric") vld_s3_class(getClass("MethodDefinition"), "classRepresentation") } \seealso{ \code{\link[=inherits]{inherits()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other id_checkers: \code{\link{chk_data}()}, \code{\link{chk_is}()}, \code{\link{chk_s4_class}()} } \concept{id_checkers} chk/man/chk_complex_number.Rd0000644000176200001440000000250214743771477015751 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-complex-number.R \name{chk_complex_number} \alias{chk_complex_number} \alias{vld_complex_number} \title{Check Complex Number} \usage{ chk_complex_number(x, x_name = NULL) vld_complex_number(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing complex scalar using \code{is.complex(x) && length(x) == 1L && !anyNA(x)} } \section{Functions}{ \itemize{ \item \code{vld_complex_number()}: Validate Complex Number }} \examples{ # chk_complex_number chk_complex_number(as.complex(1.1)) try(chk_complex_number(1.1)) # vld_complex_number vld_complex_number(as.complex(2)) } \seealso{ \code{\link[=is.integer]{is.integer()}} \code{\link[=vld_true]{vld_true()}} \code{\link[=vld_number]{vld_number()}} For more details about the use of this function, please read the article \href{https://poissonconsulting.github.io/chk/articles/chk-families.html}{chk families}. Other scalar_checker: \code{\link{chk_whole_number}()} } \concept{scalar_checker} chk/man/aaa.Rd0000644000176200001440000000070314436206156012612 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/aaa.R \name{aaa} \alias{aaa} \title{Workaround: Avoid backtraces in examples} \description{ This example will run first and set the option for the process that builds the example. (By default, pkgdown builds in a separate process.) This also produces a help page that isn't linked from anywhere. } \examples{ options(rlang_backtrace_on_error = "none") } \keyword{internal} chk/man/chk_deprecated.Rd0000644000176200001440000000747714436206156015034 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/deprecated.R \name{chk_deprecated} \alias{chk_deprecated} \alias{chk_dirs} \alias{chk_files} \alias{chk_has} \alias{chk_in} \alias{chk_no_missing} \alias{vld_no_missing} \alias{chk_off} \alias{chk_on} \alias{is_chk_on} \alias{chk_proportion} \alias{deparse_backtick} \title{Deprecated functions} \usage{ chk_dirs(x) chk_files(x) chk_has(x, values, x_name = NULL) chk_in(x, values, x_name = NULL) chk_no_missing(x, x_name = NULL) vld_no_missing(x) chk_off() chk_on() is_chk_on() chk_proportion(x, x_name = NULL) deparse_backtick(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \description{ Deprecated \code{chk_()} functions. } \section{Functions}{ \itemize{ \item \code{chk_dirs()}: Check Directories Exist \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace with \verb{[chk_all](x, [chk_dir])} \item \code{chk_files()}: Check Files Exist \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace with \verb{[chk_all](x, [chk_file])} \item \code{chk_has()}: Check Has \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace by \code{\link[=chk_superset]{chk_superset()}} \item \code{chk_in()}: Check In \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace by \code{\link[=chk_subset]{chk_subset()}} \item \code{chk_no_missing()}: Check No Missing Values \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace with \code{\link[=chk_not_any_na]{chk_not_any_na()}} \item \code{vld_no_missing()}: Validate No Missing Values \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace with \code{\link[=vld_not_any_na]{vld_not_any_na()}} \item \code{chk_off()}: Turns checking off \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This approach is no longer recommended \item \code{chk_on()}: Turns checking on \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This approach is no longer recommended \item \code{is_chk_on()}: Tests checking on \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} This approach is no longer recommended \item \code{chk_proportion()}: Check Proportion \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace by \verb{[chk_number](x); [chk_range](x)} \item \code{deparse_backtick()}: Deparse Backtick \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Replace with \code{\link[=deparse_backtick_chk]{deparse_backtick_chk()}} }} \seealso{ Other deprecated: \code{\link{chk_chr}()}, \code{\link{chk_dbl}()}, \code{\link{chk_wnum}()} } \concept{deprecated} \keyword{internal} chk/man/p.Rd0000644000176200001440000000165014712265101012321 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/p.R \name{p} \alias{p} \alias{p0} \title{Concatenate Strings} \usage{ p(..., sep = " ", collapse = NULL) p0(..., collapse = NULL) } \arguments{ \item{...}{one or more \R objects, to be converted to character vectors.} \item{sep}{a character string to separate the terms. Not \code{\link[base]{NA_character_}}.} \item{collapse}{an optional character string to separate the results. Not \code{\link[base]{NA_character_}}. When \code{collapse} is a string, the result is always a string (\code{\link[base]{character}} of length 1).} } \value{ A character vector. } \description{ A wrapper on \code{\link[base:paste]{base::paste()}}. } \section{Functions}{ \itemize{ \item \code{p0()}: A wrapper on \code{\link[base:paste]{base::paste0()}} }} \examples{ p("a", "b") p(c("a", "b"), collapse = " ") p0("a", "b") p0(c("a", "b"), collapse = "") } chk/man/chk_vector.Rd0000644000176200001440000000264214743771477014241 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-vector.R \name{chk_vector} \alias{chk_vector} \alias{vld_vector} \title{Check Vector} \usage{ chk_vector(x, x_name = NULL) vld_vector(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is a vector using \code{(is.atomic(x) && !is.matrix(x) && !is.array(x)) || is.list(x)} } \details{ \code{is.vector(x)} is not reliable because it returns TRUE only if the object is a vector with no attributes apart from names. } \section{Functions}{ \itemize{ \item \code{vld_vector()}: Validate Vector }} \examples{ # chk_vector chk_vector(1) chk_vector(list()) try(chk_vector(matrix(1))) # vld_vector vld_vector(1) } \seealso{ \code{\link[=is.atomic]{is.atomic()}}, \code{\link[=is.matrix]{is.matrix()}}, \code{\link[=is.array]{is.array()}}, \code{\link[=is.list]{is.list()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_structure_checkers: \code{\link{chk_array}()}, \code{\link{chk_atomic}()}, \code{\link{chk_list}()}, \code{\link{chk_matrix}()} } \concept{data_structure_checkers} chk/man/chk_dir.Rd0000644000176200001440000000216714743771477013517 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-dir.R \name{chk_dir} \alias{chk_dir} \alias{vld_dir} \title{Check Directory Exists} \usage{ chk_dir(x, x_name = NULL) vld_dir(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if directory exists using \code{vld_string(x) && dir.exists(x)} } \section{Functions}{ \itemize{ \item \code{vld_dir()}: Validate Directory Exists }} \examples{ # chk_dir chk_dir(tempdir()) try(chk_dir(tempfile())) # vld_dir vld_dir(1) vld_dir(tempdir()) vld_dir(tempfile()) } \seealso{ \code{\link[=vld_string]{vld_string()}} \code{\link[=dir.exists]{dir.exists()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other file_checkers: \code{\link{chk_ext}()}, \code{\link{chk_file}()} } \concept{file_checkers} chk/man/chk_character_or_factor.Rd0000644000176200001440000000341314743771477016726 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-character-or-factor.R \name{chk_character_or_factor} \alias{chk_character_or_factor} \alias{vld_character_or_factor} \title{Check Character or Factor} \usage{ chk_character_or_factor(x, x_name = NULL) vld_character_or_factor(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if character or factor using \code{is.character(x) || is.factor(x)} } \section{Functions}{ \itemize{ \item \code{vld_character_or_factor()}: Validate Character or Factor }} \examples{ # chk_character_or_factor chk_character_or_factor("1") chk_character_or_factor(factor("1")) try(chk_character(1)) # vld_character_or_factor vld_character_or_factor("1") vld_character_or_factor(matrix("a")) vld_character_or_factor(character(0)) vld_character_or_factor(NA_character_) vld_character_or_factor(1) vld_character_or_factor(TRUE) vld_character_or_factor(factor("text")) } \seealso{ \code{\link[=is.character]{is.character()}} \code{\link[=is.factor]{is.factor()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} Other factor_checkers: \code{\link{chk_factor}()} } \concept{data_type_checkers} \concept{factor_checkers} chk/man/chk_date_time.Rd0000644000176200001440000000414214743771477014667 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-datetime.R \name{chk_date_time} \alias{chk_date_time} \alias{chk_datetime} \alias{vld_date_time} \alias{vld_datetime} \title{Check Date Time} \usage{ chk_date_time(x, x_name = NULL) chk_datetime(x, x_name = NULL) vld_date_time(x) vld_datetime(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing POSIXct scalar using \code{inherits(x, "POSIXct") && length(x) == 1L && !anyNA(x)} } \section{Functions}{ \itemize{ \item \code{chk_datetime()}: Check Date Time (Deprecated) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \item \code{vld_date_time()}: Validate Date Time \item \code{vld_datetime()}: Validate Date Time (Deprecated) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} }} \examples{ # chk_date_time chk_date_time(as.POSIXct("2001-01-02")) try(chk_date_time(1)) # vld_date_time vld_date_time(as.POSIXct("2001-01-02")) vld_date_time(Sys.time()) vld_date_time(1) vld_date_time("2001-01-02") vld_date_time(c(Sys.time(), Sys.time())) } \seealso{ \code{\link[=inherits]{inherits()}}, \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} Other datetime_checkers: \code{\link{chk_date}()} } \concept{datetime_checkers} \concept{scalar_checkers} chk/man/check_key.Rd0000644000176200001440000000167314744734003014023 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-key.R \name{check_key} \alias{check_key} \title{Check Key} \usage{ check_key(x, key = character(0), na_distinct = FALSE, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{key}{A character vector of the columns that represent a unique key.} \item{na_distinct}{A flag specifying whether missing values should be considered distinct.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks if columns have unique rows. } \examples{ x <- data.frame(x = c(1, 2), y = c(1, 1)) check_key(x) try(check_key(x, "y")) } \seealso{ Other check: \code{\link{check_data}()}, \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_length}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_not_empty.Rd0000644000176200001440000000263114743771477014753 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-empty.R \name{chk_not_empty} \alias{chk_not_empty} \alias{vld_not_empty} \title{Check Not Empty} \usage{ chk_not_empty(x, x_name = NULL) vld_not_empty(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if not empty using \code{length(x) != 0L} \strong{Pass}: \code{1}, \code{1:2}, \code{NA}, \code{matrix(1:3)}, \code{list(1)}, \code{data.frame(x = 1)}. \strong{Fail}: \code{NULL}, \code{logical(0)}, \code{list()}, \code{data.frame()}. } \section{Functions}{ \itemize{ \item \code{vld_not_empty()}: Validate Not Empty }} \examples{ # chk_not_empty chk_not_empty(1) try(chk_not_empty(numeric(0))) # vld_not_empty vld_not_empty(1) vld_not_empty(matrix(1:3)) vld_not_empty(character(0)) vld_not_empty(list(1)) vld_not_empty(NULL) vld_not_empty(list()) } \seealso{ \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other misc_checkers: \code{\link{chk_join}()}, \code{\link{chk_not_any_na}()}, \code{\link{chk_unique}()} } \concept{misc_checkers} chk/man/chk_function.Rd0000644000176200001440000000256714743771477014572 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-function.R \name{chk_function} \alias{chk_function} \alias{vld_function} \title{Check Function} \usage{ chk_function(x, formals = NULL, x_name = NULL) vld_function(x, formals = NULL) } \arguments{ \item{x}{The object to check.} \item{formals}{A count of the number of formal arguments.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is a function using \code{is.function(x) && (is.null(formals) || length(formals(x)) == formals)} } \section{Functions}{ \itemize{ \item \code{vld_function()}: Validate Function }} \examples{ # chk_function chk_function(mean) try(chk_function(1)) # vld_function vld_function(mean) vld_function(function(x) x) vld_function(1) vld_function(list(1)) } \seealso{ \code{\link[=is.function]{is.function()}} \code{\link[=formals]{formals()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other missing_checkers: \code{\link{chk_missing}()}, \code{\link{chk_not_missing}()} } \concept{ellpisis_checkers} \concept{function_checkers} \concept{missing_checkers} chk/man/chk_factor.Rd0000644000176200001440000000215214743771477014211 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-factor.R \name{chk_factor} \alias{chk_factor} \alias{vld_factor} \title{Check Factor} \usage{ chk_factor(x, x_name = NULL) vld_factor(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if factor using \code{is.factor(x)} } \section{Functions}{ \itemize{ \item \code{vld_factor()}: Validate Factor }} \examples{ # chk_factor chk_factor(factor("1")) try(chk_factor("1")) # vld_factor vld_factor(factor("1")) vld_factor(factor(0)) vld_factor("1") vld_factor(1L) } \seealso{ \code{\link[=is.factor]{is.factor()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other factor_checkers: \code{\link{chk_character_or_factor}()} } \concept{data-type_checkers} \concept{factor_checkers} chk/man/err.Rd0000644000176200001440000000416114436206156012662 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/err.R \name{err} \alias{err} \alias{wrn} \alias{msg} \title{Stop, Warning and Message Messages} \usage{ err( ..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL, call = rlang::caller_call(3) ) wrn(..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL) msg(..., n = NULL, tidy = TRUE, .subclass = NULL, class = NULL) } \arguments{ \item{...}{zero or more objects which can be coerced to character (and which are pasted together with no separator) or a single condition object.} \item{n}{The value of n for converting \code{sprintf}-like types.} \item{tidy}{A flag specifying whether capitalize the first character and add a missing period.} \item{.subclass}{A string of the class of the error message.} \item{class}{Subclass of the condition.} \item{call}{The execution environment of a currently running function, e.g. \code{call = caller_env()}. The corresponding function call is retrieved and mentioned in error messages as the source of the error. You only need to supply \code{call} when throwing a condition from a helper function which wouldn't be relevant to mention in the message. Can also be \code{NULL} or a \link[rlang:topic-defuse]{defused function call} to respectively not display any call or hard-code a code to display. For more information about error calls, see \ifelse{html}{\link[rlang:topic-error-call]{Including function calls in error messages}}{\link[rlang:topic-error-call]{Including function calls in error messages}}.} } \description{ The functions call \code{\link[=message_chk]{message_chk()}} to process the message and then \code{\link[rlang:abort]{rlang::abort()}}, \code{\link[rlang:abort]{rlang::warn()}} and \code{\link[rlang:abort]{rlang::inform()}}, respectively. } \details{ The user can set the subclass. } \section{Functions}{ \itemize{ \item \code{err()}: Error \item \code{wrn()}: Warning \item \code{msg()}: Message }} \examples{ # err try(err("there \%r \%n problem value\%s", n = 2)) # wrn wrn("there \%r \%n problem value\%s", n = 2) # msg msg("there \%r \%n problem value\%s", n = 2) } chk/man/chk_list.Rd0000644000176200001440000000220514743771477013705 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-list.R \name{chk_list} \alias{chk_list} \alias{vld_list} \title{Check List} \usage{ chk_list(x, x_name = NULL) vld_list(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is a list using \code{is.list(x)} } \section{Functions}{ \itemize{ \item \code{vld_list()}: Validate List }} \examples{ # chk_list chk_list(list()) try(chk_list(1)) # vld_list vld_list(list()) vld_list(list(x = 1)) vld_list(mtcars) vld_list(1) vld_list(NULL) } \seealso{ \code{\link[=is.list]{is.list()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_structure_checkers: \code{\link{chk_array}()}, \code{\link{chk_atomic}()}, \code{\link{chk_matrix}()}, \code{\link{chk_vector}()} } \concept{data_structure_checkers} chk/man/chk_valid_name.Rd0000644000176200001440000000222314743771477015031 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-valid-name.R \name{chk_valid_name} \alias{chk_valid_name} \alias{vld_valid_name} \title{Check Valid Name} \usage{ chk_valid_name(x, x_name = NULL) vld_valid_name(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if valid name using \code{identical(make.names(x[!is.na(x)]), as.character(x[!is.na(x)]))} } \section{Functions}{ \itemize{ \item \code{vld_valid_name()}: Validate Valid Name }} \examples{ # chk_valid_name chk_valid_name("text") try(chk_valid_name(".1")) # vld_valid_name vld_valid_name(".1") } \seealso{ \code{\link[=identical]{identical()}} \code{\link[=make.names]{make.names()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other name_checkers: \code{\link{chk_named}()} } \concept{name_checkers} chk/man/chk_not_null.Rd0000644000176200001440000000203614743771477014566 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-null.R \name{chk_not_null} \alias{chk_not_null} \alias{vld_not_null} \title{Check not NULL} \usage{ chk_not_null(x, x_name = NULL) vld_not_null(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if not NULL using \code{!is.null(x)} } \section{Functions}{ \itemize{ \item \code{vld_not_null()}: Validate Not NULL }} \examples{ # chk_not_null try(chk_not_null(NULL)) chk_not_null(1) # vld_not_null vld_not_null(1) vld_not_null(NULL) } \seealso{ \code{\link[=is.null]{is.null()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other null_checkers: \code{\link{chk_null}()} } \concept{null_checkers} chk/man/chk_setequal.Rd0000644000176200001440000000273614743771477014566 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-orderset.R, R/chk-setequal.R \name{vld_orderset} \alias{vld_orderset} \alias{chk_setequal} \alias{vld_setequal} \title{Check Set Equal} \usage{ vld_orderset(x, values) chk_setequal(x, values, x_name = NULL) vld_setequal(x, values) } \arguments{ \item{x}{The object to check.} \item{values}{A vector of the permitted values.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if equal set using \code{setequal(x, values)} } \section{Functions}{ \itemize{ \item \code{vld_orderset()}: Validate Set Ordered \item \code{vld_setequal()}: Validate Set Equal }} \examples{ # vld_orderset vld_orderset(1, 1) vld_orderset(1:2, 2:1) vld_orderset(1, 2:1) vld_orderset(1:2, 2) # chk_setequal chk_setequal(1:2, 2:1) try(chk_setequal(1, 1:2)) # vld_setequal vld_setequal(1, 1) vld_setequal(1:2, 2:1) vld_setequal(1, 2:1) vld_setequal(1:2, 2) } \seealso{ \code{\link[=setequal]{setequal()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other set_checkers: \code{\link{chk_not_subset}()}, \code{\link{chk_orderset}()}, \code{\link{chk_superset}()}, \code{\link{vld_not_subset}()} } \concept{set_checkers} chk/man/figures/0000755000176200001440000000000014654734236013254 5ustar liggesuserschk/man/figures/lifecycle-questioning.svg0000644000176200001440000000171414436206156020273 0ustar liggesuserslifecyclelifecyclequestioningquestioning chk/man/figures/lifecycle-stable.svg0000644000176200001440000000247214654734236017211 0ustar liggesusers lifecycle: stable lifecycle stable chk/man/figures/lifecycle-experimental.svg0000644000176200001440000000245014654734236020430 0ustar liggesusers lifecycle: experimental lifecycle experimental chk/man/figures/lifecycle-deprecated.svg0000644000176200001440000000244014654734236020032 0ustar liggesusers lifecycle: deprecated lifecycle deprecated chk/man/figures/lifecycle-superseded.svg0000644000176200001440000000244014654734236020075 0ustar liggesusers lifecycle: superseded lifecycle superseded chk/man/figures/logo.png0000644000176200001440000000546214436206156014722 0ustar liggesusersPNG  IHDRxa>tEXtSoftwareAdobe ImageReadyqe< IDATxSEǻBYdI%VI<%*/L*p 9y*\`YE)+KJa\$,Bfٝ陝yj2Pig}_Xg䱥yJy},6<)K`n\l=p/L#63 6_[N۠X_5:දX/cvuv[G^,| v몳mmm칾^}{ {*)flгXΎCW=͎^Ћ.-}Y}`Ⰺ Ug:;Ynur=M6wmnm3)ݰ窗D}ѓd6)*nؼc^m}GP| й*ǖ>/eؠ8:OاA uS^%p v5ܝEaiO찗gGĐjAD(KJcu5dnʒ<"zy](p:%y`[.%N{ZKU!augeI0+0(`JԬ=4cMyʄ{]ء {ռ' ;yko*dwj{S!` K poo!I闳 Lp 0%7Հ[2[2 [2 q[2qEr25VF Y#ik`Yikdr;LvF':d рBN\6, 9p rZ& p3i8IM'geV6X-szpM5bXYֳ?YXtܣٻpZƢ"&j\n/nuL5];΢kVq}l-3YCrצmY1^wU(NpVr\iUبWMì䆭6<4I0*må `2L0&#d`t?zCoK5'CoK0&k1 ѱtʿllW\)oMƷ``=<&*y>dn<SO}~i)6}+ܷ^<*Γa6`p۸ @1x.~_me_ݼgZyL׿7Ňpq Z݄E,z ^mzPF0VYzpK;\kƬaˆ`_r_ܵ^CRop뿮jvR6uo[K>>Яդ0'葁:ćUx_Kg?addtf_l{.Zm}Nװ;l&*T!BS cX~?\k?fB?F-YNq3 @' ߘ_c73ЂD90ئN}l@nnA@#">;}P]qcCg7|Ώ*\WU&P!W RP;yT7&@;nU:;-Kne:+:x7iѮcY2" %YȊ\M #mS֟j>ҋ;uqAA罆U&-gފ^+^`Wx%kUq%lsk[l)P/рkV'bɏN51pݰj\VU%-2^j׀.0˒*Ӌ\㶵*K(&d/k@YiϨx\˒*xx>G^%:uzY22v^*$ni8xXN%.`yоʒp,iq-UY%e<hd*-p@C?Ҟf `}UfcLx? _9IENDB`chk/man/figures/lifecycle-archived.svg0000644000176200001440000000170714436206156017515 0ustar liggesusers lifecyclelifecyclearchivedarchived chk/man/figures/lifecycle-defunct.svg0000644000176200001440000000170414436206156017355 0ustar liggesuserslifecyclelifecycledefunctdefunct chk/man/figures/lifecycle-soft-deprecated.svg0000644000176200001440000000172614436206156021002 0ustar liggesuserslifecyclelifecyclesoft-deprecatedsoft-deprecated chk/man/figures/lifecycle-maturing.svg0000644000176200001440000000170614436206156017555 0ustar liggesuserslifecyclelifecyclematuringmaturing chk/man/figures/lifecycle-retired.svg0000644000176200001440000000170514436206156017364 0ustar liggesusers lifecyclelifecycleretiredretired chk/man/chk_integer.Rd0000644000176200001440000000253614743771477014376 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-integer.R \name{chk_integer} \alias{chk_integer} \alias{vld_integer} \title{Check Integer} \usage{ chk_integer(x, x_name = NULL) vld_integer(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if integer using \code{is.integer(x)} } \section{Functions}{ \itemize{ \item \code{vld_integer()}: Validate Integer }} \examples{ # chk_integer chk_integer(1L) try(chk_integer(1)) # vld_integer vld_integer(1L) vld_integer(matrix(1:4, nrow = 2L)) vld_integer(integer(0)) vld_integer(NA_integer_) vld_integer(1) vld_integer(TRUE) } \seealso{ \code{\link[=is.integer]{is.integer()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character}()}, \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_s4_class.Rd0000644000176200001440000000251314743771477014447 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-s4-class.R \name{chk_s4_class} \alias{chk_s4_class} \alias{vld_s4_class} \title{Check Inherits from S4 Class} \usage{ chk_s4_class(x, class, x_name = NULL) vld_s4_class(x, class) } \arguments{ \item{x}{The object to check.} \item{class}{A string specifying the class.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks inherits from S4 class using \code{isS4(x) && methods::is(x, class)} } \section{Functions}{ \itemize{ \item \code{vld_s4_class()}: Validate Inherits from S4 Class }} \examples{ # chk_s4_class try(chk_s4_class(1, "numeric")) chk_s4_class(getClass("MethodDefinition"), "classRepresentation") # vld_s4_class vld_s4_class(numeric(0), "numeric") vld_s4_class(getClass("MethodDefinition"), "classRepresentation") } \seealso{ \code{\link[methods:is]{methods::is()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other id_checkers: \code{\link{chk_data}()}, \code{\link{chk_is}()}, \code{\link{chk_s3_class}()} } \concept{id_checkers} chk/man/chk_used.Rd0000644000176200001440000000156414743771477013701 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-used.R \name{chk_used} \alias{chk_used} \alias{vld_used} \title{Check ... Used} \usage{ chk_used(...) vld_used(...) } \arguments{ \item{...}{Additional arguments.} } \value{ The \code{chk_} function throws an informative error if the test fails. } \description{ Checks if is ... used using \code{length(list(...)) != 0L} } \section{Functions}{ \itemize{ \item \code{vld_used()}: Validate ... Used }} \examples{ # chk_used fun <- function(x, ...) { chk_used(...) x } try(fun(1)) fun(1, 2) # vld_used fun <- function(x, ...) { vld_used(...) } fun(1) fun(1, 2) } \seealso{ \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other ellipsis_checkers: \code{\link{chk_unused}()} } \concept{ellipsis_checkers} chk/man/chk_true.Rd0000644000176200001440000000273414743771477013720 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-true.R \name{chk_true} \alias{chk_true} \alias{vld_true} \title{Check TRUE} \usage{ chk_true(x, x_name = NULL) vld_true(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if TRUE using \code{is.logical(x) && length(x) == 1L && !anyNA(x) && x} } \section{Functions}{ \itemize{ \item \code{vld_true()}: Validate TRUE }} \examples{ # chk_true chk_true(TRUE) try(chk_true(1)) # vld_true vld_true(TRUE) vld_true(FALSE) vld_true(NA) vld_true(0) vld_true(c(TRUE, TRUE)) } \seealso{ \code{\link[=is.logical]{is.logical()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other logical_checkers: \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_logical}()} Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_tz}()} } \concept{logical_checkers} \concept{scalar_checkers} chk/man/chk_scalar.Rd0000644000176200001440000000234114743771477014200 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-scalar.R \name{chk_scalar} \alias{chk_scalar} \alias{vld_scalar} \title{Check Scalar} \usage{ chk_scalar(x, x_name = NULL) vld_scalar(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is a vector using \code{length(x) == 1L} } \section{Functions}{ \itemize{ \item \code{vld_scalar()}: Validate Scalar }} \examples{ # chk_scalar chk_scalar(1) chk_scalar(list(1)) try(chk_scalar(1:2)) # vld_scalar vld_scalar(1) } \seealso{ \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} } \concept{scalar_checkers} chk/man/chk_all_equal.Rd0000644000176200001440000000323614743771477014676 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-all-equal.R \name{chk_all_equal} \alias{chk_all_equal} \alias{vld_all_equal} \title{Check All Equal} \usage{ chk_all_equal(x, tolerance = sqrt(.Machine$double.eps), x_name = NULL) vld_all_equal(x, tolerance = sqrt(.Machine$double.eps)) } \arguments{ \item{x}{The object to check.} \item{tolerance}{A non-negative numeric scalar.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks all elements in x equal using \code{length(x) < 2L || all(vapply(x, vld_equal, TRUE, y = x[[1]], tolerance = tolerance))} } \section{Functions}{ \itemize{ \item \code{vld_all_equal()}: Validate All Equal }} \examples{ # chk_all_equal chk_all_equal(c(1, 1.00000001)) try(chk_all_equal(c(1, 1.0000001))) chk_all_equal(list(c(x = 1), c(x = 1))) try(chk_all_equal(list(c(x = 1), c(y = 1)))) # vld_all_equal vld_all_equal(c(1, 1L)) } \seealso{ \code{\link[=length]{length()}} \code{\link[=vld_equal]{vld_equal()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()}, \code{\link{chk_equal}()}, \code{\link{chk_equivalent}()}, \code{\link{chk_identical}()} Other all_checkers: \code{\link{chk_all}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()} } \concept{all_checkers} \concept{equal_checkers} chk/man/chk_tz.Rd0000644000176200001440000000260014743771477013366 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-tz.R \name{chk_tz} \alias{chk_tz} \alias{vld_tz} \title{Check Time Zone} \usage{ chk_tz(x, x_name = NULL) vld_tz(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing valid scalar timezone using \code{is.character(x) && length(x) == 1L && !anyNA(x) && x \%in\% OlsonNames()} } \section{Functions}{ \itemize{ \item \code{vld_tz()}: Validate Time Zone }} \examples{ chk_tz("UTC") try(chk_tz("TCU")) vld_tz("UTC") vld_tz("TCU") } \seealso{ \code{\link[=length]{length()}} \code{\link[=OlsonNames]{OlsonNames()}} \code{\link[=is.character]{is.character()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()} } \concept{date_checkers} \concept{scalar_checkers} \concept{tz_checkers} chk/man/chk_atomic.Rd0000644000176200001440000000226214743771477014211 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-atomic.R \name{chk_atomic} \alias{chk_atomic} \alias{vld_atomic} \title{Check Atomic} \usage{ chk_atomic(x, x_name = NULL) vld_atomic(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if atomic using \code{is.atomic(x)} } \section{Functions}{ \itemize{ \item \code{vld_atomic()}: Validate Atomic }} \examples{ # chk_atomic chk_atomic(1) try(chk_atomic(list(1))) # vld_atomic vld_atomic(1) vld_atomic(matrix(1:3)) vld_atomic(character(0)) vld_atomic(list(1)) vld_atomic(NULL) } \seealso{ \code{\link[=is.atomic]{is.atomic()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_structure_checkers: \code{\link{chk_array}()}, \code{\link{chk_list}()}, \code{\link{chk_matrix}()}, \code{\link{chk_vector}()} } \concept{data_structure_checkers} chk/man/chk_match.Rd0000644000176200001440000000231614743771477014031 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-match.R \name{chk_match} \alias{chk_match} \alias{vld_match} \title{Check Matches} \usage{ chk_match(x, regexp = ".+", x_name = NULL) vld_match(x, regexp = ".+") } \arguments{ \item{x}{The object to check.} \item{regexp}{A string of a regular expression.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all values match regular expression using \code{all(grepl(regexp, x[!is.na(x)]))} } \section{Functions}{ \itemize{ \item \code{vld_match()}: Validate Matches }} \examples{ # chk_match chk_match("1") try(chk_match("1", regexp = "2")) # vld_match vld_match("1") vld_match("a", regexp = "a") vld_match("") vld_match("1", regexp = "2") vld_match(NA_character_, regexp = ".*") } \seealso{ \code{\link[=all]{all()}} \code{\link[=grepl]{grepl()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. } \concept{regex_checkers} chk/man/chk_all_identical.Rd0000644000176200001440000000312214743771477015515 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-all-identical.R \name{chk_all_identical} \alias{chk_all_identical} \alias{vld_all_identical} \title{Check All Identical} \usage{ chk_all_identical(x, x_name = NULL) vld_all_identical(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks all elements in x identical using \code{length(x) < 2L || all(vapply(x, vld_identical, TRUE, y = x[[1]]))} \strong{Pass}: \code{c(1, 1, 1)}, \code{list(1, 1)} \strong{Fail}: \code{c(1, 1.0000001)}, \code{list(1, NA)} } \section{Functions}{ \itemize{ \item \code{vld_all_identical()}: Validate All Identical }} \examples{ # chk_all_identical chk_all_identical(c(1, 1)) try(chk_all_identical(c(1, 1.1))) # vld_all_identical vld_all_identical(c(1, 1)) } \seealso{ \code{\link[=length]{length()}} \code{\link[=vld_identical]{vld_identical()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other equal_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_equal}()}, \code{\link{chk_equivalent}()}, \code{\link{chk_identical}()} Other all_checkers: \code{\link{chk_all}()}, \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()} } \concept{all_checkers} \concept{equal_checkers} chk/man/chk_whole_number.Rd0000644000176200001440000000300714743771477015421 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-whole-number.R \name{chk_whole_number} \alias{chk_whole_number} \alias{vld_whole_number} \title{Check Whole Number} \usage{ chk_whole_number(x, x_name = NULL) vld_whole_number(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing integer scalar or double equivalent using \code{vld_number(x) && (is.integer(x) || vld_true(all.equal(x, trunc(x))))} \strong{Pass}: \code{1}, \code{2L}, \code{1e10}, \code{-Inf} \strong{Fail}: \code{"a"}, \code{1:3}, \code{NA_integer_}, \code{log(10)} } \section{Functions}{ \itemize{ \item \code{vld_whole_number()}: Validate Whole Number }} \examples{ # chk_whole_number chk_whole_number(2) try(chk_whole_number(1.1)) # vld_whole_number vld_whole_number(2) } \seealso{ \code{\link[=is.integer]{is.integer()}} \code{\link[=vld_true]{vld_true()}} \code{\link[=vld_number]{vld_number()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checker: \code{\link{chk_complex_number}()} Other whole_number_checkers: \code{\link{chk_count}()}, \code{\link{chk_whole_numeric}()} } \concept{scalar_checker} \concept{whole_number_checkers} chk/man/chk_null_or.Rd0000644000176200001440000000144214436206156014370 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-null-or.R \name{chk_null_or} \alias{chk_null_or} \title{Check NULL Or} \usage{ chk_null_or(x, chk, ..., vld, x_name = NULL) } \arguments{ \item{x}{The object to check.} \item{chk}{A chk function. Soft-deprecated for vld. \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}} \item{...}{Arguments passed to chk.} \item{vld}{A vld function.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails. } \description{ Checks if NULL or passes test. } \examples{ chk_null_or(NULL, chk_number) chk_null_or(1, chk_number) try(chk_null_or("1", chk_number)) } chk/man/check_data.Rd0000644000176200001440000000265314744734003014143 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check-data.R \name{check_data} \alias{check_data} \title{Check Data} \usage{ check_data( x, values = NULL, exclusive = FALSE, order = FALSE, nrow = numeric(0), key = character(0), x_name = NULL ) } \arguments{ \item{x}{The object to check.} \item{values}{A uniquely named list of atomic vectors of the column values.} \item{exclusive}{A flag specifying whether x must only include columns named in values.} \item{order}{A flag specifying whether the order of columns in x must match names in values.} \item{nrow}{A flag or a whole numeric vector of the value, value range or possible values.} \item{key}{A character vector of the columns that represent a unique key.} \item{x_name}{A string of the name of object x or NULL.} } \value{ An informative error if the test fails or an invisible copy of x. } \description{ Checks column names, values, number of rows and key for a data.frame. } \examples{ check_data(data.frame()) check_data(data.frame(x = 2), list(x = 1)) try(check_data(data.frame(x = 2), list(y = 1L))) try(check_data(data.frame(x = 2), list(y = 1))) try(check_data(data.frame(x = 2), nrow = 2)) } \seealso{ Other check: \code{\link{check_dim}()}, \code{\link{check_dirs}()}, \code{\link{check_files}()}, \code{\link{check_key}()}, \code{\link{check_length}()}, \code{\link{check_names}()}, \code{\link{check_values}()} } \concept{check} chk/man/chk_character.Rd0000644000176200001440000000264314743771477014674 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-character.R \name{chk_character} \alias{chk_character} \alias{vld_character} \title{Check Character} \usage{ chk_character(x, x_name = NULL) vld_character(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if character using \code{is.character(x)} } \section{Functions}{ \itemize{ \item \code{vld_character()}: Validate Character }} \examples{ # chk_character chk_character("1") try(chk_character(1)) # vld_character vld_character("1") vld_character(matrix("a")) vld_character(character(0)) vld_character(NA_character_) vld_character(1) vld_character(TRUE) vld_character(factor("text")) } \seealso{ \code{\link[=is.character]{is.character()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_type_checkers: \code{\link{chk_character_or_factor}()}, \code{\link{chk_complex}()}, \code{\link{chk_double}()}, \code{\link{chk_environment}()}, \code{\link{chk_integer}()}, \code{\link{chk_logical}()}, \code{\link{chk_numeric}()}, \code{\link{chk_raw}()} } \concept{data_type_checkers} chk/man/chk_missing.Rd0000644000176200001440000000233214743771477014404 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-missing.R \name{chk_missing} \alias{chk_missing} \alias{vld_missing} \title{Check Missing Argument} \usage{ chk_missing(x, x_name = NULL) vld_missing(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks argument missing using \code{missing(x)} } \details{ Currently only checks if value is available (as opposed to whether it was specified). } \section{Functions}{ \itemize{ \item \code{vld_missing()}: Validate Missing Argument }} \examples{ # chk_missing fun <- function(x) { chk_missing(x) } fun() try(fun(1)) # vld_missing fun <- function(x) { vld_missing(x) } fun() fun(1) } \seealso{ \code{\link[=missing]{missing()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other missing_checkers: \code{\link{chk_function}()}, \code{\link{chk_not_missing}()} } \concept{missing_checkers} chk/man/chk_whole_numeric.Rd0000644000176200001440000000272314743771477015577 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-whole-numeric.R \name{chk_whole_numeric} \alias{chk_whole_numeric} \alias{vld_whole_numeric} \title{Check Whole Numeric} \usage{ chk_whole_numeric(x, x_name = NULL) vld_whole_numeric(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if integer vector or double equivalent using \code{is.integer(x) || (is.double(x) && vld_true(all.equal(x, as.integer(x))))} } \section{Functions}{ \itemize{ \item \code{vld_whole_numeric()}: Validate Whole Numeric }} \examples{ # chk_whole_numeric chk_whole_numeric(1) try(chk_whole_numeric(1.1)) # vld_whole_numeric vld_whole_numeric(1) vld_whole_numeric(NA_real_) vld_whole_numeric(1:2) vld_whole_numeric(double(0)) vld_whole_numeric(TRUE) vld_whole_numeric(1.5) } \seealso{ \code{\link[=is.integer]{is.integer()}} \code{\link[=is.double]{is.double()}} \code{\link[=vld_true]{vld_true()}} \code{\link[=all.equal]{all.equal()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other whole_number_checkers: \code{\link{chk_count}()}, \code{\link{chk_whole_number}()} } \concept{whole_number_checkers} chk/man/chk_all.Rd0000644000176200001440000000235514743771477013510 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-all.R \name{chk_all} \alias{chk_all} \alias{vld_all} \title{Check All} \usage{ chk_all(x, chk_fun, ..., x_name = NULL) vld_all(x, vld_fun, ...) } \arguments{ \item{x}{The object to check.} \item{chk_fun}{A chk_ function.} \item{...}{Additional arguments.} \item{x_name}{A string of the name of object x or NULL.} \item{vld_fun}{A vld_ function.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks all elements using \code{all(vapply(x, chk_fun, TRUE, ...))} } \section{Functions}{ \itemize{ \item \code{vld_all()}: Validate All }} \examples{ # chk_all chk_all(TRUE, chk_lgl) # FIXME try(chk_all(1, chk_lgl)) chk_all(c(TRUE, NA), chk_lgl) # vld_all vld_all(c(TRUE, NA), vld_lgl) } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other all_checkers: \code{\link{chk_all_equal}()}, \code{\link{chk_all_equivalent}()}, \code{\link{chk_all_identical}()} } \concept{all_checkers} chk/man/chk_number.Rd0000644000176200001440000000225414743771477014226 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-number.R \name{chk_number} \alias{chk_number} \alias{vld_number} \title{Check Number} \usage{ chk_number(x, x_name = NULL) vld_number(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if non-missing numeric scalar using \code{is.numeric(x) && length(x) == 1L && !anyNA(x)} \strong{Pass}: \code{1}, \code{2L}, \code{log(10)}, \code{-Inf} \strong{Fail}: \code{"a"}, \code{1:3}, \code{NA_real_} } \section{Functions}{ \itemize{ \item \code{vld_number()}: Validate Number }} \examples{ # chk_number chk_number(1.1) try(chk_number(TRUE)) # vld_number vld_number(1.1) } \seealso{ \code{\link[=is.numeric]{is.numeric()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. } \concept{data_type_checkers scalar_checkers} chk/man/deparse_backtick_chk.Rd0000644000176200001440000000153314436206156016175 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{deparse_backtick_chk} \alias{deparse_backtick_chk} \alias{backtick_chk} \alias{unbacktick_chk} \title{Deparse Backtick} \usage{ deparse_backtick_chk(x) backtick_chk(x) unbacktick_chk(x) } \arguments{ \item{x}{A substituted object to deparse.} } \value{ A string of the backticked substituted object. } \description{ \code{deparse_backtick_chk} is a wrapper on \code{\link[=deparse]{deparse()}} and \code{backtick_chk}. } \details{ It is exported to allow users to easily construct their own \code{chk_} functions. } \section{Functions}{ \itemize{ \item \code{backtick_chk()}: Backtick \item \code{unbacktick_chk()}: Unbacktick }} \examples{ # deparse_backtick_chk deparse_backtick_chk(2) deparse_backtick_chk(2^2) } \seealso{ \code{\link[=deparse]{deparse()}} } chk/man/cc.Rd0000644000176200001440000000203514436206156012455 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/cc.R \name{cc} \alias{cc} \title{Concatenate with Commas} \usage{ cc( x, conj = ", ", sep = ", ", brac = if (is.character(x) || is.factor(x)) "'" else "", ellipsis = 10L, chk = TRUE ) } \arguments{ \item{x}{The object to concatenate.} \item{conj}{A string of the conjunction to separate the last value by.} \item{sep}{A string of the separator.} \item{brac}{A string to brac the values by.} \item{ellipsis}{A numeric scalar of the maximum number of values to display before using an ellipsis.} \item{chk}{A flag specifying whether to check the other parameters.} } \value{ A string. } \description{ Concatenates object values into a string with each value separated by a comma and the last value separated by a conjunction. } \details{ By default, if x has more than 10 values an ellipsis is used to ensure only 10 values are displayed (including the ellipsis). } \examples{ cc(1:2) cc(1:2, conj = " or") cc(3:1, brac = "'") cc(1:11) cc(as.character(1:2)) } chk/man/abort_chk.Rd0000644000176200001440000000323714436206156014031 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{abort_chk} \alias{abort_chk} \title{Abort Check} \usage{ abort_chk(..., n = NULL, tidy = TRUE, call = rlang::caller_call(2)) } \arguments{ \item{...}{Multiple objects that are converted to a string using \code{paste0(..., collapse = '')}.} \item{n}{The value of n for converting \code{sprintf}-like types.} \item{tidy}{A flag specifying whether capitalize the first character and add a missing period.} \item{call}{The execution environment of a currently running function, e.g. \code{call = caller_env()}. The corresponding function call is retrieved and mentioned in error messages as the source of the error. You only need to supply \code{call} when throwing a condition from a helper function which wouldn't be relevant to mention in the message. Can also be \code{NULL} or a \link[rlang:topic-defuse]{defused function call} to respectively not display any call or hard-code a code to display. For more information about error calls, see \ifelse{html}{\link[rlang:topic-error-call]{Including function calls in error messages}}{\link[rlang:topic-error-call]{Including function calls in error messages}}.} } \value{ Throws an error of class \code{'chk_error'}. } \description{ A wrapper on \code{\link[=err]{err()}} that sets the subclass to be \code{'chk_error'}. } \details{ It is exported to allow users to easily construct their own \code{chk_} functions. } \examples{ try(abort_chk("x must be NULL")) try(abort_chk("`x` must be NULL")) try(abort_chk("there \%r \%n problem value\%s", n = 1)) try(abort_chk("there \%r \%n problem value\%s", n = 1.5)) } \seealso{ \code{\link[=err]{err()}} } chk/man/chk_date.Rd0000644000176200001440000000261314743771477013652 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-date.R \name{chk_date} \alias{chk_date} \alias{vld_date} \title{Check Date} \usage{ chk_date(x, x_name = NULL) vld_date(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks non-missing Date scalar using \code{inherits(x, "Date") && length(x) == 1L && !anyNA(x)} } \section{Functions}{ \itemize{ \item \code{vld_date()}: Validate Date }} \examples{ # chk_date chk_date(Sys.Date()) try(chk_date(1)) # vld_date vld_date(Sys.Date()) vld_date(Sys.time()) vld_date(1) } \seealso{ \code{\link[=inherits]{inherits()}} \code{\link[=length]{length()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other scalar_checkers: \code{\link{chk_count}()}, \code{\link{chk_date_time}()}, \code{\link{chk_false}()}, \code{\link{chk_flag}()}, \code{\link{chk_lgl}()}, \code{\link{chk_scalar}()}, \code{\link{chk_string}()}, \code{\link{chk_true}()}, \code{\link{chk_tz}()} Other datetime_checkers: \code{\link{chk_date_time}()} } \concept{datetime_checkers} \concept{scalar_checkers} chk/man/chk_sorted.Rd0000644000176200001440000000175614743771477014244 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-sorted.R \name{chk_sorted} \alias{chk_sorted} \alias{vld_sorted} \title{Check Sorted} \usage{ chk_sorted(x, x_name = NULL) vld_sorted(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is sorted using \code{is.unsorted(x, na.rm = TRUE)} } \section{Functions}{ \itemize{ \item \code{vld_sorted()}: Validate Sorted }} \examples{ # chk_sorted chk_sorted(1:2) try(chk_sorted(2:1)) # vld_sorted vld_sorted(1:2) vld_sorted(2:1) } \seealso{ \code{\link[=is.unsorted]{is.unsorted()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. } \concept{sorted_checkers} chk/man/chk_array.Rd0000644000176200001440000000215714743771477014056 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-array.R \name{chk_array} \alias{chk_array} \alias{vld_array} \title{Check Array} \usage{ chk_array(x, x_name = NULL) vld_array(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if is an array using \code{is.array(x)} } \section{Functions}{ \itemize{ \item \code{vld_array()}: Validate Array }} \examples{ # chk_array chk_array(array(1)) try(chk_array(matrix(1))) # vld_array vld_array(1) vld_array(array(1)) } \seealso{ \code{\link[=is.array]{is.array()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other data_structure_checkers: \code{\link{chk_atomic}()}, \code{\link{chk_list}()}, \code{\link{chk_matrix}()}, \code{\link{chk_vector}()} } \concept{data_structure_checkers} chk/man/chk_is.Rd0000644000176200001440000000220414743771477013344 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-is.R \name{chk_is} \alias{chk_is} \alias{vld_is} \title{Check Class} \usage{ chk_is(x, class, x_name = NULL) vld_is(x, class) } \arguments{ \item{x}{The object to check.} \item{class}{A string specifying the class.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks inherits from class using \code{inherits(x, class)} } \section{Functions}{ \itemize{ \item \code{vld_is()}: Validate Inherits from Class }} \examples{ chk_is(1, "numeric") try(chk_is(1L, "double")) # vld_is vld_is(numeric(0), "numeric") vld_is(1L, "double") } \seealso{ \code{\link[=inherits]{inherits()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other id_checkers: \code{\link{chk_data}()}, \code{\link{chk_s3_class}()}, \code{\link{chk_s4_class}()} } \concept{id_checkers} chk/man/chk_lt.Rd0000644000176200001440000000242314743771477013353 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-lt.R \name{chk_lt} \alias{chk_lt} \alias{vld_lt} \title{Check Less Than} \usage{ chk_lt(x, value = 0, x_name = NULL) vld_lt(x, value = 0) } \arguments{ \item{x}{The object to check.} \item{value}{A non-missing scalar of a value.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if all non-missing values are less than value using \code{all(x[!is.na(x)] < value)} } \section{Functions}{ \itemize{ \item \code{vld_lt()}: Validate Less Than }} \examples{ # chk_lt chk_lt(-0.1) try(chk_lt(c(-0.1, 0.2))) # vld_lt vld_lt(numeric(0)) vld_lt(0) vld_lt(-0.1) vld_lt(c(-0.1, -0.2, NA)) vld_lt(c(-0.1, 0.2)) vld_lt(c(-0.1, 0.2), value = 1) vld_lt("a", value = "b") } \seealso{ \code{\link[=all]{all()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other range_checkers: \code{\link{chk_gt}()}, \code{\link{chk_gte}()}, \code{\link{chk_lte}()}, \code{\link{chk_range}()} } \concept{range_checkers} chk/man/chk_ext.Rd0000644000176200001440000000253014743771477013533 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-ext.R \name{chk_ext} \alias{chk_ext} \alias{vld_ext} \title{Check File Extension} \usage{ chk_ext(x, ext, x_name = NULL) vld_ext(x, ext) } \arguments{ \item{x}{The object to check.} \item{ext}{A character vector of the permitted file extensions (without the .).} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks extension using \code{vld_string(x) && vld_subset(tools::file_ext(x), ext)} The user may want to use \code{\link[=toupper]{toupper()}} or \code{\link[=tolower]{tolower()}} to ensure the case matches. } \section{Functions}{ \itemize{ \item \code{vld_ext()}: Validate File Extension }} \examples{ # chk_ext try(chk_ext("file1.pdf", "png")) # vld_ext vld_ext("oeu.pdf", "pdf") vld_ext(toupper("oeu.pdf"), "PDF") } \seealso{ \code{\link[=vld_string]{vld_string()}} \code{\link[=vld_subset]{vld_subset()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other file_checkers: \code{\link{chk_dir}()}, \code{\link{chk_file}()} } \concept{file_checkers} chk/man/chk_not_any_na.Rd0000644000176200001440000000251014743771477015056 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-not-any-na.R \name{chk_not_any_na} \alias{chk_not_any_na} \alias{vld_not_any_na} \title{Check Not Any Missing Values} \usage{ chk_not_any_na(x, x_name = NULL) vld_not_any_na(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if not any missing values using \code{!anyNA(x)} \strong{Pass}: \code{1}, \code{1:2}, \code{"1"}, \code{logical(0)}. \strong{Fail}: \code{NA}, \code{c(1, NA)}. } \section{Functions}{ \itemize{ \item \code{vld_not_any_na()}: Validate Not Any Missing Values }} \examples{ # chk_not_any_na chk_not_any_na(1) try(chk_not_any_na(NA)) # vld_not_any_na vld_not_any_na(1) vld_not_any_na(1:2) vld_not_any_na(NA_real_) vld_not_any_na(integer(0)) vld_not_any_na(c(NA, 1)) vld_not_any_na(TRUE) } \seealso{ For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other misc_checkers: \code{\link{chk_join}()}, \code{\link{chk_not_empty}()}, \code{\link{chk_unique}()} } \concept{misc_checkers} chk/man/chk_file.Rd0000644000176200001440000000217714743771477013661 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chk-file.R \name{chk_file} \alias{chk_file} \alias{vld_file} \title{Check File Exists} \usage{ chk_file(x, x_name = NULL) vld_file(x) } \arguments{ \item{x}{The object to check.} \item{x_name}{A string of the name of object x or NULL.} } \value{ The \code{chk_} function throws an informative error if the test fails or returns the original object if successful so it can used in pipes. The \code{vld_} function returns a flag indicating whether the test was met. } \description{ Checks if file exists using \code{vld_string(x) && file.exists(x) && !dir.exists(x)} } \section{Functions}{ \itemize{ \item \code{vld_file()}: Validate File Exists }} \examples{ # chk_file try(chk_file(tempfile())) # vld_file vld_file(tempfile()) } \seealso{ \code{\link[=vld_string]{vld_string()}} \code{\link[=file.exists]{file.exists()}} \code{\link[=dir.exists]{dir.exists()}} For more details about the use of this function, please read the article \code{vignette("chk-families")}. Other file_checkers: \code{\link{chk_dir}()}, \code{\link{chk_ext}()} } \concept{file_checkers} chk/man/chkor.Rd0000644000176200001440000000133414436206156013177 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chkor.R \name{chkor} \alias{chkor} \title{Check OR} \usage{ chkor(...) } \arguments{ \item{...}{Multiple \code{chk_} functions.} } \value{ An informative error if the test fails. } \description{ The \code{chkor()} function has been deprecated for the faster \code{chkor_vld()}. } \details{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} } \examples{ chkor() chkor(chk_flag(TRUE)) try(chkor(chk_flag(1))) try(chkor(chk_flag(1), chk_flag(2))) chkor(chk_flag(1), chk_flag(TRUE)) } \seealso{ \code{\link[=chk_null_or]{chk_null_or()}} } chk/DESCRIPTION0000644000176200001440000000401214745002005012517 0ustar liggesusersPackage: chk Title: Check User-Supplied Function Arguments Version: 0.10.0 Authors@R: c( person("Joe", "Thorley", , "joe@poissonconsulting.ca", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-7683-4592")), person("Kirill", "Müller", role = "aut", comment = c(ORCID = "0000-0002-1416-3412")), person("Ayla", "Pearson", role = "aut", comment = c(ORCID = "0000-0001-7388-1222")), person("Florencia", "D'Andrea", role = "ctb"), person("Nadine", "Hussein", , "nadine@poissonconsulting.ca", role = "ctb", comment = c(ORCID = "0000-0003-4470-8361")), person("Evan", "Amies-Galonski", , "evan@poissonconsulting.ca", role = "ctb", comment = c(ORCID = "0000-0003-1096-2089")), person("Poisson Consulting", role = c("cph", "fnd")) ) Description: For developers to check user-supplied function arguments. It is designed to be simple, fast and customizable. Error messages follow the tidyverse style guide. License: MIT + file LICENSE URL: https://github.com/poissonconsulting/chk, https://poissonconsulting.github.io/chk/ BugReports: https://github.com/poissonconsulting/chk/issues/ Depends: R (>= 3.6) Imports: lifecycle, methods, rlang, tools Suggests: covr, knitr, rmarkdown, testthat (>= 3.0.0), withr VignetteBuilder: knitr RdMacros: lifecycle Config/Needs/website: poissonconsulting/poissontemplate Config/testthat/edition: 3 Encoding: UTF-8 Language: en-US RoxygenNote: 7.3.2.9000 NeedsCompilation: no Packaged: 2025-01-24 19:31:20 UTC; joe Author: Joe Thorley [aut, cre] (), Kirill Müller [aut] (), Ayla Pearson [aut] (), Florencia D'Andrea [ctb], Nadine Hussein [ctb] (), Evan Amies-Galonski [ctb] (), Poisson Consulting [cph, fnd] Maintainer: Joe Thorley Repository: CRAN Date/Publication: 2025-01-24 21:20:05 UTC