diff --git a/.Rbuildignore b/.Rbuildignore index 9fca0424af..332618274d 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -11,3 +11,4 @@ ^inst/examples/quickstart_sparse$ ^inst/examples/array_metadata_array$ ^\.editorconfig$ +^src/unused_*cpp.txt$ diff --git a/NAMESPACE b/NAMESPACE index f18a12b4b8..7dd610c3d8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -70,7 +70,6 @@ export(tiledb_stats_enable) export(tiledb_stats_print) export(tiledb_subarray) export(tiledb_version) -exportClasses("tiledb_sparse") exportClasses(tiledb_array_schema) exportClasses(tiledb_attr) exportClasses(tiledb_config) @@ -80,6 +79,7 @@ exportClasses(tiledb_dim) exportClasses(tiledb_domain) exportClasses(tiledb_filter) exportClasses(tiledb_filter_list) +exportClasses(tiledb_sparse) exportMethods("[") exportMethods(attrs) exportMethods(cell_order) diff --git a/R/ArraySchema.R b/R/ArraySchema.R index 334aa9a24d..cd413a4d95 100644 --- a/R/ArraySchema.R +++ b/R/ArraySchema.R @@ -6,7 +6,7 @@ setClass("tiledb_array_schema", slots = list(ptr = "externalptr")) tiledb_array_schema.from_ptr <- function(ptr) { - if (missing(ptr) || typeof(ptr) != "externalptr" || is.null(ptr)) { + if (missing(ptr) || typeof(ptr) != "externalptr" || is.null(ptr)) { stop("ptr argument must be a non NULL externalptr to a tiledb_array_schema instance") } new("tiledb_array_schema", ptr = ptr) @@ -51,6 +51,9 @@ tiledb_array_schema <- function( stop("domain argument must be a tiledb::Domain") } is_attr <- function(obj) is(obj, "tiledb_attr") + if (is_attr(attrs)) { # if an attrs object given: + attrs <- list(attrs) # make it a list so that lapply works below + } if (missing(attrs) || length(attrs) == 0 || !all(vapply(attrs, is_attr, logical(1)))) { stop("attrs argument must be a list of one or tiled_attr objects") } diff --git a/R/Domain.R b/R/Domain.R index 164bf88b86..cab38c61b0 100644 --- a/R/Domain.R +++ b/R/Domain.R @@ -30,6 +30,9 @@ tiledb_domain <- function(dims, ctx = tiledb_get_context()) { stop("argument ctx must be a tiledb_ctx") } is_dim <- function(obj) is(obj, "tiledb_dim") + if (is_dim(dims)) { # if a dim object given: + dims <- list(dims) # make it a vector so that lapply works below + } if (missing(dims) || length(dims) == 0 || !all(vapply(dims, is_dim, logical(1)))) { stop("argument dims must be a list of one or more tileb_dim") } diff --git a/R/FilterList.R b/R/FilterList.R index 593e600241..2be1952d91 100644 --- a/R/FilterList.R +++ b/R/FilterList.R @@ -28,6 +28,9 @@ tiledb_filter_list <- function(filters = c(), ctx = tiledb_get_context()) { stop("argument ctx must be a tiledb_ctx") } is_filter <- function(obj) is(obj, "tiledb_filter") + if (is_filter(filters)) { # if a filters object given: + filters <- list(filters) # make it a list so that lapply works below + } filter_ptrs = c() if (length(filters) > 0) { if (!all(vapply(filters, is_filter, logical(1)))) { diff --git a/R/Metadata.R b/R/Metadata.R index 1982dc627d..8790861708 100644 --- a/R/Metadata.R +++ b/R/Metadata.R @@ -4,17 +4,14 @@ ##' Test if TileDB Array has Metadata ##' -##' @param arr A TileDB Array object, or a character URI describing one +##' @param arr A TileDB Array object ##' @param key A character value describing a metadata key ##' @return A logical value indicating if the given key exists in the ##' metdata of the given array ##' @export tiledb_has_metadata <- function(arr, key) { - if (is.character(arr)) { - return(has_metadata_simple(arr, key)) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("Argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -23,8 +20,8 @@ tiledb_has_metadata <- function(arr, key) { stop("Array is not open for reading, cannot access metadata.", call.=FALSE) } - ## Run query - return(has_metadata_ptr(arr@ptr, key)) + res <- libtiledb_array_get_metadata_list(arr@ptr) + return(key %in% names(res)) } ##' Return count of TileDB Array Metadata objects @@ -33,11 +30,8 @@ tiledb_has_metadata <- function(arr, key) { ##' @return A integer variable with the number of Metadata objects ##' @export tiledb_num_metadata <- function(arr) { - if (is.character(arr)) { - return(num_metadata_simple(arr)) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("Argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -47,21 +41,19 @@ tiledb_num_metadata <- function(arr) { } ## Run query - return(num_metadata_ptr(arr@ptr)) + return(libtiledb_array_get_metadata_num(arr@ptr)) } ##' Return a TileDB Array Metadata object given by key ##' ##' @param arr A TileDB Array object, or a character URI describing one ##' @param key A character value describing a metadata key -##' @return A object stored in the Metadata under the given key +##' @return A object stored in the Metadata under the given key, +##' or \sQuote{NULL} if none found. ##' @export tiledb_get_metadata <- function(arr, key) { - if (is.character(arr)) { - return(get_metadata_simple(arr, key)) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("Argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -70,8 +62,11 @@ tiledb_get_metadata <- function(arr, key) { stop("Array is not open for reading, cannot access metadata.", call.=FALSE) } - ## Run query - return(get_metadata_ptr(arr@ptr, key)) + res <- libtiledb_array_get_metadata_list(arr@ptr) + if (key %in% names(res)) + return(res[[key]]) + else + return(NULL) } ##' Store an object in TileDB Array Metadata under given key @@ -82,11 +77,8 @@ tiledb_get_metadata <- function(arr, key) { ##' @return A boolean value indicating success ##' @export tiledb_put_metadata <- function(arr, key, val) { - if (is.character(arr)) { - return(put_metadata_simple(arr, key, val)) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("Argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -96,7 +88,7 @@ tiledb_put_metadata <- function(arr, key, val) { } ## Run query - return(put_metadata_ptr(arr@ptr, key, val)) + return(libtiledb_array_put_metadata(arr@ptr, key, val)) } @@ -106,13 +98,8 @@ tiledb_put_metadata <- function(arr, key, val) { ##' @return A object stored in the Metadata under the given key ##' @export tiledb_get_all_metadata <- function(arr) { - if (is.character(arr)) { - res <- get_all_metadata_simple(arr) - class(res) <- "tiledb_metadata" - return(res) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("Argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -122,7 +109,7 @@ tiledb_get_all_metadata <- function(arr) { } ## Run query - res <- get_all_metadata_ptr(arr@ptr) + res <- libtiledb_array_get_metadata_list(arr@ptr) class(res) <- "tiledb_metadata" return(res) } @@ -138,16 +125,13 @@ print.tiledb_metadata <- function(x, width=NULL, ...) { ##' Delete a TileDB Array Metadata object given by key ##' -##' @param arr A TileDB Array object, or a character URI describing one +##' @param arr A TileDB Array object ##' @param key A character value describing a metadata key ##' @return A boolean indicating success ##' @export tiledb_delete_metadata <- function(arr, key) { - if (is.character(arr)) { - return(delete_metadata_simple(arr, key)) - } else if (!.isArray(arr)) { - message("Neither (text) URI nor Array.") - return(NULL) + if (!is(arr, "tiledb_sparse") && !is(arr, "tiledb_dense")) { + stop("ctx argument must be a TileDB (dense or sparse) array.", call.=FALSE) } ## Now deal with (default) case of an array object @@ -156,6 +140,7 @@ tiledb_delete_metadata <- function(arr, key) { stop("Array is not open for writing, cannot access metadata.", call.=FALSE) } - ## Run query - return(delete_metadata_ptr(arr@ptr, key)) + ## Run metadata removal + libtiledb_array_delete_metadata(arr@ptr, key); + invisible(TRUE) } diff --git a/R/RcppExports.R b/R/RcppExports.R index 51c7a227d9..c72e008d26 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -1,62 +1,6 @@ # Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 -has_metadata_simple <- function(array_name, key) { - .Call(`_tiledb_has_metadata_simple`, array_name, key) -} - -has_metadata_ptr <- function(array, key) { - .Call(`_tiledb_has_metadata_ptr`, array, key) -} - -num_metadata_simple <- function(array_name) { - .Call(`_tiledb_num_metadata_simple`, array_name) -} - -num_metadata_ptr <- function(array) { - .Call(`_tiledb_num_metadata_ptr`, array) -} - -get_metadata_simple <- function(array_name, key) { - .Call(`_tiledb_get_metadata_simple`, array_name, key) -} - -get_metadata_ptr <- function(array, key) { - .Call(`_tiledb_get_metadata_ptr`, array, key) -} - -put_metadata_simple <- function(array_name, key, obj) { - .Call(`_tiledb_put_metadata_simple`, array_name, key, obj) -} - -put_metadata_ptr <- function(array, key, obj) { - .Call(`_tiledb_put_metadata_ptr`, array, key, obj) -} - -get_metadata_from_index_ptr <- function(array, idx) { - .Call(`_tiledb_get_metadata_from_index_ptr`, array, idx) -} - -get_metadata_from_index_simple <- function(array_name, idx) { - .Call(`_tiledb_get_metadata_from_index_simple`, array_name, idx) -} - -get_all_metadata_simple <- function(array_name) { - .Call(`_tiledb_get_all_metadata_simple`, array_name) -} - -get_all_metadata_ptr <- function(array) { - .Call(`_tiledb_get_all_metadata_ptr`, array) -} - -delete_metadata_simple <- function(array_name, key) { - .Call(`_tiledb_delete_metadata_simple`, array_name, key) -} - -delete_metadata_ptr <- function(array, key) { - .Call(`_tiledb_delete_metadata_ptr`, array, key) -} - tiledb_datatype_R_type <- function(datatype) { .Call(`_tiledb_tiledb_datatype_R_type`, datatype) } @@ -389,8 +333,28 @@ libtiledb_array_nonempty_domain <- function(array) { .Call(`_tiledb_libtiledb_array_nonempty_domain`, array) } -libtiledb_array_consolidate <- function(ctx, uri) { - .Call(`_tiledb_libtiledb_array_consolidate`, ctx, uri) +libtiledb_array_consolidate <- function(ctx, uri, cfgptr = NULL) { + invisible(.Call(`_tiledb_libtiledb_array_consolidate`, ctx, uri, cfgptr)) +} + +libtiledb_array_put_metadata <- function(array, key, obj) { + .Call(`_tiledb_libtiledb_array_put_metadata`, array, key, obj) +} + +libtiledb_array_get_metadata_num <- function(array) { + .Call(`_tiledb_libtiledb_array_get_metadata_num`, array) +} + +libtiledb_array_get_metadata_from_index <- function(array, idx) { + .Call(`_tiledb_libtiledb_array_get_metadata_from_index`, array, idx) +} + +libtiledb_array_get_metadata_list <- function(array) { + .Call(`_tiledb_libtiledb_array_get_metadata_list`, array) +} + +libtiledb_array_delete_metadata <- function(array, key) { + invisible(.Call(`_tiledb_libtiledb_array_delete_metadata`, array, key)) } libtiledb_query <- function(ctx, array, type) { diff --git a/R/SparseArray.R b/R/SparseArray.R index a2f80741be..77ce5f7178 100644 --- a/R/SparseArray.R +++ b/R/SparseArray.R @@ -4,7 +4,7 @@ #' @slot uri A character despription #' @slot as.data.frame A logical value #' @slot ptr External pointer to the underlying implementation -#' @exportClass "tiledb_sparse" +#' @exportClass tiledb_sparse setClass("tiledb_sparse", slots = list(ctx = "tiledb_ctx", uri = "character", as.data.frame = "logical", ptr = "externalptr")) diff --git a/TileDB-R.Rproj b/TileDB-R.Rproj index aa9a2dad9e..eb6db5d907 100644 --- a/TileDB-R.Rproj +++ b/TileDB-R.Rproj @@ -14,4 +14,4 @@ LaTeX: pdfLaTeX BuildType: Package PackageInstallArgs: --no-multiarch --with-keep.source -PackageRoxygenize: rd,collate,namespace +PackageRoxygenize: rd,namespace diff --git a/inst/notebooks/documentation.Rmd b/inst/notebooks/documentation.Rmd index 00080596c3..2e11ab92ae 100644 --- a/inst/notebooks/documentation.Rmd +++ b/inst/notebooks/documentation.Rmd @@ -38,7 +38,7 @@ create_array <- function(array_name) { tiledb_dim("cols", c(1L, 4L), 4L, "INT32"))) # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. - schema <- tiledb_array_schema(dom, attrs = c(tiledb_attr("a", type = "INT32"))) + schema <- tiledb_array_schema(dom, attrs = tiledb_attr("a", type = "INT32")) # Create the (empty) array on disk. tiledb_array_create(array_name, schema) @@ -71,8 +71,8 @@ create_array <- function(array_name) { dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"), tiledb_dim("cols", c(1L, 4L), 4L, "INT32"))) - # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. - schema = tiledb_array_schema(dom, attrs=c(tiledb_attr("a", type = "INT32")), sparse = TRUE) + # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. + schema = tiledb_array_schema(dom, attrs=tiledb_attr("a", type = "INT32"), sparse = TRUE) # Create the (empty) array on disk. tiledb_array_create(array_name, schema) @@ -90,6 +90,10 @@ write_array <- function(array_name) { create_array(urisparse) write_array(urisparse) +close_and_reopen <- function(arr, txt) { + res <- tiledb:::libtiledb_array_close(arr@ptr) + res <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, txt) +} ``` @@ -147,7 +151,7 @@ comp <- tiledb_filter("GZIP") tiledb_filter_set_option(comp,"COMPRESSION_LEVEL", 10) # Create a filter list with the compressor -filter_list <- tiledb_filter_list(c(comp)) +filter_list <- tiledb_filter_list(comp) # Create attribute with the filter list attr <- tiledb_attr("attr", "INT32", filter_list = filter_list) @@ -324,7 +328,7 @@ d1 <- tiledb_dim(domain = c(1L, 5L)) d2 <- tiledb_dim(domain = c(1L, 5L)) dom <- tiledb_domain(c(d1, d2)) val <- tiledb_attr("val", type = "INT32") -sch <- tiledb_array_schema(dom, c(val), sparse=TRUE) +sch <- tiledb_array_schema(dom, val, sparse=TRUE) tiledb_array_create(tmp, sch) @@ -377,7 +381,7 @@ attr <- tiledb_attr("a", type = r_to_tiledb_type(vec)) ## set to two values per cell tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 2) -sch <- tiledb_array_schema(dom, c(attr)) +sch <- tiledb_array_schema(dom, attr) tiledb_array_create(uridensefix, sch) ctx <- tiledb_ctx() @@ -730,8 +734,11 @@ v ### Writing Array Metadata ```{r writemetadata} -res <- tiledb_put_metadata(uridense, "aaa", 100L) -res <- tiledb_put_metadata(uridense, "bb", c(1.1, 2.2)) +arr <- tiledb_dense(uridense) +close_and_reopen(arr, "WRITE") +res <- tiledb_put_metadata(arr, "aaa", 100L) +res <- tiledb_put_metadata(arr, "bb", c(1.1, 2.2)) +invisible(tiledb:::libtiledb_array_close(arr@ptr)) ``` ### Reading Array Metadata @@ -739,18 +746,21 @@ res <- tiledb_put_metadata(uridense, "bb", c(1.1, 2.2)) One can read by key: ```{r readmetadata} -tiledb_get_metadata(uridense, "aaa") +close_and_reopen(arr, "READ") +tiledb_get_metadata(arr, "aaa") ``` Or one can retrieve all metadata at once: ```{r readmetadataall} -md <- tiledb_get_all_metadata(uridense) +md <- tiledb_get_all_metadata(arr) print(md) ``` ### Deleting Array Metadata ```{r deletemetadata} -res <- tiledb_delete_metadata(uridense, "aaa") +close_and_reopen(arr, "WRITE") +res <- tiledb_delete_metadata(arr, "aaa") + ``` diff --git a/inst/notebooks/documentation.html b/inst/notebooks/documentation.html index 73ac6257ac..5aed8a07a1 100644 --- a/inst/notebooks/documentation.html +++ b/inst/notebooks/documentation.html @@ -1701,7 +1701,7 @@

Prelimaries

tiledb_dim("cols", c(1L, 4L), 4L, "INT32"))) # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. - schema <- tiledb_array_schema(dom, attrs = c(tiledb_attr("a", type = "INT32"))) + schema <- tiledb_array_schema(dom, attrs = tiledb_attr("a", type = "INT32")) # Create the (empty) array on disk. tiledb_array_create(array_name, schema) @@ -1718,7 +1718,7 @@

Prelimaries

} create_array(uridense) -
## [1] "/tmp/Rtmpz7aolS/dense"
+
## [1] "/tmp/RtmpoOK3ly/dense"
write_array(uridense)
 
 
@@ -1735,8 +1735,8 @@ 

Prelimaries

dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"), tiledb_dim("cols", c(1L, 4L), 4L, "INT32"))) - # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. - schema = tiledb_array_schema(dom, attrs=c(tiledb_attr("a", type = "INT32")), sparse = TRUE) + # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer. + schema = tiledb_array_schema(dom, attrs=tiledb_attr("a", type = "INT32"), sparse = TRUE) # Create the (empty) array on disk. tiledb_array_create(array_name, schema) @@ -1752,8 +1752,13 @@

Prelimaries

} create_array(urisparse)
-
## [1] "/tmp/Rtmpz7aolS/sparse"
-
write_array(urisparse)
+
## [1] "/tmp/RtmpoOK3ly/sparse"
+
write_array(urisparse)
+
+close_and_reopen <- function(arr, txt) {
+  res <- tiledb:::libtiledb_array_close(arr@ptr)
+  res <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, txt)
+}

API Usage

@@ -1796,7 +1801,7 @@

Setting a Compressor

tiledb_filter_set_option(comp,"COMPRESSION_LEVEL", 10) # Create a filter list with the compressor -filter_list <- tiledb_filter_list(c(comp)) +filter_list <- tiledb_filter_list(comp) # Create attribute with the filter list attr <- tiledb_attr("attr", "INT32", filter_list = filter_list) @@ -1883,7 +1888,7 @@

Creating Encrypted Arrays

# shortcut: borrow schema from dense array; could create schema too schema <- schema(tiledb_dense(uridense)) tiledb:::libtiledb_array_create_with_key(uridensewkey, schema@ptr, encryption_key) -
## [1] "/tmp/Rtmpz7aolS/densewkey"
+
## [1] "/tmp/RtmpoOK3ly/densewkey"
##TODO: R support
@@ -1944,9 +1949,9 @@

Writing Sparse Cells

d2 <- tiledb_dim(domain = c(1L, 5L)) dom <- tiledb_domain(c(d1, d2)) val <- tiledb_attr("val", type = "INT32") -sch <- tiledb_array_schema(dom, c(val), sparse=TRUE) +sch <- tiledb_array_schema(dom, val, sparse=TRUE) tiledb_array_create(tmp, sch) -
## [1] "/tmp/Rtmpz7aolS/sparse"
+
## [1] "/tmp/RtmpoOK3ly/sparse"
# Prepare some data
 data <- c(3L, 4L, 1L, 2L)
 
@@ -1986,9 +1991,9 @@ 

Fixed-length Attributes

## set to two values per cell tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 2) -sch <- tiledb_array_schema(dom, c(attr)) +sch <- tiledb_array_schema(dom, attr) tiledb_array_create(uridensefix, sch)
-
## [1] "/tmp/Rtmpz7aolS/densefix"
+
## [1] "/tmp/RtmpoOK3ly/densefix"
ctx <- tiledb_ctx()
 arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensefix, "WRITE")
 subarr <- c(1L,4L, 1L,4L)
@@ -2027,7 +2032,7 @@ 

Var-length Attributes

## Create the (empty) array on disk. tiledb:::libtiledb_array_create(uridensevar, schptr)
-
## [1] "/tmp/Rtmpz7aolS/densevar"
+
## [1] "/tmp/RtmpoOK3ly/densevar"
data <- "abbcccddeeefghhhijjjkklmnoop";
 offsets <- c(0L, 1L, 3L, 6L, 8L, 11L, 12L, 13L, 16L, 17L, 20L, 22L, 23L, 24L, 25L, 27L)
 
@@ -2040,7 +2045,7 @@ 

Var-length Attributes

qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr) qryptr <- tiledb:::libtiledb_query_submit(qryptr) tiledb:::libtiledb_array_close(arrptr)
-
## <pointer: 0x55a211bf8a20>
+
## <pointer: 0x55d5011abad0>
#TODO Higher-level R support
@@ -2293,9 +2298,8 @@

Result Estimation

Time Traveling

ctx <- tiledb_ctx()
 tstamp <- Sys.time() - 1.0; # one seconds ago (as the arrays created here are in temp.files)
-arrptr <- tiledb:::libtiledb_array_open_at(ctx@ptr, uridense, "READ", tstamp)
-
## [1] "2020-03-09 12:18:22.387257 CDT"
-
subarr <- c(1L,2L, 2L,4L)
+arrptr <- tiledb:::libtiledb_array_open_at(ctx@ptr, uridense, "READ", tstamp)
+subarr <- c(1L,2L, 2L,4L)
 qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
 qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
 qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
@@ -2320,23 +2324,28 @@ 

Configuration

Array Metadata

Writing Array Metadata

-
res <- tiledb_put_metadata(uridense, "aaa", 100L)
-res <- tiledb_put_metadata(uridense, "bb", c(1.1, 2.2))
+
arr <- tiledb_dense(uridense)
+close_and_reopen(arr, "WRITE")
+res <- tiledb_put_metadata(arr, "aaa", 100L)
+res <- tiledb_put_metadata(arr, "bb", c(1.1, 2.2))
+invisible(tiledb:::libtiledb_array_close(arr@ptr))

Reading Array Metadata

One can read by key:

-
tiledb_get_metadata(uridense, "aaa")
+
close_and_reopen(arr, "READ")
+tiledb_get_metadata(arr, "aaa")
## [1] 100

Or one can retrieve all metadata at once:

-
md <- tiledb_get_all_metadata(uridense)
+
md <- tiledb_get_all_metadata(arr)
 print(md)
## aaa: 100
 ## bb:  1.1, 2.2

Deleting Array Metadata

-
res <- tiledb_delete_metadata(uridense, "aaa")
+
close_and_reopen(arr, "WRITE")
+res <- tiledb_delete_metadata(arr, "aaa")
diff --git a/inst/notebooks/documentation.nb.html b/inst/notebooks/documentation.nb.html index 313263b9bf..af413f7bc6 100644 --- a/inst/notebooks/documentation.nb.html +++ b/inst/notebooks/documentation.nb.html @@ -1890,12 +1890,93 @@

Prelimaries

We will the two basic examples for a dense and sparse array simply to create array data on disk to refer to later in examples that follow.

- -
create_array(uridense)
+ +
library(tiledb)
+
+tdir <- tempdir()
+uridense <- file.path(tdir, "dense")
+uridensefix <- file.path(tdir, "densefix")
+uridensevar <- file.path(tdir, "densevar")
+
+create_array <- function(array_name) {
+    # Check if the array already exists.
+    if (tiledb_object_type(array_name) == "ARRAY") {
+        message("Array already exists.")
+        return(invisible(NULL))
+    }
+
+    # The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
+    dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
+                                  tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))
+
+    # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer.
+    schema <- tiledb_array_schema(dom, attrs = tiledb_attr("a", type = "INT32"))
+
+    # Create the (empty) array on disk.
+    tiledb_array_create(array_name, schema)
+}
+
+write_array <- function(array_name) {
+    data <- array(c(c(1L, 5L, 9L, 13L),
+                    c(2L, 6L, 10L, 14L),
+                    c(3L, 7L, 11L, 15L),
+                    c(4L, 8L, 12L, 16L)), dim = c(4,4))
+    # Open the array and write to it.
+    A <- tiledb_dense(uri = array_name)
+    A[] <- data
+}
+
+create_array(uridense)
- -
[1] "/tmp/RtmpaoIiNJ/dense"
+ +
[1] "/tmp/RtmpMiNRCx/dense"
+ +
write_array(uridense)
+
+
+urisparse <- file.path(tdir, "sparse")
+
+create_array <- function(array_name) {
+    # Check if the array already exists.
+    if (tiledb_object_type(array_name) == "ARRAY") {
+        message("Array already exists.")
+        return(invisible(NULL))
+    }
+
+    # The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
+    dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
+                                  tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))
+
+    # The array will be dense with a single attribute "a" so each (i,j) cell can store an integer.
+    schema = tiledb_array_schema(dom, attrs=tiledb_attr("a", type = "INT32"), sparse = TRUE)
+
+    # Create the (empty) array on disk.
+    tiledb_array_create(array_name, schema)
+}
+
+write_array <- function(array_name) {
+    I <- c(1, 2, 2)
+    J <- c(1, 4, 3)
+    data <- c(1L, 2L, 3L)
+    # Open the array and write to it.
+    A <- tiledb_sparse(uri = array_name)
+    A[I, J] <- data
+}
+
+create_array(urisparse)
+ + +
[1] "/tmp/RtmpMiNRCx/sparse"
+ + +
write_array(urisparse)
+
+close_and_reopen <- function(arr, txt) {
+  res <- tiledb:::libtiledb_array_close(arr@ptr)
+  res <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, txt)
+}
+ @@ -1908,11 +1989,11 @@

Create Dimension

-
library(tiledb)
-
-# Create dimension
-# In C++: Dimension::create<T>(...)
-dim <- tiledb_dim("dim", c(1L, 4L), 2L, "INT32")
+
library(tiledb)
+
+# Create dimension
+# In C++: Dimension::create<T>(...)
+dim <- tiledb_dim("dim", c(1L, 4L), 2L, "INT32")
@@ -1922,15 +2003,15 @@

Create Array Domain

-
library(tiledb)
-
-#  .. create dimensions `dim1`, `dim2`
-dim1 <- tiledb_dim("dim1", c(1L, 4L), 2L, "INT32")
-dim2 <- tiledb_dim("dim2", c(1L, 2L), 2L, "INT32")
-
-# Create domain with two dimensions
-# In C++: domain.add_dimensions(dim1).add_dimension(dim2)
-dom <- tiledb_domain(dims = c(dim1, dim2))
+
library(tiledb)
+
+#  .. create dimensions `dim1`, `dim2`
+dim1 <- tiledb_dim("dim1", c(1L, 4L), 2L, "INT32")
+dim2 <- tiledb_dim("dim2", c(1L, 2L), 2L, "INT32")
+
+# Create domain with two dimensions
+# In C++: domain.add_dimensions(dim1).add_dimension(dim2)
+dom <- tiledb_domain(dims = c(dim1, dim2))
@@ -1940,21 +2021,21 @@

Creating Attributes

-
# Create attribute
-# In C++: Attribute::create<T>(ctx, "attr")
-attr <- tiledb_attr("attr", "INT32")
+
# Create attribute
+# In C++: Attribute::create<T>(ctx, "attr")
+attr <- tiledb_attr("attr", "INT32")
-
# We can also set the number of attributes to a value other than one
-tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 3)
-
-# And we can set the a variable number of attributes (using NA to select variable size)
-tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
-## TODO: R function for level setter
+
# We can also set the number of attributes to a value other than one
+tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 3)
+
+# And we can set the a variable number of attributes (using NA to select variable size)
+tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
+## TODO: R function for level setter
@@ -1962,15 +2043,15 @@

Creating Attributes

Setting a Compressor

- -
comp <- tiledb_filter("GZIP")
-tiledb_filter_set_option(comp,"COMPRESSION_LEVEL", 10)
-
-# Create a filter list with the compressor
-filter_list <- tiledb_filter_list(c(comp))
-
-# Create attribute with the filter list
-attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)
+ +
comp <- tiledb_filter("GZIP")
+tiledb_filter_set_option(comp,"COMPRESSION_LEVEL", 10)
+
+# Create a filter list with the compressor
+filter_list <- tiledb_filter_list(comp)
+
+# Create attribute with the filter list
+attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)
@@ -1980,15 +2061,15 @@

Setting Other Filters

-
# Create filters
-f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
-f2 <- tiledb_filter("ZSTD")
-
-# Create a filter list with the two filters
-filter_list <- tiledb_filter_list(c(f1,f2))
-
-# Create attribute with the filter list
-attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)
+
# Create filters
+f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
+f2 <- tiledb_filter("ZSTD")
+
+# Create a filter list with the two filters
+filter_list <- tiledb_filter_list(c(f1,f2))
+
+# Create attribute with the filter list
+attr <- tiledb_attr("attr", "INT32", filter_list = filter_list)
@@ -1998,8 +2079,8 @@

Setting the Tile Chunk Size

-
# ... create filter list
-set_max_chunk_size(filter_list, 10000)
+
# ... create filter list
+set_max_chunk_size(filter_list, 10000)
@@ -2010,14 +2091,14 @@

Creating the Array Schema

-
# ... create domain dom
-attr1 <- tiledb_attr("attr1", "INT32", filter_list = filter_list)
-attr2 <- tiledb_attr("attr2", "FLOAT64", filter_list = filter_list)
-
-# Create a dense array
-schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = FALSE)
-# Or, create a spaese array
-# schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = TRUE)
+
# ... create domain dom
+attr1 <- tiledb_attr("attr1", "INT32", filter_list = filter_list)
+attr2 <- tiledb_attr("attr2", "FLOAT64", filter_list = filter_list)
+
+# Create a dense array
+schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = FALSE)
+# Or, create a spaese array
+# schema <- tiledb_array_schema(dom, c(attr1, attr2), sparse = TRUE)
@@ -2026,13 +2107,13 @@

Setting the Tile and Cell Order

-
# ... create domain dom
-# ... create attributes attr1, attr2
-
-# The tile and order can be "ROW_MAJOR" or "COL_MAJOR"
-schema <- tiledb_array_schema(dom, c(attr1, attr2),
-                              cell_order = "COL_MAJOR",
-                              tile_order = "ROW_MAJOR")
+
# ... create domain dom
+# ... create attributes attr1, attr2
+
+# The tile and order can be "ROW_MAJOR" or "COL_MAJOR"
+schema <- tiledb_array_schema(dom, c(attr1, attr2),
+                              cell_order = "COL_MAJOR",
+                              tile_order = "ROW_MAJOR")
@@ -2042,14 +2123,14 @@

Setting the Data Tile Capacity

-
tiledb:::libtiledb_array_schema_set_capacity(schema@ptr, 100000)
-tiledb:::libtiledb_array_schema_get_capacity(schema@ptr)
+
tiledb:::libtiledb_array_schema_set_capacity(schema@ptr, 100000)
+tiledb:::libtiledb_array_schema_get_capacity(schema@ptr)
[1] 100000
-
## TODO R function for accessor
+
## TODO R function for accessor
@@ -2059,18 +2140,18 @@

Setting Coordinate and Offset Filters

-
# ... create domain dom
-# ... create attributes attr1, attr2
-# ... create filter lists fl1, fl2, similar to attributes
-f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
-f2 <- tiledb_filter("ZSTD")
-fl1 <- tiledb_filter_list(c(f1))
-fl2 <- tiledb_filter_list(c(f2))
-
-# Create the schema setting the coordinates and offsets filter lists
-schema <- tiledb_array_schema(dom, c(attr1, attr2),
-                              coords_filter_list = fl1,
-                              offsets_filter_list = fl2)
+
# ... create domain dom
+# ... create attributes attr1, attr2
+# ... create filter lists fl1, fl2, similar to attributes
+f1 <- tiledb_filter("BIT_WIDTH_REDUCTION")
+f2 <- tiledb_filter("ZSTD")
+fl1 <- tiledb_filter_list(c(f1))
+fl2 <- tiledb_filter_list(c(f2))
+
+# Create the schema setting the coordinates and offsets filter lists
+schema <- tiledb_array_schema(dom, c(attr1, attr2),
+                              coords_filter_list = fl1,
+                              offsets_filter_list = fl2)
@@ -2080,8 +2161,8 @@

Checking Correctness

-
tiledb:::libtiledb_array_schema_check(schema@ptr)
-## TODO: R function for access
+
tiledb:::libtiledb_array_schema_check(schema@ptr)
+## TODO: R function for access
@@ -2092,10 +2173,10 @@

Creating the Array

-
# ... create array schema
-
-# Create the array
-tiledb_array_create(uridense, schema)
+
# ... create array schema
+
+# Create the array
+tiledb_array_create(uridense, schema)
@@ -2105,19 +2186,19 @@

Creating Encrypted Arrays

-
encryption_key <- "0123456789abcdeF0123456789abcdeF"
-uridensewkey <- file.path(tdir, "densewkey")
-if (dir.exists(uridensewkey)) unlink(uridensewkey, recursive=TRUE)
-
-# shortcut: borrow schema from dense array; could create schema too
-schema <- schema(tiledb_dense(uridense))
-tiledb:::libtiledb_array_create_with_key(uridensewkey, schema@ptr, encryption_key)
+
encryption_key <- "0123456789abcdeF0123456789abcdeF"
+uridensewkey <- file.path(tdir, "densewkey")
+if (dir.exists(uridensewkey)) unlink(uridensewkey, recursive=TRUE)
+
+# shortcut: borrow schema from dense array; could create schema too
+schema <- schema(tiledb_dense(uridense))
+tiledb:::libtiledb_array_create_with_key(uridensewkey, schema@ptr, encryption_key)
- -
[1] "/tmp/RtmppsnBrT/densewkey"
+ +
[1] "/tmp/RtmpMiNRCx/densewkey"
-
##TODO: R support
+
##TODO: R support
@@ -2130,33 +2211,33 @@

Writing in Dense Subarrays

-
## prepare a larger 5 x 5 to embed into
-tmp <- tempfile()
-d1  <- tiledb_dim(domain = c(1L, 5L))
-d2  <- tiledb_dim(domain = c(1L, 5L))
-dom <- tiledb_domain(c(d1, d2))
-val <- tiledb_attr(name="val", type = "INT32")
-sch <- tiledb_array_schema(dom, c(val))
-tiledb_array_create(tmp, sch)
-
-dat <- matrix(as.integer(rnorm(25)*100), 5, 5)
-arr <- tiledb_dense(tmp, as.data.frame=FALSE)
-arr[] <- dat
-
-
-# Prepare a 2x3 dense array
-# Contrary to Python, R by default stores arrays in col-major order
-data <-  array(c(1L, 4L, 2L, 5L, 3L, 6L), dim=c(2,3))
-
-# Prepare the [1,2] x [2,4] subarray to write to
-I <- c(1:2)
-J <- c(2:4)
-
-# Open the array and write the data to it
-A <- tiledb_dense(uri = tmp)
-A[I, J] <- data
-
-unlink(tmp, recursive=TRUE)
+
## prepare a larger 5 x 5 to embed into
+tmp <- tempfile()
+d1  <- tiledb_dim(domain = c(1L, 5L))
+d2  <- tiledb_dim(domain = c(1L, 5L))
+dom <- tiledb_domain(c(d1, d2))
+val <- tiledb_attr(name="val", type = "INT32")
+sch <- tiledb_array_schema(dom, c(val))
+tiledb_array_create(tmp, sch)
+
+dat <- matrix(as.integer(rnorm(25)*100), 5, 5)
+arr <- tiledb_dense(tmp, as.data.frame=FALSE)
+arr[] <- dat
+
+
+# Prepare a 2x3 dense array
+# Contrary to Python, R by default stores arrays in col-major order
+data <-  array(c(1L, 4L, 2L, 5L, 3L, 6L), dim=c(2,3))
+
+# Prepare the [1,2] x [2,4] subarray to write to
+I <- c(1:2)
+J <- c(2:4)
+
+# Open the array and write the data to it
+A <- tiledb_dense(uri = tmp)
+A[I, J] <- data
+
+unlink(tmp, recursive=TRUE)
@@ -2165,19 +2246,19 @@

Basic Writing using Low-Level Code

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "WRITE")
-
-## data: simple (integer sequence) of 1:16 times 10
-vec <- 1:16 * 10L
-subarr <- c(1L,4L, 1L,4L)
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-res <- tiledb:::libtiledb_array_close(arrptr)
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "WRITE")
+
+## data: simple (integer sequence) of 1:16 times 10
+vec <- 1:16 * 10L
+subarr <- c(1L,4L, 1L,4L)
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+res <- tiledb:::libtiledb_array_close(arrptr)
@@ -2187,30 +2268,30 @@

Basic Writing using Low-Level Code

Writing Sparse Cells

- -
tmp <- urisparse
-unlink(tmp, recursive=TRUE)
-
-d1  <- tiledb_dim(domain = c(1L, 5L))
-d2  <- tiledb_dim(domain = c(1L, 5L))
-dom <- tiledb_domain(c(d1, d2))
-val <- tiledb_attr("val", type = "INT32")
-sch <- tiledb_array_schema(dom, c(val), sparse=TRUE)
-tiledb_array_create(tmp, sch)
+ +
tmp <- urisparse
+unlink(tmp, recursive=TRUE)
+
+d1  <- tiledb_dim(domain = c(1L, 5L))
+d2  <- tiledb_dim(domain = c(1L, 5L))
+dom <- tiledb_domain(c(d1, d2))
+val <- tiledb_attr("val", type = "INT32")
+sch <- tiledb_array_schema(dom, val, sparse=TRUE)
+tiledb_array_create(tmp, sch)
- -
[1] "/tmp/RtmppsnBrT/sparse"
+ +
[1] "/tmp/RtmpMiNRCx/sparse"
-
# Prepare some data
-data <- c(3L, 4L, 1L, 2L)
-
-I <- c(3, 4, 1, 2)
-J <- c(3, 4, 2, 1)
-
-# Open the array and write the data to it
-A <- tiledb_sparse(uri = tmp)
-A[I, J] <- data
+
# Prepare some data
+data <- c(3L, 4L, 1L, 2L)
+
+I <- c(3, 4, 1, 2)
+J <- c(3, 4, 2, 1)
+
+# Open the array and write the data to it
+A <- tiledb_sparse(uri = tmp)
+A[I, J] <- data
@@ -2220,20 +2301,20 @@

Writing Encrypted Arrays

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "WRITE", encryption_key)
-
-## data: simple (integer sequence) of 1:16 times 10
-vec <- 1:16 * 10L
-subarr <- c(1L,4L, 1L,4L)
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-res <- tiledb:::libtiledb_array_close(arrptr)
-# TODO Higher-level R support
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "WRITE", encryption_key)
+
+## data: simple (integer sequence) of 1:16 times 10
+vec <- 1:16 * 10L
+subarr <- c(1L,4L, 1L,4L)
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+res <- tiledb:::libtiledb_array_close(arrptr)
+# TODO Higher-level R support
@@ -2242,36 +2323,36 @@

Writing Encrypted Arrays

Fixed-length Attributes

- -
if (dir.exists(uridensefix)) unlink(uridensefix, recursive=TRUE)
-d1  <- tiledb_dim(domain = c(1L, 4L))
-d2  <- tiledb_dim(domain = c(1L, 4L))
-dom <- tiledb_domain(c(d1, d2))
-
-vec <- 1:32 * 10L
-attr <- tiledb_attr("a", type = r_to_tiledb_type(vec))
-
-## set to two values per cell
-tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 2)
-sch <- tiledb_array_schema(dom, c(attr))
-tiledb_array_create(uridensefix, sch)
+ +
if (dir.exists(uridensefix)) unlink(uridensefix, recursive=TRUE)
+d1  <- tiledb_dim(domain = c(1L, 4L))
+d2  <- tiledb_dim(domain = c(1L, 4L))
+dom <- tiledb_domain(c(d1, d2))
+
+vec <- 1:32 * 10L
+attr <- tiledb_attr("a", type = r_to_tiledb_type(vec))
+
+## set to two values per cell
+tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, 2)
+sch <- tiledb_array_schema(dom, attr)
+tiledb_array_create(uridensefix, sch)
- -
[1] "/tmp/RtmppsnBrT/densefix"
+ +
[1] "/tmp/RtmpMiNRCx/densefix"
-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensefix, "WRITE")
-subarr <- c(1L,4L, 1L,4L)
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-res <- tiledb:::libtiledb_array_close(arrptr)
-
-#TODO Higher-level R support
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensefix, "WRITE")
+subarr <- c(1L,4L, 1L,4L)
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+res <- tiledb:::libtiledb_array_close(arrptr)
+
+#TODO Higher-level R support
@@ -2281,52 +2362,52 @@

Var-length Attributes

-
if (dir.exists(uridensevar)) unlink(uridensevar, recursive=TRUE)
-## Define array
-## The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
-dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
-                              tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))
-
-
-attr <- tiledb_attr("a1", type = "CHAR")
-## set to variable length
-tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
-
-## now set the schema
-ctx <- tiledb_ctx()
-schptr <- tiledb:::libtiledb_array_schema_create(ctx@ptr, "DENSE")
-tiledb:::libtiledb_array_schema_set_domain(schptr, dom@ptr)
-tiledb:::libtiledb_array_schema_set_cell_order(schptr, "ROW_MAJOR")
-tiledb:::libtiledb_array_schema_set_tile_order(schptr, "ROW_MAJOR")
-tiledb:::libtiledb_array_schema_add_attribute(schptr, attr@ptr)
-
-
-
-## Create the (empty) array on disk.
-tiledb:::libtiledb_array_create(uridensevar, schptr)
+
if (dir.exists(uridensevar)) unlink(uridensevar, recursive=TRUE)
+## Define array
+## The array will be 4x4 with dimensions "rows" and "cols", with domain [1,4].
+dom <- tiledb_domain(dims = c(tiledb_dim("rows", c(1L, 4L), 4L, "INT32"),
+                              tiledb_dim("cols", c(1L, 4L), 4L, "INT32")))
+
+
+attr <- tiledb_attr("a1", type = "CHAR")
+## set to variable length
+tiledb:::libtiledb_attribute_set_cell_val_num(attr@ptr, NA)
+
+## now set the schema
+ctx <- tiledb_ctx()
+schptr <- tiledb:::libtiledb_array_schema_create(ctx@ptr, "DENSE")
+tiledb:::libtiledb_array_schema_set_domain(schptr, dom@ptr)
+tiledb:::libtiledb_array_schema_set_cell_order(schptr, "ROW_MAJOR")
+tiledb:::libtiledb_array_schema_set_tile_order(schptr, "ROW_MAJOR")
+tiledb:::libtiledb_array_schema_add_attribute(schptr, attr@ptr)
+
+
+
+## Create the (empty) array on disk.
+tiledb:::libtiledb_array_create(uridensevar, schptr)
- -
[1] "/tmp/RtmppsnBrT/densevar"
+ +
[1] "/tmp/RtmpMiNRCx/densevar"
-
data <- "abbcccddeeefghhhijjjkklmnoop";
-offsets <- c(0L, 1L, 3L, 6L, 8L, 11L, 12L, 13L, 16L, 17L, 20L, 22L, 23L, 24L, 25L, 27L)
-
-ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "WRITE")
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-
-bufptr <- tiledb:::libtiledb_query_buffer_var_char_create(offsets, data)
-qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-tiledb:::libtiledb_array_close(arrptr)
+
data <- "abbcccddeeefghhhijjjkklmnoop";
+offsets <- c(0L, 1L, 3L, 6L, 8L, 11L, 12L, 13L, 16L, 17L, 20L, 22L, 23L, 24L, 25L, 27L)
+
+ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "WRITE")
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "WRITE")
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+
+bufptr <- tiledb:::libtiledb_query_buffer_var_char_create(offsets, data)
+qryptr <- tiledb:::libtiledb_query_set_buffer_var_char(qryptr, "a1", bufptr)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+tiledb:::libtiledb_array_close(arrptr)
- -
<pointer: 0x7fb5fc018dc0>
+ +
<pointer: 0x7fd6a40137a0>
-
#TODO Higher-level R support
+
#TODO Higher-level R support
@@ -2336,12 +2417,12 @@

Getting the Fragment Info

-
## continuing from previous example on dense variable length array
-## (but this works of course with any array after a write is needed
-numfrag <- tiledb:::libtiledb_query_get_fragment_num(qryptr)
-uritxt <- tiledb:::libtiledb_query_get_fragment_uri(qryptr, 0)
-
-##TODO Higher-level R support
+
## continuing from previous example on dense variable length array
+## (but this works of course with any array after a write is needed
+numfrag <- tiledb:::libtiledb_query_get_fragment_num(qryptr)
+uritxt <- tiledb:::libtiledb_query_get_fragment_uri(qryptr, 0)
+
+##TODO Higher-level R support
@@ -2354,11 +2435,11 @@

Reading the Array Schema

-
array_name <- urisparse
-A <- tiledb_sparse(uri = array_name)
-# can also load dense
-sch <- schema(A)
-# can also open encrypted arrays with key
+
array_name <- urisparse
+A <- tiledb_sparse(uri = array_name)
+# can also load dense
+sch <- schema(A)
+# can also open encrypted arrays with key
@@ -2367,45 +2448,45 @@

Inspecting the array schema

-
array_name <- urisparse
-
-# Get array schema
-A <- tiledb_sparse(uri = array_name)
-# or use tiledb_dense(uri = array_name) for dense
-schema <- schema(A)
-
-# Get array type
-sparse <- is.sparse(schema)
-
-# Get tile capacity
-tiledb:::libtiledb_array_schema_get_capacity(sch@ptr)
+
array_name <- urisparse
+
+# Get array schema
+A <- tiledb_sparse(uri = array_name)
+# or use tiledb_dense(uri = array_name) for dense
+schema <- schema(A)
+
+# Get array type
+sparse <- is.sparse(schema)
+
+# Get tile capacity
+tiledb:::libtiledb_array_schema_get_capacity(sch@ptr)
[1] 10000
-
# TODO: R accessor for tile
-
-# Get tile order
-t_order <- tile_order(schema)
-
-# Get cell order
-c_order <- cell_order(schema)
-
-# Get coordinates and offset filter list
-reslist <- filter_list(schema)
-
-# Get the array domain
-dom <- domain(schema)
-
-# Get all attributes as list
-attrs <- attrs(schema)
-
-# Get attribute from name
-attr <- attrs(schema, "attr")
-
-# Dump the array schema in ASCII format to stdout
-show(schema)
+
# TODO: R accessor for tile
+
+# Get tile order
+t_order <- tile_order(schema)
+
+# Get cell order
+c_order <- cell_order(schema)
+
+# Get coordinates and offset filter list
+reslist <- filter_list(schema)
+
+# Get the array domain
+dom <- domain(schema)
+
+# Get all attributes as list
+attrs <- attrs(schema)
+
+# Get attribute from name
+attr <- attrs(schema, "attr")
+
+# Dump the array schema in ASCII format to stdout
+show(schema)
- Array type: sparse
@@ -2443,21 +2524,21 @@ 

Inspecting Domain

-
# ... get array schema
-# ... get domain from schema
-dom <- domain(schema)
-
-# Get the domain datatype (i.e., the datatype of all dimensions)
-type <- datatype(dom)
-
-# Get number of dimensions
-dim_num <- dim(dom)
-
-# Get all dimension
-dims <- dimensions(dom)
-
-# Dump the domain in ASCII format in the selected output
-show(dom)
+
# ... get array schema
+# ... get domain from schema
+dom <- domain(schema)
+
+# Get the domain datatype (i.e., the datatype of all dimensions)
+type <- datatype(dom)
+
+# Get number of dimensions
+dim_num <- dim(dom)
+
+# Get all dimension
+dims <- dimensions(dom)
+
+# Dump the domain in ASCII format in the selected output
+show(dom)
=== Domain ===
@@ -2481,26 +2562,26 @@ 

Inspecting Dimensions

-
# ... get array schema
-# ... get domain
-# ... get dimension by index or name
-
-#FIXME
-
-# Get dimension name
-dim_name <- name(dim)
-
-# Get dimension datatype
-dim_type <- datatype(dim)
-
-# Get dimension domain
-domain <- domain(dim)
-
-# Get tile extent
-tile_extent <- tile(dim)
-
-# Dump the dimension in ASCII format in the selected output
-show(dim)
+
# ... get array schema
+# ... get domain
+# ... get dimension by index or name
+
+#FIXME
+
+# Get dimension name
+dim_name <- name(dim)
+
+# Get dimension datatype
+dim_type <- datatype(dim)
+
+# Get dimension domain
+domain <- domain(dim)
+
+# Get tile extent
+tile_extent <- tile(dim)
+
+# Dump the dimension in ASCII format in the selected output
+show(dim)
@@ -2510,30 +2591,30 @@

Inspecting Attributes

-
# ... get array schema
-# ... get attribute by index or name
-
-stopifnot(is.null(attr))
-# Get attribute name
-attr_name <- name(attr)
-
-# Get attribute datatype
-attr_type <- datatype(attr)
-
-# Get filter list
-filter_list <- filter_list(attr)
-
-# Check if attribute is variable-length
-# variable length attribtues are not supported in R currently
-
-# Get number of values per cell
-num <- ncells(attr)
-
-# Get cell size for this attribute
-sz <-- tiledb:::libtiledb_attribute_get_cell_val(attr@ptr)
-
-# Dump the attribute in ASCII format in the selected output
-show(attr)
+
# ... get array schema
+# ... get attribute by index or name
+
+stopifnot(is.null(attr))
+# Get attribute name
+attr_name <- name(attr)
+
+# Get attribute datatype
+attr_type <- datatype(attr)
+
+# Get filter list
+filter_list <- filter_list(attr)
+
+# Check if attribute is variable-length
+# variable length attribtues are not supported in R currently
+
+# Get number of values per cell
+num <- ncells(attr)
+
+# Get cell size for this attribute
+sz <-- tiledb:::libtiledb_attribute_get_cell_val(attr@ptr)
+
+# Dump the attribute in ASCII format in the selected output
+show(attr)
@@ -2543,17 +2624,17 @@

Inspecting Filters

-
fl <- tiledb_filter_list()
-
-# get number of filter
-tiledb:::libtiledb_filter_list_get_nfilters(fl@ptr)
-
-# get max chunk size
-tiledb:::libtiledb_filter_list_get_max_chunk_size(fl@ptr)
-
-# get filter from index
-ind <- i
-tiledb:::libtiledb_filter_list_get_filter_from_index(fl@ptr, ind)
+
fl <- tiledb_filter_list()
+
+# get number of filter
+tiledb:::libtiledb_filter_list_get_nfilters(fl@ptr)
+
+# get max chunk size
+tiledb:::libtiledb_filter_list_get_max_chunk_size(fl@ptr)
+
+# get filter from index
+ind <- i
+tiledb:::libtiledb_filter_list_get_filter_from_index(fl@ptr, ind)
@@ -2564,18 +2645,18 @@

Basic Reading

-
# Create a TileDB context
-ctx <- tiledb_ctx()
-
-# Open a dense array
-A <- tiledb_dense(uri = uridense, ctx=ctx)
-
-# Or, open a sparse array
-# A <- tiledb_sparse(uri = "<array-uri>", ctx=ctx)
-
-# Slice only rows 1, 2 and cols 2, 3, 4
-data <- A[1:2, 2:4]
-show(data)
+
# Create a TileDB context
+ctx <- tiledb_ctx()
+
+# Open a dense array
+A <- tiledb_dense(uri = uridense, ctx=ctx)
+
+# Or, open a sparse array
+# A <- tiledb_sparse(uri = "<array-uri>", ctx=ctx)
+
+# Slice only rows 1, 2 and cols 2, 3, 4
+data <- A[1:2, 2:4]
+show(data)
     [,1] [,2] [,3]
@@ -2589,24 +2670,24 @@ 

Basic Reading using Low-Level Code

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
-## subarray of rows 1,2 and cols 2,3,4
-subarr <- c(1L,2L, 2L,4L)
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-v <- integer(6)  # reserve space
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-print(v)         # unformed array, no coordinates
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
+## subarray of rows 1,2 and cols 2,3,4
+subarr <- c(1L,2L, 2L,4L)
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+v <- integer(6)  # reserve space
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+print(v)         # unformed array, no coordinates
[1] 20 30 40 60 70 80
-
res <- tiledb:::libtiledb_array_close(arrptr)
+
res <- tiledb:::libtiledb_array_close(arrptr)
@@ -2617,27 +2698,27 @@

Reading Encrypted Arrays

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "READ", encryption_key)
-
-## subarray of rows 1,2 and cols 2,3,4
-subarr <- c(1L,2L, 2L,4L)
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-v <- integer(6)  # reserve space
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-print(v)         # unformed array, no coordinates
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open_with_key(ctx@ptr, uridensewkey, "READ", encryption_key)
+
+## subarray of rows 1,2 and cols 2,3,4
+subarr <- c(1L,2L, 2L,4L)
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+v <- integer(6)  # reserve space
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+print(v)         # unformed array, no coordinates
[1] 20 30 40 60 70 80
-
res <- tiledb:::libtiledb_array_close(arrptr)
-
-## TODO open at timestamp example
+
res <- tiledb:::libtiledb_array_close(arrptr)
+
+## TODO open at timestamp example
@@ -2647,27 +2728,27 @@

Multi-range Subarrays

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
-
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
-
-## range of rows 1 and 2, and 4 for dim 1, all rows for dim 2
-qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 1L, 2L)
-qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 4L, 4L)
-qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 1, 1L, 4L)
-
-qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
-v <- integer(12)  # reserve space
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
-qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-print(v)         # unformed array, no coordinates
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
+
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+
+## range of rows 1 and 2, and 4 for dim 1, all rows for dim 2
+qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 1L, 2L)
+qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 0, 4L, 4L)
+qryptr <- tiledb:::libtiledb_query_add_range(qryptr, 1, 1L, 4L)
+
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+v <- integer(12)  # reserve space
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+print(v)         # unformed array, no coordinates
 [1]  10  20  30  40  50  60  70  80 130 140 150 160
-
res <- tiledb:::libtiledb_array_close(arrptr)
+
res <- tiledb:::libtiledb_array_close(arrptr)
@@ -2677,19 +2758,19 @@

Incomplete Queries

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
-subarr <- c(1L,4L, 1L,4L)
-qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
-vec <- integer(4)  # reserve (insufficient) space
-qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
-finished <- FALSE
-while (!finished) {
-  qryptr <- tiledb:::libtiledb_query_submit(qryptr)
-  print(vec)
-  finished <- tiledb:::libtiledb_query_status(qryptr) == "COMPLETE"
-}
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridense, "READ")
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+subarr <- c(1L,4L, 1L,4L)
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+vec <- integer(4)  # reserve (insufficient) space
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", vec)
+finished <- FALSE
+while (!finished) {
+  qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+  print(vec)
+  finished <- tiledb:::libtiledb_query_status(qryptr) == "COMPLETE"
+}
[1] 10 20 30 40
@@ -2698,7 +2779,7 @@ 

Incomplete Queries

[1] 130 140 150 160
-
res <- tiledb:::libtiledb_array_close(arrptr)
+
res <- tiledb:::libtiledb_array_close(arrptr)
@@ -2708,12 +2789,12 @@

Result Estimation

-
ctx <- tiledb_ctx()
-arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "READ")
-qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
-estsz <- tiledb:::libtiledb_query_get_est_result_size_var(qryptr, "a1")
-res <- tiledb:::libtiledb_array_close(arrptr)
-estsz
+
ctx <- tiledb_ctx()
+arrptr <- tiledb:::libtiledb_array_open(ctx@ptr, uridensevar, "READ")
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+estsz <- tiledb:::libtiledb_query_get_est_result_size_var(qryptr, "a1")
+res <- tiledb:::libtiledb_array_close(arrptr)
+estsz
[1] 16 28
@@ -2725,11 +2806,22 @@

Result Estimation

Time Traveling

- -
v
+ +
ctx <- tiledb_ctx()
+tstamp <- Sys.time() - 1.0; # one seconds ago (as the arrays created here are in temp.files)
+arrptr <- tiledb:::libtiledb_array_open_at(ctx@ptr, uridense, "READ", tstamp)
+subarr <- c(1L,2L, 2L,4L)
+qryptr <- tiledb:::libtiledb_query(ctx@ptr, arrptr, "READ")
+qryptr <- tiledb:::libtiledb_query_set_subarray(qryptr, subarr)
+qryptr <- tiledb:::libtiledb_query_set_layout(qryptr, "ROW_MAJOR")
+v <- integer(6)  # reserve space
+qryptr <- tiledb:::libtiledb_query_set_buffer(qryptr, "a", v)
+qryptr <- tiledb:::libtiledb_query_submit(qryptr)
+res <- tiledb:::libtiledb_array_close(arrptr)
+v
- -
[1] 2 3 4 6 7 8
+ +
[1] 0 0 0 0 0 0
@@ -2750,9 +2842,12 @@

Array Metadata

Writing Array Metadata

- -
res <- tiledb_put_metadata(uridense, "aaa", 100L)
-res <- tiledb_put_metadata(uridense, "bb", c(1.1, 2.2))
+ +
arr <- tiledb_dense(uridense)
+close_and_reopen(arr, "WRITE")
+res <- tiledb_put_metadata(arr, "aaa", 100L)
+res <- tiledb_put_metadata(arr, "bb", c(1.1, 2.2))
+invisible(tiledb:::libtiledb_array_close(arr@ptr))
@@ -2762,18 +2857,26 @@

Reading Array Metadata

One can read by key:

- -
tiledb_get_metadata(uridense, "aaa")
+ +
close_and_reopen(arr, "READ")
+tiledb_get_metadata(arr, "aaa")
+ +
[1] 100
+

Or one can retrieve all metadata at once:

- -
md <- tiledb_get_all_metadata(uridense)
-print(md)
+ +
md <- tiledb_get_all_metadata(arr)
+print(md)
+ +
aaa:    100
+bb: 1.1, 2.2
+ @@ -2781,15 +2884,16 @@

Reading Array Metadata

Deleting Array Metadata

- -
res <- tiledb_delete_metadata(uridense, "aaa")
+ +
close_and_reopen(arr, "WRITE")
+res <- tiledb_delete_metadata(arr, "aaa")
-
LS0tCnRpdGxlOiAiVGlsZURCIFIgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIGhpZ2hsaWdodDogcHlnbWVudHMKICAgIHRoZW1lOiBsdW1lbgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKPCEtLVRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuICBUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouICAgQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gIFRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4tLT4KCiMgUHJlbGltYXJpZXMKCldlIHdpbGwgdGhlIHR3byBiYXNpYyBleGFtcGxlcyBmb3IgYSBkZW5zZSBhbmQgc3BhcnNlIGFycmF5IHNpbXBseSB0byBjcmVhdGUKYXJyYXkgZGF0YSBvbiBkaXNrIHRvIHJlZmVyIHRvIGxhdGVyIGluIGV4YW1wbGVzIHRoYXQgZm9sbG93LgoKYGBge3IgcnVuZXhhbXBsZXN9CmxpYnJhcnkodGlsZWRiKQoKdGRpciA8LSB0ZW1wZGlyKCkKdXJpZGVuc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJkZW5zZSIpCnVyaWRlbnNlZml4IDwtIGZpbGUucGF0aCh0ZGlyLCAiZGVuc2VmaXgiKQp1cmlkZW5zZXZhciA8LSBmaWxlLnBhdGgodGRpciwgImRlbnNldmFyIikKCmNyZWF0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICAjIENoZWNrIGlmIHRoZSBhcnJheSBhbHJlYWR5IGV4aXN0cy4KICAgIGlmICh0aWxlZGJfb2JqZWN0X3R5cGUoYXJyYXlfbmFtZSkgPT0gIkFSUkFZIikgewogICAgICAgIG1lc3NhZ2UoIkFycmF5IGFscmVhZHkgZXhpc3RzLiIpCiAgICAgICAgcmV0dXJuKGludmlzaWJsZShOVUxMKSkKICAgIH0KCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIDR4NCB3aXRoIGRpbWVuc2lvbnMgInJvd3MiIGFuZCAiY29scyIsIHdpdGggZG9tYWluIFsxLDRdLgogICAgZG9tIDwtIHRpbGVkYl9kb21haW4oZGltcyA9IGModGlsZWRiX2RpbSgicm93cyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZWRiX2RpbSgiY29scyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpKSkKCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIGRlbnNlIHdpdGggYSBzaW5nbGUgYXR0cmlidXRlICJhIiBzbyBlYWNoIChpLGopIGNlbGwgY2FuIHN0b3JlIGFuIGludGVnZXIuCiAgICBzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHJzID0gYyh0aWxlZGJfYXR0cigiYSIsIHR5cGUgPSAiSU5UMzIiKSkpCgogICAgIyBDcmVhdGUgdGhlIChlbXB0eSkgYXJyYXkgb24gZGlzay4KICAgIHRpbGVkYl9hcnJheV9jcmVhdGUoYXJyYXlfbmFtZSwgc2NoZW1hKQp9Cgp3cml0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICBkYXRhIDwtIGFycmF5KGMoYygxTCwgNUwsIDlMLCAxM0wpLAogICAgICAgICAgICAgICAgICAgIGMoMkwsIDZMLCAxMEwsIDE0TCksCiAgICAgICAgICAgICAgICAgICAgYygzTCwgN0wsIDExTCwgMTVMKSwKICAgICAgICAgICAgICAgICAgICBjKDRMLCA4TCwgMTJMLCAxNkwpKSwgZGltID0gYyg0LDQpKQogICAgIyBPcGVuIHRoZSBhcnJheSBhbmQgd3JpdGUgdG8gaXQuCiAgICBBIDwtIHRpbGVkYl9kZW5zZSh1cmkgPSBhcnJheV9uYW1lKQogICAgQVtdIDwtIGRhdGEKfQoKY3JlYXRlX2FycmF5KHVyaWRlbnNlKQp3cml0ZV9hcnJheSh1cmlkZW5zZSkKCgp1cmlzcGFyc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJzcGFyc2UiKQoKY3JlYXRlX2FycmF5IDwtIGZ1bmN0aW9uKGFycmF5X25hbWUpIHsKICAgICMgQ2hlY2sgaWYgdGhlIGFycmF5IGFscmVhZHkgZXhpc3RzLgogICAgaWYgKHRpbGVkYl9vYmplY3RfdHlwZShhcnJheV9uYW1lKSA9PSAiQVJSQVkiKSB7CiAgICAgICAgbWVzc2FnZSgiQXJyYXkgYWxyZWFkeSBleGlzdHMuIikKICAgICAgICByZXR1cm4oaW52aXNpYmxlKE5VTEwpKQogICAgfQoKICAgICMgVGhlIGFycmF5IHdpbGwgYmUgNHg0IHdpdGggZGltZW5zaW9ucyAicm93cyIgYW5kICJjb2xzIiwgd2l0aCBkb21haW4gWzEsNF0uCiAgICBkb20gPC0gdGlsZWRiX2RvbWFpbihkaW1zID0gYyh0aWxlZGJfZGltKCJyb3dzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlZGJfZGltKCJjb2xzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIikpKQoKICAgIyBUaGUgYXJyYXkgd2lsbCBiZSBkZW5zZSB3aXRoIGEgc2luZ2xlIGF0dHJpYnV0ZSAiYSIgc28gZWFjaCAoaSxqKSBjZWxsIGNhbiBzdG9yZSBhbiBpbnRlZ2VyLgogICAgc2NoZW1hID0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHJzPWModGlsZWRiX2F0dHIoImEiLCB0eXBlID0gIklOVDMyIikpLCBzcGFyc2UgPSBUUlVFKQoKICAgICMgQ3JlYXRlIHRoZSAoZW1wdHkpIGFycmF5IG9uIGRpc2suCiAgICB0aWxlZGJfYXJyYXlfY3JlYXRlKGFycmF5X25hbWUsIHNjaGVtYSkKfQoKd3JpdGVfYXJyYXkgPC0gZnVuY3Rpb24oYXJyYXlfbmFtZSkgewogICAgSSA8LSBjKDEsIDIsIDIpCiAgICBKIDwtIGMoMSwgNCwgMykKICAgIGRhdGEgPC0gYygxTCwgMkwsIDNMKQogICAgIyBPcGVuIHRoZSBhcnJheSBhbmQgd3JpdGUgdG8gaXQuCiAgICBBIDwtIHRpbGVkYl9zcGFyc2UodXJpID0gYXJyYXlfbmFtZSkKICAgIEFbSSwgSl0gPC0gZGF0YQp9CgpjcmVhdGVfYXJyYXkodXJpc3BhcnNlKQp3cml0ZV9hcnJheSh1cmlzcGFyc2UpCgpgYGAKCgoKIyBBUEkgVXNhZ2UKCiMjIENyZWF0aW5nIEFycmF5cwoKIyMjIENyZWF0ZSBEaW1lbnNpb24KCmBgYHtyIGNyZWF0ZWRpbX0KbGlicmFyeSh0aWxlZGIpCgojIENyZWF0ZSBkaW1lbnNpb24KIyBJbiBDKys6IERpbWVuc2lvbjo6Y3JlYXRlPFQ+KC4uLikKZGltIDwtIHRpbGVkYl9kaW0oImRpbSIsIGMoMUwsIDRMKSwgMkwsICJJTlQzMiIpCmBgYAoKCiMjIyBDcmVhdGUgQXJyYXkgRG9tYWluCgpgYGB7ciBjcmVhdGFycmRvbX0KbGlicmFyeSh0aWxlZGIpCgojICAuLiBjcmVhdGUgZGltZW5zaW9ucyBgZGltMWAsIGBkaW0yYApkaW0xIDwtIHRpbGVkYl9kaW0oImRpbTEiLCBjKDFMLCA0TCksIDJMLCAiSU5UMzIiKQpkaW0yIDwtIHRpbGVkYl9kaW0oImRpbTIiLCBjKDFMLCAyTCksIDJMLCAiSU5UMzIiKQoKIyBDcmVhdGUgZG9tYWluIHdpdGggdHdvIGRpbWVuc2lvbnMKIyBJbiBDKys6IGRvbWFpbi5hZGRfZGltZW5zaW9ucyhkaW0xKS5hZGRfZGltZW5zaW9uKGRpbTIpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGRpbXMgPSBjKGRpbTEsIGRpbTIpKQpgYGAKCiMjIyBDcmVhdGluZyBBdHRyaWJ1dGVzCgpgYGB7ciBjcmVhdGVhdHRyfQojIENyZWF0ZSBhdHRyaWJ1dGUKIyBJbiBDKys6IEF0dHJpYnV0ZTo6Y3JlYXRlPFQ+KGN0eCwgImF0dHIiKQphdHRyIDwtIHRpbGVkYl9hdHRyKCJhdHRyIiwgIklOVDMyIikKYGBgCgpgYGB7ciBjcmVhdGVhdHRydmFybnVtfQojIFdlIGNhbiBhbHNvIHNldCB0aGUgbnVtYmVyIG9mIGF0dHJpYnV0ZXMgdG8gYSB2YWx1ZSBvdGhlciB0aGFuIG9uZQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXR0cmlidXRlX3NldF9jZWxsX3ZhbF9udW0oYXR0ckBwdHIsIDMpCgojIEFuZCB3ZSBjYW4gc2V0IHRoZSBhIHZhcmlhYmxlIG51bWJlciBvZiBhdHRyaWJ1dGVzICh1c2luZyBOQSB0byBzZWxlY3QgdmFyaWFibGUgc2l6ZSkKdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9zZXRfY2VsbF92YWxfbnVtKGF0dHJAcHRyLCBOQSkKIyMgVE9ETzogUiBmdW5jdGlvbiBmb3IgbGV2ZWwgc2V0dGVyCmBgYAoKIyMjIyBTZXR0aW5nIGEgQ29tcHJlc3NvcgoKYGBge3Igc2V0Y29tcHJ9CmNvbXAgPC0gdGlsZWRiX2ZpbHRlcigiR1pJUCIpCnRpbGVkYl9maWx0ZXJfc2V0X29wdGlvbihjb21wLCJDT01QUkVTU0lPTl9MRVZFTCIsIDEwKQoKIyBDcmVhdGUgYSBmaWx0ZXIgbGlzdCB3aXRoIHRoZSBjb21wcmVzc29yCmZpbHRlcl9saXN0IDwtIHRpbGVkYl9maWx0ZXJfbGlzdChjKGNvbXApKQoKIyBDcmVhdGUgYXR0cmlidXRlIHdpdGggdGhlIGZpbHRlciBsaXN0CmF0dHIgPC0gdGlsZWRiX2F0dHIoImF0dHIiLCAiSU5UMzIiLCBmaWx0ZXJfbGlzdCA9IGZpbHRlcl9saXN0KQpgYGAKCgojIyMjIFNldHRpbmcgT3RoZXIgRmlsdGVycwoKYGBge3Igc2V0Zmlscn0KIyBDcmVhdGUgZmlsdGVycwpmMSA8LSB0aWxlZGJfZmlsdGVyKCJCSVRfV0lEVEhfUkVEVUNUSU9OIikKZjIgPC0gdGlsZWRiX2ZpbHRlcigiWlNURCIpCgojIENyZWF0ZSBhIGZpbHRlciBsaXN0IHdpdGggdGhlIHR3byBmaWx0ZXJzCmZpbHRlcl9saXN0IDwtIHRpbGVkYl9maWx0ZXJfbGlzdChjKGYxLGYyKSkKCiMgQ3JlYXRlIGF0dHJpYnV0ZSB3aXRoIHRoZSBmaWx0ZXIgbGlzdAphdHRyIDwtIHRpbGVkYl9hdHRyKCJhdHRyIiwgIklOVDMyIiwgZmlsdGVyX2xpc3QgPSBmaWx0ZXJfbGlzdCkKYGBgCgoKIyMjIyBTZXR0aW5nIHRoZSBUaWxlIENodW5rIFNpemUKCmBgYHtyIHNldHRpbGVjaHVua3NpemV9CiMgLi4uIGNyZWF0ZSBmaWx0ZXIgbGlzdApzZXRfbWF4X2NodW5rX3NpemUoZmlsdGVyX2xpc3QsIDEwMDAwKQpgYGAKCgojIyMgQ3JlYXRpbmcgdGhlIEFycmF5IFNjaGVtYQoKYGBge3IgY3JlYXRlYXJyc2NoZW1hfQojIC4uLiBjcmVhdGUgZG9tYWluIGRvbQphdHRyMSA8LSB0aWxlZGJfYXR0cigiYXR0cjEiLCAiSU5UMzIiLCBmaWx0ZXJfbGlzdCA9IGZpbHRlcl9saXN0KQphdHRyMiA8LSB0aWxlZGJfYXR0cigiYXR0cjIiLCAiRkxPQVQ2NCIsIGZpbHRlcl9saXN0ID0gZmlsdGVyX2xpc3QpCgojIENyZWF0ZSBhIGRlbnNlIGFycmF5CnNjaGVtYSA8LSB0aWxlZGJfYXJyYXlfc2NoZW1hKGRvbSwgYyhhdHRyMSwgYXR0cjIpLCBzcGFyc2UgPSBGQUxTRSkKIyBPciwgY3JlYXRlIGEgc3BhZXNlIGFycmF5CiMgc2NoZW1hIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIxLCBhdHRyMiksIHNwYXJzZSA9IFRSVUUpCmBgYAoKIyMjIyBTZXR0aW5nIHRoZSBUaWxlIGFuZCBDZWxsIE9yZGVyCgpgYGB7ciBzZXR0aWxlY2VsbG9yZGVyfQojIC4uLiBjcmVhdGUgZG9tYWluIGRvbQojIC4uLiBjcmVhdGUgYXR0cmlidXRlcyBhdHRyMSwgYXR0cjIKCiMgVGhlIHRpbGUgYW5kIG9yZGVyIGNhbiBiZSAiUk9XX01BSk9SIiBvciAiQ09MX01BSk9SIgpzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGMoYXR0cjEsIGF0dHIyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbF9vcmRlciA9ICJDT0xfTUFKT1IiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlX29yZGVyID0gIlJPV19NQUpPUiIpCmBgYAoKIyMjIyBTZXR0aW5nIHRoZSBEYXRhIFRpbGUgQ2FwYWNpdHkKCmBgYHtyIHNldHRpbGVjYXBhY2l0eX0KdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9zZXRfY2FwYWNpdHkoc2NoZW1hQHB0ciwgMTAwMDAwKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX2dldF9jYXBhY2l0eShzY2hlbWFAcHRyKQojIyBUT0RPIFIgZnVuY3Rpb24gZm9yIGFjY2Vzc29yCmBgYAoKIyMjIyBTZXR0aW5nIENvb3JkaW5hdGUgYW5kIE9mZnNldCBGaWx0ZXJzCgpgYGB7ciBzZXRjb29yZG9mZnNldGZpbHR9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCiMgLi4uIGNyZWF0ZSBhdHRyaWJ1dGVzIGF0dHIxLCBhdHRyMgojIC4uLiBjcmVhdGUgZmlsdGVyIGxpc3RzIGZsMSwgZmwyLCBzaW1pbGFyIHRvIGF0dHJpYnV0ZXMKZjEgPC0gdGlsZWRiX2ZpbHRlcigiQklUX1dJRFRIX1JFRFVDVElPTiIpCmYyIDwtIHRpbGVkYl9maWx0ZXIoIlpTVEQiKQpmbDEgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjEpKQpmbDIgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjIpKQoKIyBDcmVhdGUgdGhlIHNjaGVtYSBzZXR0aW5nIHRoZSBjb29yZGluYXRlcyBhbmQgb2Zmc2V0cyBmaWx0ZXIgbGlzdHMKc2NoZW1hIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIxLCBhdHRyMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb3Jkc19maWx0ZXJfbGlzdCA9IGZsMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0c19maWx0ZXJfbGlzdCA9IGZsMikKYGBgCgoKIyMjIyBDaGVja2luZyBDb3JyZWN0bmVzcwoKYGBge3IgYXJyYXlzY2hlbWFjaGVja30KdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9jaGVjayhzY2hlbWFAcHRyKQojIyBUT0RPOiBSIGZ1bmN0aW9uIGZvciBhY2Nlc3MKYGBgCgoKCiMjIyBDcmVhdGluZyB0aGUgQXJyYXkKCmBgYHtyIGNyZWF0ZWFycmF5LCBldmFsPUZBTFNFfQojIC4uLiBjcmVhdGUgYXJyYXkgc2NoZW1hCgojIENyZWF0ZSB0aGUgYXJyYXkKdGlsZWRiX2FycmF5X2NyZWF0ZSh1cmlkZW5zZSwgc2NoZW1hKQpgYGAKCiMjIyBDcmVhdGluZyBFbmNyeXB0ZWQgQXJyYXlzCgpgYGB7ciBjcmVhdGV3aXRoa2V5fQplbmNyeXB0aW9uX2tleSA8LSAiMDEyMzQ1Njc4OWFiY2RlRjAxMjM0NTY3ODlhYmNkZUYiCnVyaWRlbnNld2tleSA8LSBmaWxlLnBhdGgodGRpciwgImRlbnNld2tleSIpCmlmIChkaXIuZXhpc3RzKHVyaWRlbnNld2tleSkpIHVubGluayh1cmlkZW5zZXdrZXksIHJlY3Vyc2l2ZT1UUlVFKQoKIyBzaG9ydGN1dDogYm9ycm93IHNjaGVtYSBmcm9tIGRlbnNlIGFycmF5OyBjb3VsZCBjcmVhdGUgc2NoZW1hIHRvbwpzY2hlbWEgPC0gc2NoZW1hKHRpbGVkYl9kZW5zZSh1cmlkZW5zZSkpCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jcmVhdGVfd2l0aF9rZXkodXJpZGVuc2V3a2V5LCBzY2hlbWFAcHRyLCBlbmNyeXB0aW9uX2tleSkKIyNUT0RPOiBSIHN1cHBvcnQKYGBgCgoKIyMgV3JpdGluZyBBcnJheXMKCiMjIyBXcml0aW5nIGluIERlbnNlIFN1YmFycmF5cwoKYGBge3Igd3JpdGVkZW5zZXN1YmFyciwgZXZhbD1GQUxTRX0KIyMgcHJlcGFyZSBhIGxhcmdlciA1IHggNSB0byBlbWJlZCBpbnRvCnRtcCA8LSB0ZW1wZmlsZSgpCmQxICA8LSB0aWxlZGJfZGltKGRvbWFpbiA9IGMoMUwsIDVMKSkKZDIgIDwtIHRpbGVkYl9kaW0oZG9tYWluID0gYygxTCwgNUwpKQpkb20gPC0gdGlsZWRiX2RvbWFpbihjKGQxLCBkMikpCnZhbCA8LSB0aWxlZGJfYXR0cihuYW1lPSJ2YWwiLCB0eXBlID0gIklOVDMyIikKc2NoIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKHZhbCkpCnRpbGVkYl9hcnJheV9jcmVhdGUodG1wLCBzY2gpCgpkYXQgPC0gbWF0cml4KGFzLmludGVnZXIocm5vcm0oMjUpKjEwMCksIDUsIDUpCmFyciA8LSB0aWxlZGJfZGVuc2UodG1wLCBhcy5kYXRhLmZyYW1lPUZBTFNFKQphcnJbXSA8LSBkYXQKCgojIFByZXBhcmUgYSAyeDMgZGVuc2UgYXJyYXkKIyBDb250cmFyeSB0byBQeXRob24sIFIgYnkgZGVmYXVsdCBzdG9yZXMgYXJyYXlzIGluIGNvbC1tYWpvciBvcmRlcgpkYXRhIDwtICBhcnJheShjKDFMLCA0TCwgMkwsIDVMLCAzTCwgNkwpLCBkaW09YygyLDMpKQoKIyBQcmVwYXJlIHRoZSBbMSwyXSB4IFsyLDRdIHN1YmFycmF5IHRvIHdyaXRlIHRvCkkgPC0gYygxOjIpCkogPC0gYygyOjQpCgojIE9wZW4gdGhlIGFycmF5IGFuZCB3cml0ZSB0aGUgZGF0YSB0byBpdApBIDwtIHRpbGVkYl9kZW5zZSh1cmkgPSB0bXApCkFbSSwgSl0gPC0gZGF0YQoKdW5saW5rKHRtcCwgcmVjdXJzaXZlPVRSVUUpCmBgYAoKCiMjIyMgQmFzaWMgV3JpdGluZyB1c2luZyBMb3ctTGV2ZWwgQ29kZQoKYGBge3IgYmFzaXNjd3JpdGluZ2xvd2xldmVsfQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZSwgIldSSVRFIikKCiMjIGRhdGE6IHNpbXBsZSAoaW50ZWdlciBzZXF1ZW5jZSkgb2YgMToxNiB0aW1lcyAxMAp2ZWMgPC0gMToxNiAqIDEwTApzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKYGBgCgoKIyMjIFdyaXRpbmcgU3BhcnNlIENlbGxzCgpgYGB7ciB3cml0ZXNwYXJzZWNlbGxzfQp0bXAgPC0gdXJpc3BhcnNlCnVubGluayh0bXAsIHJlY3Vyc2l2ZT1UUlVFKQoKZDEgIDwtIHRpbGVkYl9kaW0oZG9tYWluID0gYygxTCwgNUwpKQpkMiAgPC0gdGlsZWRiX2RpbShkb21haW4gPSBjKDFMLCA1TCkpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGMoZDEsIGQyKSkKdmFsIDwtIHRpbGVkYl9hdHRyKCJ2YWwiLCB0eXBlID0gIklOVDMyIikKc2NoIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKHZhbCksIHNwYXJzZT1UUlVFKQp0aWxlZGJfYXJyYXlfY3JlYXRlKHRtcCwgc2NoKQoKCiMgUHJlcGFyZSBzb21lIGRhdGEKZGF0YSA8LSBjKDNMLCA0TCwgMUwsIDJMKQoKSSA8LSBjKDMsIDQsIDEsIDIpCkogPC0gYygzLCA0LCAyLCAxKQoKIyBPcGVuIHRoZSBhcnJheSBhbmQgd3JpdGUgdGhlIGRhdGEgdG8gaXQKQSA8LSB0aWxlZGJfc3BhcnNlKHVyaSA9IHRtcCkKQVtJLCBKXSA8LSBkYXRhCgpgYGAKCgojIyMgV3JpdGluZyBFbmNyeXB0ZWQgQXJyYXlzCgpgYGB7ciB3cml0aW5nZW5jcnlwdGVkbG93bGV2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuX3dpdGhfa2V5KGN0eEBwdHIsIHVyaWRlbnNld2tleSwgIldSSVRFIiwgZW5jcnlwdGlvbl9rZXkpCgojIyBkYXRhOiBzaW1wbGUgKGludGVnZXIgc2VxdWVuY2UpIG9mIDE6MTYgdGltZXMgMTAKdmVjIDwtIDE6MTYgKiAxMEwKc3ViYXJyIDwtIGMoMUwsNEwsIDFMLDRMKQoKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJXUklURSIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2ZWMpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCiMgVE9ETyBIaWdoZXItbGV2ZWwgUiBzdXBwb3J0CgpgYGAKCgoKCiMjIyBGaXhlZC1sZW5ndGggQXR0cmlidXRlcwoKYGBge3IgZml4ZWRsZW5ndGhhdHRyaWJ1dGVzfQppZiAoZGlyLmV4aXN0cyh1cmlkZW5zZWZpeCkpIHVubGluayh1cmlkZW5zZWZpeCwgcmVjdXJzaXZlPVRSVUUpCmQxICA8LSB0aWxlZGJfZGltKGRvbWFpbiA9IGMoMUwsIDRMKSkKZDIgIDwtIHRpbGVkYl9kaW0oZG9tYWluID0gYygxTCwgNEwpKQpkb20gPC0gdGlsZWRiX2RvbWFpbihjKGQxLCBkMikpCgp2ZWMgPC0gMTozMiAqIDEwTAphdHRyIDwtIHRpbGVkYl9hdHRyKCJhIiwgdHlwZSA9IHJfdG9fdGlsZWRiX3R5cGUodmVjKSkKCiMjIHNldCB0byB0d28gdmFsdWVzIHBlciBjZWxsCnRpbGVkYjo6OmxpYnRpbGVkYl9hdHRyaWJ1dGVfc2V0X2NlbGxfdmFsX251bShhdHRyQHB0ciwgMikKc2NoIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIpKQp0aWxlZGJfYXJyYXlfY3JlYXRlKHVyaWRlbnNlZml4LCBzY2gpCgpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZWZpeCwgIldSSVRFIikKc3ViYXJyIDwtIGMoMUwsNEwsIDFMLDRMKQoKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJXUklURSIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2ZWMpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCgojVE9ETyBIaWdoZXItbGV2ZWwgUiBzdXBwb3J0CmBgYAoKIyMjIFZhci1sZW5ndGggQXR0cmlidXRlcwoKYGBge3J9CmlmIChkaXIuZXhpc3RzKHVyaWRlbnNldmFyKSkgdW5saW5rKHVyaWRlbnNldmFyLCByZWN1cnNpdmU9VFJVRSkKIyMgRGVmaW5lIGFycmF5CiMjIFRoZSBhcnJheSB3aWxsIGJlIDR4NCB3aXRoIGRpbWVuc2lvbnMgInJvd3MiIGFuZCAiY29scyIsIHdpdGggZG9tYWluIFsxLDRdLgpkb20gPC0gdGlsZWRiX2RvbWFpbihkaW1zID0gYyh0aWxlZGJfZGltKCJyb3dzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVkYl9kaW0oImNvbHMiLCBjKDFMLCA0TCksIDRMLCAiSU5UMzIiKSkpCgoKYXR0ciA8LSB0aWxlZGJfYXR0cigiYTEiLCB0eXBlID0gIkNIQVIiKQojIyBzZXQgdG8gdmFyaWFibGUgbGVuZ3RoCnRpbGVkYjo6OmxpYnRpbGVkYl9hdHRyaWJ1dGVfc2V0X2NlbGxfdmFsX251bShhdHRyQHB0ciwgTkEpCgojIyBub3cgc2V0IHRoZSBzY2hlbWEKY3R4IDwtIHRpbGVkYl9jdHgoKQpzY2hwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9jcmVhdGUoY3R4QHB0ciwgIkRFTlNFIikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9zZXRfZG9tYWluKHNjaHB0ciwgZG9tQHB0cikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9zZXRfY2VsbF9vcmRlcihzY2hwdHIsICJST1dfTUFKT1IiKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF90aWxlX29yZGVyKHNjaHB0ciwgIlJPV19NQUpPUiIpCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfYWRkX2F0dHJpYnV0ZShzY2hwdHIsIGF0dHJAcHRyKQoKCgojIyBDcmVhdGUgdGhlIChlbXB0eSkgYXJyYXkgb24gZGlzay4KdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2NyZWF0ZSh1cmlkZW5zZXZhciwgc2NocHRyKQoKZGF0YSA8LSAiYWJiY2NjZGRlZWVmZ2hoaGlqampra2xtbm9vcCI7Cm9mZnNldHMgPC0gYygwTCwgMUwsIDNMLCA2TCwgOEwsIDExTCwgMTJMLCAxM0wsIDE2TCwgMTdMLCAyMEwsIDIyTCwgMjNMLCAyNEwsIDI1TCwgMjdMKQoKY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2V2YXIsICJXUklURSIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiV1JJVEUiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKCmJ1ZnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfYnVmZmVyX3Zhcl9jaGFyX2NyZWF0ZShvZmZzZXRzLCBkYXRhKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXJfdmFyX2NoYXIocXJ5cHRyLCAiYTEiLCBidWZwdHIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKCiNUT0RPIEhpZ2hlci1sZXZlbCBSIHN1cHBvcnQKYGBgCgoKIyMjIEdldHRpbmcgdGhlIEZyYWdtZW50IEluZm8KCmBgYHtyIGZyYWdtZW50aW5mb30KIyMgY29udGludWluZyBmcm9tIHByZXZpb3VzIGV4YW1wbGUgb24gZGVuc2UgdmFyaWFibGUgbGVuZ3RoIGFycmF5CiMjIChidXQgdGhpcyB3b3JrcyBvZiBjb3Vyc2Ugd2l0aCBhbnkgYXJyYXkgYWZ0ZXIgYSB3cml0ZSBpcyBuZWVkZWQKbnVtZnJhZyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfZ2V0X2ZyYWdtZW50X251bShxcnlwdHIpCnVyaXR4dCA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfZ2V0X2ZyYWdtZW50X3VyaShxcnlwdHIsIDApCgojI1RPRE8gSGlnaGVyLWxldmVsIFIgc3VwcG9ydApgYGAKCiMjIFJlYWRpbmcgQXJyYXlzCgojIyMgUmVhZGluZyB0aGUgQXJyYXkgU2NoZW1hCgpgYGB7ciBzY2hlbWFsb2FkfQphcnJheV9uYW1lIDwtIHVyaXNwYXJzZQpBIDwtIHRpbGVkYl9zcGFyc2UodXJpID0gYXJyYXlfbmFtZSkKIyBjYW4gYWxzbyBsb2FkIGRlbnNlCnNjaCA8LSBzY2hlbWEoQSkKIyBjYW4gYWxzbyBvcGVuIGVuY3J5cHRlZCBhcnJheXMgd2l0aCBrZXkKYGBgCgojIyMjIEluc3BlY3RpbmcgdGhlIGFycmF5IHNjaGVtYQoKYGBge3Igc2NoZW1haW5zcGVjdH0KYXJyYXlfbmFtZSA8LSB1cmlzcGFyc2UKCiMgR2V0IGFycmF5IHNjaGVtYQpBIDwtIHRpbGVkYl9zcGFyc2UodXJpID0gYXJyYXlfbmFtZSkKIyBvciB1c2UgdGlsZWRiX2RlbnNlKHVyaSA9IGFycmF5X25hbWUpIGZvciBkZW5zZQpzY2hlbWEgPC0gc2NoZW1hKEEpCgojIEdldCBhcnJheSB0eXBlCnNwYXJzZSA8LSBpcy5zcGFyc2Uoc2NoZW1hKQoKIyBHZXQgdGlsZSBjYXBhY2l0eQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX2dldF9jYXBhY2l0eShzY2hAcHRyKQojIFRPRE86IFIgYWNjZXNzb3IgZm9yIHRpbGUKCiMgR2V0IHRpbGUgb3JkZXIKdF9vcmRlciA8LSB0aWxlX29yZGVyKHNjaGVtYSkKCiMgR2V0IGNlbGwgb3JkZXIKY19vcmRlciA8LSBjZWxsX29yZGVyKHNjaGVtYSkKCiMgR2V0IGNvb3JkaW5hdGVzIGFuZCBvZmZzZXQgZmlsdGVyIGxpc3QKcmVzbGlzdCA8LSBmaWx0ZXJfbGlzdChzY2hlbWEpCgojIEdldCB0aGUgYXJyYXkgZG9tYWluCmRvbSA8LSBkb21haW4oc2NoZW1hKQoKIyBHZXQgYWxsIGF0dHJpYnV0ZXMgYXMgbGlzdAphdHRycyA8LSBhdHRycyhzY2hlbWEpCgojIEdldCBhdHRyaWJ1dGUgZnJvbSBuYW1lCmF0dHIgPC0gYXR0cnMoc2NoZW1hLCAiYXR0ciIpCgojIER1bXAgdGhlIGFycmF5IHNjaGVtYSBpbiBBU0NJSSBmb3JtYXQgdG8gc3Rkb3V0CnNob3coc2NoZW1hKQpgYGAKCgojIyMjIEluc3BlY3RpbmcgRG9tYWluCgpgYGB7ciBpbnNwZWN0ZG9tYWlufQojIC4uLiBnZXQgYXJyYXkgc2NoZW1hCiMgLi4uIGdldCBkb21haW4gZnJvbSBzY2hlbWEKZG9tIDwtIGRvbWFpbihzY2hlbWEpCgojIEdldCB0aGUgZG9tYWluIGRhdGF0eXBlIChpLmUuLCB0aGUgZGF0YXR5cGUgb2YgYWxsIGRpbWVuc2lvbnMpCnR5cGUgPC0gZGF0YXR5cGUoZG9tKQoKIyBHZXQgbnVtYmVyIG9mIGRpbWVuc2lvbnMKZGltX251bSA8LSBkaW0oZG9tKQoKIyBHZXQgYWxsIGRpbWVuc2lvbgpkaW1zIDwtIGRpbWVuc2lvbnMoZG9tKQoKIyBEdW1wIHRoZSBkb21haW4gaW4gQVNDSUkgZm9ybWF0IGluIHRoZSBzZWxlY3RlZCBvdXRwdXQKc2hvdyhkb20pCmBgYAoKIyMjIyBJbnNwZWN0aW5nIERpbWVuc2lvbnMKCmBgYHtyIGluc3BlY3RkaW1lbnNpb25zLCBldmFsPUZBTFNFfQojIC4uLiBnZXQgYXJyYXkgc2NoZW1hCiMgLi4uIGdldCBkb21haW4KIyAuLi4gZ2V0IGRpbWVuc2lvbiBieSBpbmRleCBvciBuYW1lCgojRklYTUUKCiMgR2V0IGRpbWVuc2lvbiBuYW1lCmRpbV9uYW1lIDwtIG5hbWUoZGltKQoKIyBHZXQgZGltZW5zaW9uIGRhdGF0eXBlCmRpbV90eXBlIDwtIGRhdGF0eXBlKGRpbSkKCiMgR2V0IGRpbWVuc2lvbiBkb21haW4KZG9tYWluIDwtIGRvbWFpbihkaW0pCgojIEdldCB0aWxlIGV4dGVudAp0aWxlX2V4dGVudCA8LSB0aWxlKGRpbSkKCiMgRHVtcCB0aGUgZGltZW5zaW9uIGluIEFTQ0lJIGZvcm1hdCBpbiB0aGUgc2VsZWN0ZWQgb3V0cHV0CnNob3coZGltKQoKYGBgCgoKIyMjIyBJbnNwZWN0aW5nIEF0dHJpYnV0ZXMKCmBgYHtyIGluc3BlY3RhdHRyLCBldmFsPUZBTFNFfQojIC4uLiBnZXQgYXJyYXkgc2NoZW1hCiMgLi4uIGdldCBhdHRyaWJ1dGUgYnkgaW5kZXggb3IgbmFtZQoKc3RvcGlmbm90KGlzLm51bGwoYXR0cikpCiMgR2V0IGF0dHJpYnV0ZSBuYW1lCmF0dHJfbmFtZSA8LSBuYW1lKGF0dHIpCgojIEdldCBhdHRyaWJ1dGUgZGF0YXR5cGUKYXR0cl90eXBlIDwtIGRhdGF0eXBlKGF0dHIpCgojIEdldCBmaWx0ZXIgbGlzdApmaWx0ZXJfbGlzdCA8LSBmaWx0ZXJfbGlzdChhdHRyKQoKIyBDaGVjayBpZiBhdHRyaWJ1dGUgaXMgdmFyaWFibGUtbGVuZ3RoCiMgdmFyaWFibGUgbGVuZ3RoIGF0dHJpYnR1ZXMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gUiBjdXJyZW50bHkKCiMgR2V0IG51bWJlciBvZiB2YWx1ZXMgcGVyIGNlbGwKbnVtIDwtIG5jZWxscyhhdHRyKQoKIyBHZXQgY2VsbCBzaXplIGZvciB0aGlzIGF0dHJpYnV0ZQpzeiA8LS0gdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9nZXRfY2VsbF92YWwoYXR0ckBwdHIpCgojIER1bXAgdGhlIGF0dHJpYnV0ZSBpbiBBU0NJSSBmb3JtYXQgaW4gdGhlIHNlbGVjdGVkIG91dHB1dApzaG93KGF0dHIpCmBgYAoKCgojIyMjIEluc3BlY3RpbmcgRmlsdGVycwoKYGBge3IgaW5zcGVjdGZpbHRlcnMsIGV2YWw9RkFMU0V9CmZsIDwtIHRpbGVkYl9maWx0ZXJfbGlzdCgpCgojIGdldCBudW1iZXIgb2YgZmlsdGVyCnRpbGVkYjo6OmxpYnRpbGVkYl9maWx0ZXJfbGlzdF9nZXRfbmZpbHRlcnMoZmxAcHRyKQoKIyBnZXQgbWF4IGNodW5rIHNpemUKdGlsZWRiOjo6bGlidGlsZWRiX2ZpbHRlcl9saXN0X2dldF9tYXhfY2h1bmtfc2l6ZShmbEBwdHIpCgojIGdldCBmaWx0ZXIgZnJvbSBpbmRleAppbmQgPC0gaQp0aWxlZGI6OjpsaWJ0aWxlZGJfZmlsdGVyX2xpc3RfZ2V0X2ZpbHRlcl9mcm9tX2luZGV4KGZsQHB0ciwgaW5kKQpgYGAKCiMjIyBCYXNpYyBSZWFkaW5nCgpgYGB7ciBiYXNpc2NyZWFkaW5nfQojIENyZWF0ZSBhIFRpbGVEQiBjb250ZXh0CmN0eCA8LSB0aWxlZGJfY3R4KCkKCiMgT3BlbiBhIGRlbnNlIGFycmF5CkEgPC0gdGlsZWRiX2RlbnNlKHVyaSA9IHVyaWRlbnNlLCBjdHg9Y3R4KQoKIyBPciwgb3BlbiBhIHNwYXJzZSBhcnJheQojIEEgPC0gdGlsZWRiX3NwYXJzZSh1cmkgPSAiPGFycmF5LXVyaT4iLCBjdHg9Y3R4KQoKIyBTbGljZSBvbmx5IHJvd3MgMSwgMiBhbmQgY29scyAyLCAzLCA0CmRhdGEgPC0gQVsxOjIsIDI6NF0Kc2hvdyhkYXRhKQpgYGAKCiMjIyMgQmFzaWMgUmVhZGluZyB1c2luZyBMb3ctTGV2ZWwgQ29kZQoKYGBge3IgYmFzaXNjcmVhZGluZ2xvd2xldmVsfQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZSwgIlJFQUQiKQojIyBzdWJhcnJheSBvZiByb3dzIDEsMiBhbmQgY29scyAyLDMsNApzdWJhcnIgPC0gYygxTCwyTCwgMkwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnYgPC0gaW50ZWdlcig2KSAgIyByZXNlcnZlIHNwYWNlCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpwcmludCh2KSAgICAgICAgICMgdW5mb3JtZWQgYXJyYXksIG5vIGNvb3JkaW5hdGVzCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQpgYGAKCiMjIyBSZWFkaW5nIEVuY3J5cHRlZCBBcnJheXMKCmBgYHtyIHJlYWRlbmNyeXB0ZWR9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuX3dpdGhfa2V5KGN0eEBwdHIsIHVyaWRlbnNld2tleSwgIlJFQUQiLCBlbmNyeXB0aW9uX2tleSkKCiMjIHN1YmFycmF5IG9mIHJvd3MgMSwyIGFuZCBjb2xzIDIsMyw0CnN1YmFyciA8LSBjKDFMLDJMLCAyTCw0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKdiA8LSBpbnRlZ2VyKDYpICAjIHJlc2VydmUgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2KQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnByaW50KHYpICAgICAgICAgIyB1bmZvcm1lZCBhcnJheSwgbm8gY29vcmRpbmF0ZXMKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCgojIyBUT0RPIG9wZW4gYXQgdGltZXN0YW1wIGV4YW1wbGUKYGBgCgojIyMgTXVsdGktcmFuZ2UgU3ViYXJyYXlzCgpgYGB7ciBtdWx0aXJhbmdlfQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZSwgIlJFQUQiKQoKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJSRUFEIikKCiMjIHJhbmdlIG9mIHJvd3MgMSBhbmQgMiwgYW5kIDQgZm9yIGRpbSAxLCBhbGwgcm93cyBmb3IgZGltIDIKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9hZGRfcmFuZ2UocXJ5cHRyLCAwLCAxTCwgMkwpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfYWRkX3JhbmdlKHFyeXB0ciwgMCwgNEwsIDRMKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X2FkZF9yYW5nZShxcnlwdHIsIDEsIDFMLCA0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQp2IDwtIGludGVnZXIoMTIpICAjIHJlc2VydmUgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2KQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnByaW50KHYpICAgICAgICAgIyB1bmZvcm1lZCBhcnJheSwgbm8gY29vcmRpbmF0ZXMKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCmBgYAoKIyMjIEluY29tcGxldGUgUXVlcmllcwoKYGBge3IgaW5jb21wbGV0ZXJlYWRzfQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZSwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQpzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQp2ZWMgPC0gaW50ZWdlcig0KSAgIyByZXNlcnZlIChpbnN1ZmZpY2llbnQpIHNwYWNlCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdmVjKQpmaW5pc2hlZCA8LSBGQUxTRQp3aGlsZSAoIWZpbmlzaGVkKSB7CiAgcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQogIHByaW50KHZlYykKICBmaW5pc2hlZCA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3RhdHVzKHFyeXB0cikgPT0gIkNPTVBMRVRFIgp9CnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQpgYGAKCiMjIyBSZXN1bHQgRXN0aW1hdGlvbgoKYGBge3IgcmVzdWx0ZXN0aW1hdGlvbn0KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW4oY3R4QHB0ciwgdXJpZGVuc2V2YXIsICJSRUFEIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJSRUFEIikKZXN0c3ogPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X2dldF9lc3RfcmVzdWx0X3NpemVfdmFyKHFyeXB0ciwgImExIikKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCmVzdHN6CmBgYAoKIyMjIFRpbWUgVHJhdmVsaW5nCgpgYGB7ciB0aW1ldHJhdmVsfQpjdHggPC0gdGlsZWRiX2N0eCgpCnRzdGFtcCA8LSBTeXMudGltZSgpIC0gMS4wOyAjIG9uZSBzZWNvbmRzIGFnbyAoYXMgdGhlIGFycmF5cyBjcmVhdGVkIGhlcmUgYXJlIGluIHRlbXAuZmlsZXMpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3Blbl9hdChjdHhAcHRyLCB1cmlkZW5zZSwgIlJFQUQiLCB0c3RhbXApCnN1YmFyciA8LSBjKDFMLDJMLCAyTCw0TCkKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJSRUFEIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQp2IDwtIGludGVnZXIoNikgICMgcmVzZXJ2ZSBzcGFjZQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHYpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCnYKYGBgCgojIyBFbWJlZGRlZCBTUUwKCiMjIEFzeW5jaHJvbm91cyBRdWVyaWVzCgojIyBDb25maWd1cmF0aW9uCgojIyBBcnJheSBNZXRhZGF0YQoKIyMjIFdyaXRpbmcgQXJyYXkgTWV0YWRhdGEKCmBgYHtyIHdyaXRlbWV0YWRhdGF9CnJlcyA8LSB0aWxlZGJfcHV0X21ldGFkYXRhKHVyaWRlbnNlLCAiYWFhIiwgMTAwTCkKcmVzIDwtIHRpbGVkYl9wdXRfbWV0YWRhdGEodXJpZGVuc2UsICJiYiIsIGMoMS4xLCAyLjIpKQpgYGAKCiMjIyBSZWFkaW5nIEFycmF5IE1ldGFkYXRhCgpPbmUgY2FuIHJlYWQgYnkga2V5OgoKYGBge3IgcmVhZG1ldGFkYXRhfQp0aWxlZGJfZ2V0X21ldGFkYXRhKHVyaWRlbnNlLCAiYWFhIikKYGBgCgpPciBvbmUgY2FuIHJldHJpZXZlIGFsbCBtZXRhZGF0YSBhdCBvbmNlOgoKYGBge3IgcmVhZG1ldGFkYXRhYWxsfQptZCA8LSB0aWxlZGJfZ2V0X2FsbF9tZXRhZGF0YSh1cmlkZW5zZSkKcHJpbnQobWQpCmBgYAoKIyMjIERlbGV0aW5nIEFycmF5IE1ldGFkYXRhCgpgYGB7ciBkZWxldGVtZXRhZGF0YX0KcmVzIDwtIHRpbGVkYl9kZWxldGVfbWV0YWRhdGEodXJpZGVuc2UsICJhYWEiKQpgYGAK
+
LS0tCnRpdGxlOiAiVGlsZURCIFIgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIGhpZ2hsaWdodDogcHlnbWVudHMKICAgIHRoZW1lOiBsdW1lbgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKPCEtLVRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuICBUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouICAgQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4gIFRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4tLT4KCiMgUHJlbGltYXJpZXMKCldlIHdpbGwgdGhlIHR3byBiYXNpYyBleGFtcGxlcyBmb3IgYSBkZW5zZSBhbmQgc3BhcnNlIGFycmF5IHNpbXBseSB0byBjcmVhdGUKYXJyYXkgZGF0YSBvbiBkaXNrIHRvIHJlZmVyIHRvIGxhdGVyIGluIGV4YW1wbGVzIHRoYXQgZm9sbG93LgoKYGBge3IgcnVuZXhhbXBsZXN9CmxpYnJhcnkodGlsZWRiKQoKdGRpciA8LSB0ZW1wZGlyKCkKdXJpZGVuc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJkZW5zZSIpCnVyaWRlbnNlZml4IDwtIGZpbGUucGF0aCh0ZGlyLCAiZGVuc2VmaXgiKQp1cmlkZW5zZXZhciA8LSBmaWxlLnBhdGgodGRpciwgImRlbnNldmFyIikKCmNyZWF0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICAjIENoZWNrIGlmIHRoZSBhcnJheSBhbHJlYWR5IGV4aXN0cy4KICAgIGlmICh0aWxlZGJfb2JqZWN0X3R5cGUoYXJyYXlfbmFtZSkgPT0gIkFSUkFZIikgewogICAgICAgIG1lc3NhZ2UoIkFycmF5IGFscmVhZHkgZXhpc3RzLiIpCiAgICAgICAgcmV0dXJuKGludmlzaWJsZShOVUxMKSkKICAgIH0KCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIDR4NCB3aXRoIGRpbWVuc2lvbnMgInJvd3MiIGFuZCAiY29scyIsIHdpdGggZG9tYWluIFsxLDRdLgogICAgZG9tIDwtIHRpbGVkYl9kb21haW4oZGltcyA9IGModGlsZWRiX2RpbSgicm93cyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZWRiX2RpbSgiY29scyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpKSkKCiAgICAjIFRoZSBhcnJheSB3aWxsIGJlIGRlbnNlIHdpdGggYSBzaW5nbGUgYXR0cmlidXRlICJhIiBzbyBlYWNoIChpLGopIGNlbGwgY2FuIHN0b3JlIGFuIGludGVnZXIuCiAgICBzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHJzID0gdGlsZWRiX2F0dHIoImEiLCB0eXBlID0gIklOVDMyIikpCgogICAgIyBDcmVhdGUgdGhlIChlbXB0eSkgYXJyYXkgb24gZGlzay4KICAgIHRpbGVkYl9hcnJheV9jcmVhdGUoYXJyYXlfbmFtZSwgc2NoZW1hKQp9Cgp3cml0ZV9hcnJheSA8LSBmdW5jdGlvbihhcnJheV9uYW1lKSB7CiAgICBkYXRhIDwtIGFycmF5KGMoYygxTCwgNUwsIDlMLCAxM0wpLAogICAgICAgICAgICAgICAgICAgIGMoMkwsIDZMLCAxMEwsIDE0TCksCiAgICAgICAgICAgICAgICAgICAgYygzTCwgN0wsIDExTCwgMTVMKSwKICAgICAgICAgICAgICAgICAgICBjKDRMLCA4TCwgMTJMLCAxNkwpKSwgZGltID0gYyg0LDQpKQogICAgIyBPcGVuIHRoZSBhcnJheSBhbmQgd3JpdGUgdG8gaXQuCiAgICBBIDwtIHRpbGVkYl9kZW5zZSh1cmkgPSBhcnJheV9uYW1lKQogICAgQVtdIDwtIGRhdGEKfQoKY3JlYXRlX2FycmF5KHVyaWRlbnNlKQp3cml0ZV9hcnJheSh1cmlkZW5zZSkKCgp1cmlzcGFyc2UgPC0gZmlsZS5wYXRoKHRkaXIsICJzcGFyc2UiKQoKY3JlYXRlX2FycmF5IDwtIGZ1bmN0aW9uKGFycmF5X25hbWUpIHsKICAgICMgQ2hlY2sgaWYgdGhlIGFycmF5IGFscmVhZHkgZXhpc3RzLgogICAgaWYgKHRpbGVkYl9vYmplY3RfdHlwZShhcnJheV9uYW1lKSA9PSAiQVJSQVkiKSB7CiAgICAgICAgbWVzc2FnZSgiQXJyYXkgYWxyZWFkeSBleGlzdHMuIikKICAgICAgICByZXR1cm4oaW52aXNpYmxlKE5VTEwpKQogICAgfQoKICAgICMgVGhlIGFycmF5IHdpbGwgYmUgNHg0IHdpdGggZGltZW5zaW9ucyAicm93cyIgYW5kICJjb2xzIiwgd2l0aCBkb21haW4gWzEsNF0uCiAgICBkb20gPC0gdGlsZWRiX2RvbWFpbihkaW1zID0gYyh0aWxlZGJfZGltKCJyb3dzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxlZGJfZGltKCJjb2xzIiwgYygxTCwgNEwpLCA0TCwgIklOVDMyIikpKQoKICAgICMgVGhlIGFycmF5IHdpbGwgYmUgZGVuc2Ugd2l0aCBhIHNpbmdsZSBhdHRyaWJ1dGUgImEiIHNvIGVhY2ggKGksaikgY2VsbCBjYW4gc3RvcmUgYW4gaW50ZWdlci4KICAgIHNjaGVtYSA9IHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBhdHRycz10aWxlZGJfYXR0cigiYSIsIHR5cGUgPSAiSU5UMzIiKSwgc3BhcnNlID0gVFJVRSkKCiAgICAjIENyZWF0ZSB0aGUgKGVtcHR5KSBhcnJheSBvbiBkaXNrLgogICAgdGlsZWRiX2FycmF5X2NyZWF0ZShhcnJheV9uYW1lLCBzY2hlbWEpCn0KCndyaXRlX2FycmF5IDwtIGZ1bmN0aW9uKGFycmF5X25hbWUpIHsKICAgIEkgPC0gYygxLCAyLCAyKQogICAgSiA8LSBjKDEsIDQsIDMpCiAgICBkYXRhIDwtIGMoMUwsIDJMLCAzTCkKICAgICMgT3BlbiB0aGUgYXJyYXkgYW5kIHdyaXRlIHRvIGl0LgogICAgQSA8LSB0aWxlZGJfc3BhcnNlKHVyaSA9IGFycmF5X25hbWUpCiAgICBBW0ksIEpdIDwtIGRhdGEKfQoKY3JlYXRlX2FycmF5KHVyaXNwYXJzZSkKd3JpdGVfYXJyYXkodXJpc3BhcnNlKQoKY2xvc2VfYW5kX3Jlb3BlbiA8LSBmdW5jdGlvbihhcnIsIHR4dCkgewogIHJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJyQHB0cikKICByZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fd2l0aF9wdHIoYXJyQHB0ciwgdHh0KQp9CmBgYAoKCgojIEFQSSBVc2FnZQoKIyMgQ3JlYXRpbmcgQXJyYXlzCgojIyMgQ3JlYXRlIERpbWVuc2lvbgoKYGBge3IgY3JlYXRlZGltfQpsaWJyYXJ5KHRpbGVkYikKCiMgQ3JlYXRlIGRpbWVuc2lvbgojIEluIEMrKzogRGltZW5zaW9uOjpjcmVhdGU8VD4oLi4uKQpkaW0gPC0gdGlsZWRiX2RpbSgiZGltIiwgYygxTCwgNEwpLCAyTCwgIklOVDMyIikKYGBgCgoKIyMjIENyZWF0ZSBBcnJheSBEb21haW4KCmBgYHtyIGNyZWF0YXJyZG9tfQpsaWJyYXJ5KHRpbGVkYikKCiMgIC4uIGNyZWF0ZSBkaW1lbnNpb25zIGBkaW0xYCwgYGRpbTJgCmRpbTEgPC0gdGlsZWRiX2RpbSgiZGltMSIsIGMoMUwsIDRMKSwgMkwsICJJTlQzMiIpCmRpbTIgPC0gdGlsZWRiX2RpbSgiZGltMiIsIGMoMUwsIDJMKSwgMkwsICJJTlQzMiIpCgojIENyZWF0ZSBkb21haW4gd2l0aCB0d28gZGltZW5zaW9ucwojIEluIEMrKzogZG9tYWluLmFkZF9kaW1lbnNpb25zKGRpbTEpLmFkZF9kaW1lbnNpb24oZGltMikKZG9tIDwtIHRpbGVkYl9kb21haW4oZGltcyA9IGMoZGltMSwgZGltMikpCmBgYAoKIyMjIENyZWF0aW5nIEF0dHJpYnV0ZXMKCmBgYHtyIGNyZWF0ZWF0dHJ9CiMgQ3JlYXRlIGF0dHJpYnV0ZQojIEluIEMrKzogQXR0cmlidXRlOjpjcmVhdGU8VD4oY3R4LCAiYXR0ciIpCmF0dHIgPC0gdGlsZWRiX2F0dHIoImF0dHIiLCAiSU5UMzIiKQpgYGAKCmBgYHtyIGNyZWF0ZWF0dHJ2YXJudW19CiMgV2UgY2FuIGFsc28gc2V0IHRoZSBudW1iZXIgb2YgYXR0cmlidXRlcyB0byBhIHZhbHVlIG90aGVyIHRoYW4gb25lCnRpbGVkYjo6OmxpYnRpbGVkYl9hdHRyaWJ1dGVfc2V0X2NlbGxfdmFsX251bShhdHRyQHB0ciwgMykKCiMgQW5kIHdlIGNhbiBzZXQgdGhlIGEgdmFyaWFibGUgbnVtYmVyIG9mIGF0dHJpYnV0ZXMgKHVzaW5nIE5BIHRvIHNlbGVjdCB2YXJpYWJsZSBzaXplKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXR0cmlidXRlX3NldF9jZWxsX3ZhbF9udW0oYXR0ckBwdHIsIE5BKQojIyBUT0RPOiBSIGZ1bmN0aW9uIGZvciBsZXZlbCBzZXR0ZXIKYGBgCgojIyMjIFNldHRpbmcgYSBDb21wcmVzc29yCgpgYGB7ciBzZXRjb21wcn0KY29tcCA8LSB0aWxlZGJfZmlsdGVyKCJHWklQIikKdGlsZWRiX2ZpbHRlcl9zZXRfb3B0aW9uKGNvbXAsIkNPTVBSRVNTSU9OX0xFVkVMIiwgMTApCgojIENyZWF0ZSBhIGZpbHRlciBsaXN0IHdpdGggdGhlIGNvbXByZXNzb3IKZmlsdGVyX2xpc3QgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGNvbXApCgojIENyZWF0ZSBhdHRyaWJ1dGUgd2l0aCB0aGUgZmlsdGVyIGxpc3QKYXR0ciA8LSB0aWxlZGJfYXR0cigiYXR0ciIsICJJTlQzMiIsIGZpbHRlcl9saXN0ID0gZmlsdGVyX2xpc3QpCmBgYAoKCiMjIyMgU2V0dGluZyBPdGhlciBGaWx0ZXJzCgpgYGB7ciBzZXRmaWxyfQojIENyZWF0ZSBmaWx0ZXJzCmYxIDwtIHRpbGVkYl9maWx0ZXIoIkJJVF9XSURUSF9SRURVQ1RJT04iKQpmMiA8LSB0aWxlZGJfZmlsdGVyKCJaU1REIikKCiMgQ3JlYXRlIGEgZmlsdGVyIGxpc3Qgd2l0aCB0aGUgdHdvIGZpbHRlcnMKZmlsdGVyX2xpc3QgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KGMoZjEsZjIpKQoKIyBDcmVhdGUgYXR0cmlidXRlIHdpdGggdGhlIGZpbHRlciBsaXN0CmF0dHIgPC0gdGlsZWRiX2F0dHIoImF0dHIiLCAiSU5UMzIiLCBmaWx0ZXJfbGlzdCA9IGZpbHRlcl9saXN0KQpgYGAKCgojIyMjIFNldHRpbmcgdGhlIFRpbGUgQ2h1bmsgU2l6ZQoKYGBge3Igc2V0dGlsZWNodW5rc2l6ZX0KIyAuLi4gY3JlYXRlIGZpbHRlciBsaXN0CnNldF9tYXhfY2h1bmtfc2l6ZShmaWx0ZXJfbGlzdCwgMTAwMDApCmBgYAoKCiMjIyBDcmVhdGluZyB0aGUgQXJyYXkgU2NoZW1hCgpgYGB7ciBjcmVhdGVhcnJzY2hlbWF9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCmF0dHIxIDwtIHRpbGVkYl9hdHRyKCJhdHRyMSIsICJJTlQzMiIsIGZpbHRlcl9saXN0ID0gZmlsdGVyX2xpc3QpCmF0dHIyIDwtIHRpbGVkYl9hdHRyKCJhdHRyMiIsICJGTE9BVDY0IiwgZmlsdGVyX2xpc3QgPSBmaWx0ZXJfbGlzdCkKCiMgQ3JlYXRlIGEgZGVuc2UgYXJyYXkKc2NoZW1hIDwtIHRpbGVkYl9hcnJheV9zY2hlbWEoZG9tLCBjKGF0dHIxLCBhdHRyMiksIHNwYXJzZSA9IEZBTFNFKQojIE9yLCBjcmVhdGUgYSBzcGFlc2UgYXJyYXkKIyBzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGMoYXR0cjEsIGF0dHIyKSwgc3BhcnNlID0gVFJVRSkKYGBgCgojIyMjIFNldHRpbmcgdGhlIFRpbGUgYW5kIENlbGwgT3JkZXIKCmBgYHtyIHNldHRpbGVjZWxsb3JkZXJ9CiMgLi4uIGNyZWF0ZSBkb21haW4gZG9tCiMgLi4uIGNyZWF0ZSBhdHRyaWJ1dGVzIGF0dHIxLCBhdHRyMgoKIyBUaGUgdGlsZSBhbmQgb3JkZXIgY2FuIGJlICJST1dfTUFKT1IiIG9yICJDT0xfTUFKT1IiCnNjaGVtYSA8LSB0aWxlZGJfYXJyYXlfc2NoZW1hKGRvbSwgYyhhdHRyMSwgYXR0cjIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsX29yZGVyID0gIkNPTF9NQUpPUiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVfb3JkZXIgPSAiUk9XX01BSk9SIikKYGBgCgojIyMjIFNldHRpbmcgdGhlIERhdGEgVGlsZSBDYXBhY2l0eQoKYGBge3Igc2V0dGlsZWNhcGFjaXR5fQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9jYXBhY2l0eShzY2hlbWFAcHRyLCAxMDAwMDApCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfZ2V0X2NhcGFjaXR5KHNjaGVtYUBwdHIpCiMjIFRPRE8gUiBmdW5jdGlvbiBmb3IgYWNjZXNzb3IKYGBgCgojIyMjIFNldHRpbmcgQ29vcmRpbmF0ZSBhbmQgT2Zmc2V0IEZpbHRlcnMKCmBgYHtyIHNldGNvb3Jkb2Zmc2V0ZmlsdH0KIyAuLi4gY3JlYXRlIGRvbWFpbiBkb20KIyAuLi4gY3JlYXRlIGF0dHJpYnV0ZXMgYXR0cjEsIGF0dHIyCiMgLi4uIGNyZWF0ZSBmaWx0ZXIgbGlzdHMgZmwxLCBmbDIsIHNpbWlsYXIgdG8gYXR0cmlidXRlcwpmMSA8LSB0aWxlZGJfZmlsdGVyKCJCSVRfV0lEVEhfUkVEVUNUSU9OIikKZjIgPC0gdGlsZWRiX2ZpbHRlcigiWlNURCIpCmZsMSA8LSB0aWxlZGJfZmlsdGVyX2xpc3QoYyhmMSkpCmZsMiA8LSB0aWxlZGJfZmlsdGVyX2xpc3QoYyhmMikpCgojIENyZWF0ZSB0aGUgc2NoZW1hIHNldHRpbmcgdGhlIGNvb3JkaW5hdGVzIGFuZCBvZmZzZXRzIGZpbHRlciBsaXN0cwpzY2hlbWEgPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGMoYXR0cjEsIGF0dHIyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRzX2ZpbHRlcl9saXN0ID0gZmwxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRzX2ZpbHRlcl9saXN0ID0gZmwyKQpgYGAKCgojIyMjIENoZWNraW5nIENvcnJlY3RuZXNzCgpgYGB7ciBhcnJheXNjaGVtYWNoZWNrfQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX2NoZWNrKHNjaGVtYUBwdHIpCiMjIFRPRE86IFIgZnVuY3Rpb24gZm9yIGFjY2VzcwpgYGAKCgoKIyMjIENyZWF0aW5nIHRoZSBBcnJheQoKYGBge3IgY3JlYXRlYXJyYXksIGV2YWw9RkFMU0V9CiMgLi4uIGNyZWF0ZSBhcnJheSBzY2hlbWEKCiMgQ3JlYXRlIHRoZSBhcnJheQp0aWxlZGJfYXJyYXlfY3JlYXRlKHVyaWRlbnNlLCBzY2hlbWEpCmBgYAoKIyMjIENyZWF0aW5nIEVuY3J5cHRlZCBBcnJheXMKCmBgYHtyIGNyZWF0ZXdpdGhrZXl9CmVuY3J5cHRpb25fa2V5IDwtICIwMTIzNDU2Nzg5YWJjZGVGMDEyMzQ1Njc4OWFiY2RlRiIKdXJpZGVuc2V3a2V5IDwtIGZpbGUucGF0aCh0ZGlyLCAiZGVuc2V3a2V5IikKaWYgKGRpci5leGlzdHModXJpZGVuc2V3a2V5KSkgdW5saW5rKHVyaWRlbnNld2tleSwgcmVjdXJzaXZlPVRSVUUpCgojIHNob3J0Y3V0OiBib3Jyb3cgc2NoZW1hIGZyb20gZGVuc2UgYXJyYXk7IGNvdWxkIGNyZWF0ZSBzY2hlbWEgdG9vCnNjaGVtYSA8LSBzY2hlbWEodGlsZWRiX2RlbnNlKHVyaWRlbnNlKSkKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2NyZWF0ZV93aXRoX2tleSh1cmlkZW5zZXdrZXksIHNjaGVtYUBwdHIsIGVuY3J5cHRpb25fa2V5KQojI1RPRE86IFIgc3VwcG9ydApgYGAKCgojIyBXcml0aW5nIEFycmF5cwoKIyMjIFdyaXRpbmcgaW4gRGVuc2UgU3ViYXJyYXlzCgpgYGB7ciB3cml0ZWRlbnNlc3ViYXJyLCBldmFsPUZBTFNFfQojIyBwcmVwYXJlIGEgbGFyZ2VyIDUgeCA1IHRvIGVtYmVkIGludG8KdG1wIDwtIHRlbXBmaWxlKCkKZDEgIDwtIHRpbGVkYl9kaW0oZG9tYWluID0gYygxTCwgNUwpKQpkMiAgPC0gdGlsZWRiX2RpbShkb21haW4gPSBjKDFMLCA1TCkpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGMoZDEsIGQyKSkKdmFsIDwtIHRpbGVkYl9hdHRyKG5hbWU9InZhbCIsIHR5cGUgPSAiSU5UMzIiKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGModmFsKSkKdGlsZWRiX2FycmF5X2NyZWF0ZSh0bXAsIHNjaCkKCmRhdCA8LSBtYXRyaXgoYXMuaW50ZWdlcihybm9ybSgyNSkqMTAwKSwgNSwgNSkKYXJyIDwtIHRpbGVkYl9kZW5zZSh0bXAsIGFzLmRhdGEuZnJhbWU9RkFMU0UpCmFycltdIDwtIGRhdAoKCiMgUHJlcGFyZSBhIDJ4MyBkZW5zZSBhcnJheQojIENvbnRyYXJ5IHRvIFB5dGhvbiwgUiBieSBkZWZhdWx0IHN0b3JlcyBhcnJheXMgaW4gY29sLW1ham9yIG9yZGVyCmRhdGEgPC0gIGFycmF5KGMoMUwsIDRMLCAyTCwgNUwsIDNMLCA2TCksIGRpbT1jKDIsMykpCgojIFByZXBhcmUgdGhlIFsxLDJdIHggWzIsNF0gc3ViYXJyYXkgdG8gd3JpdGUgdG8KSSA8LSBjKDE6MikKSiA8LSBjKDI6NCkKCiMgT3BlbiB0aGUgYXJyYXkgYW5kIHdyaXRlIHRoZSBkYXRhIHRvIGl0CkEgPC0gdGlsZWRiX2RlbnNlKHVyaSA9IHRtcCkKQVtJLCBKXSA8LSBkYXRhCgp1bmxpbmsodG1wLCByZWN1cnNpdmU9VFJVRSkKYGBgCgoKIyMjIyBCYXNpYyBXcml0aW5nIHVzaW5nIExvdy1MZXZlbCBDb2RlCgpgYGB7ciBiYXNpc2N3cml0aW5nbG93bGV2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiV1JJVEUiKQoKIyMgZGF0YTogc2ltcGxlIChpbnRlZ2VyIHNlcXVlbmNlKSBvZiAxOjE2IHRpbWVzIDEwCnZlYyA8LSAxOjE2ICogMTBMCnN1YmFyciA8LSBjKDFMLDRMLCAxTCw0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiV1JJVEUiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdmVjKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnJlcyA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQpgYGAKCgojIyMgV3JpdGluZyBTcGFyc2UgQ2VsbHMKCmBgYHtyIHdyaXRlc3BhcnNlY2VsbHN9CnRtcCA8LSB1cmlzcGFyc2UKdW5saW5rKHRtcCwgcmVjdXJzaXZlPVRSVUUpCgpkMSAgPC0gdGlsZWRiX2RpbShkb21haW4gPSBjKDFMLCA1TCkpCmQyICA8LSB0aWxlZGJfZGltKGRvbWFpbiA9IGMoMUwsIDVMKSkKZG9tIDwtIHRpbGVkYl9kb21haW4oYyhkMSwgZDIpKQp2YWwgPC0gdGlsZWRiX2F0dHIoInZhbCIsIHR5cGUgPSAiSU5UMzIiKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIHZhbCwgc3BhcnNlPVRSVUUpCnRpbGVkYl9hcnJheV9jcmVhdGUodG1wLCBzY2gpCgoKIyBQcmVwYXJlIHNvbWUgZGF0YQpkYXRhIDwtIGMoM0wsIDRMLCAxTCwgMkwpCgpJIDwtIGMoMywgNCwgMSwgMikKSiA8LSBjKDMsIDQsIDIsIDEpCgojIE9wZW4gdGhlIGFycmF5IGFuZCB3cml0ZSB0aGUgZGF0YSB0byBpdApBIDwtIHRpbGVkYl9zcGFyc2UodXJpID0gdG1wKQpBW0ksIEpdIDwtIGRhdGEKCmBgYAoKCiMjIyBXcml0aW5nIEVuY3J5cHRlZCBBcnJheXMKCmBgYHtyIHdyaXRpbmdlbmNyeXB0ZWRsb3dsZXZlbH0KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fd2l0aF9rZXkoY3R4QHB0ciwgdXJpZGVuc2V3a2V5LCAiV1JJVEUiLCBlbmNyeXB0aW9uX2tleSkKCiMjIGRhdGE6IHNpbXBsZSAoaW50ZWdlciBzZXF1ZW5jZSkgb2YgMToxNiB0aW1lcyAxMAp2ZWMgPC0gMToxNiAqIDEwTApzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKIyBUT0RPIEhpZ2hlci1sZXZlbCBSIHN1cHBvcnQKCmBgYAoKCgoKIyMjIEZpeGVkLWxlbmd0aCBBdHRyaWJ1dGVzCgpgYGB7ciBmaXhlZGxlbmd0aGF0dHJpYnV0ZXN9CmlmIChkaXIuZXhpc3RzKHVyaWRlbnNlZml4KSkgdW5saW5rKHVyaWRlbnNlZml4LCByZWN1cnNpdmU9VFJVRSkKZDEgIDwtIHRpbGVkYl9kaW0oZG9tYWluID0gYygxTCwgNEwpKQpkMiAgPC0gdGlsZWRiX2RpbShkb21haW4gPSBjKDFMLCA0TCkpCmRvbSA8LSB0aWxlZGJfZG9tYWluKGMoZDEsIGQyKSkKCnZlYyA8LSAxOjMyICogMTBMCmF0dHIgPC0gdGlsZWRiX2F0dHIoImEiLCB0eXBlID0gcl90b190aWxlZGJfdHlwZSh2ZWMpKQoKIyMgc2V0IHRvIHR3byB2YWx1ZXMgcGVyIGNlbGwKdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9zZXRfY2VsbF92YWxfbnVtKGF0dHJAcHRyLCAyKQpzY2ggPC0gdGlsZWRiX2FycmF5X3NjaGVtYShkb20sIGF0dHIpCnRpbGVkYl9hcnJheV9jcmVhdGUodXJpZGVuc2VmaXgsIHNjaCkKCmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlZml4LCAiV1JJVEUiKQpzdWJhcnIgPC0gYygxTCw0TCwgMUwsNEwpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHZlYykKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKCiNUT0RPIEhpZ2hlci1sZXZlbCBSIHN1cHBvcnQKYGBgCgojIyMgVmFyLWxlbmd0aCBBdHRyaWJ1dGVzCgpgYGB7cn0KaWYgKGRpci5leGlzdHModXJpZGVuc2V2YXIpKSB1bmxpbmsodXJpZGVuc2V2YXIsIHJlY3Vyc2l2ZT1UUlVFKQojIyBEZWZpbmUgYXJyYXkKIyMgVGhlIGFycmF5IHdpbGwgYmUgNHg0IHdpdGggZGltZW5zaW9ucyAicm93cyIgYW5kICJjb2xzIiwgd2l0aCBkb21haW4gWzEsNF0uCmRvbSA8LSB0aWxlZGJfZG9tYWluKGRpbXMgPSBjKHRpbGVkYl9kaW0oInJvd3MiLCBjKDFMLCA0TCksIDRMLCAiSU5UMzIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZWRiX2RpbSgiY29scyIsIGMoMUwsIDRMKSwgNEwsICJJTlQzMiIpKSkKCgphdHRyIDwtIHRpbGVkYl9hdHRyKCJhMSIsIHR5cGUgPSAiQ0hBUiIpCiMjIHNldCB0byB2YXJpYWJsZSBsZW5ndGgKdGlsZWRiOjo6bGlidGlsZWRiX2F0dHJpYnV0ZV9zZXRfY2VsbF92YWxfbnVtKGF0dHJAcHRyLCBOQSkKCiMjIG5vdyBzZXQgdGhlIHNjaGVtYQpjdHggPC0gdGlsZWRiX2N0eCgpCnNjaHB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX2NyZWF0ZShjdHhAcHRyLCAiREVOU0UiKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9kb21haW4oc2NocHRyLCBkb21AcHRyKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfc2NoZW1hX3NldF9jZWxsX29yZGVyKHNjaHB0ciwgIlJPV19NQUpPUiIpCnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfc2V0X3RpbGVfb3JkZXIoc2NocHRyLCAiUk9XX01BSk9SIikKdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X3NjaGVtYV9hZGRfYXR0cmlidXRlKHNjaHB0ciwgYXR0ckBwdHIpCgoKCiMjIENyZWF0ZSB0aGUgKGVtcHR5KSBhcnJheSBvbiBkaXNrLgp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY3JlYXRlKHVyaWRlbnNldmFyLCBzY2hwdHIpCgpkYXRhIDwtICJhYmJjY2NkZGVlZWZnaGhoaWpqamtrbG1ub29wIjsKb2Zmc2V0cyA8LSBjKDBMLCAxTCwgM0wsIDZMLCA4TCwgMTFMLCAxMkwsIDEzTCwgMTZMLCAxN0wsIDIwTCwgMjJMLCAyM0wsIDI0TCwgMjVMLCAyN0wpCgpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZXZhciwgIldSSVRFIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJXUklURSIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQoKYnVmcHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9idWZmZXJfdmFyX2NoYXJfY3JlYXRlKG9mZnNldHMsIGRhdGEpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcl92YXJfY2hhcihxcnlwdHIsICJhMSIsIGJ1ZnB0cikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQp0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJycHRyKQoKI1RPRE8gSGlnaGVyLWxldmVsIFIgc3VwcG9ydApgYGAKCgojIyMgR2V0dGluZyB0aGUgRnJhZ21lbnQgSW5mbwoKYGBge3IgZnJhZ21lbnRpbmZvfQojIyBjb250aW51aW5nIGZyb20gcHJldmlvdXMgZXhhbXBsZSBvbiBkZW5zZSB2YXJpYWJsZSBsZW5ndGggYXJyYXkKIyMgKGJ1dCB0aGlzIHdvcmtzIG9mIGNvdXJzZSB3aXRoIGFueSBhcnJheSBhZnRlciBhIHdyaXRlIGlzIG5lZWRlZApudW1mcmFnIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9nZXRfZnJhZ21lbnRfbnVtKHFyeXB0cikKdXJpdHh0IDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9nZXRfZnJhZ21lbnRfdXJpKHFyeXB0ciwgMCkKCiMjVE9ETyBIaWdoZXItbGV2ZWwgUiBzdXBwb3J0CmBgYAoKIyMgUmVhZGluZyBBcnJheXMKCiMjIyBSZWFkaW5nIHRoZSBBcnJheSBTY2hlbWEKCmBgYHtyIHNjaGVtYWxvYWR9CmFycmF5X25hbWUgPC0gdXJpc3BhcnNlCkEgPC0gdGlsZWRiX3NwYXJzZSh1cmkgPSBhcnJheV9uYW1lKQojIGNhbiBhbHNvIGxvYWQgZGVuc2UKc2NoIDwtIHNjaGVtYShBKQojIGNhbiBhbHNvIG9wZW4gZW5jcnlwdGVkIGFycmF5cyB3aXRoIGtleQpgYGAKCiMjIyMgSW5zcGVjdGluZyB0aGUgYXJyYXkgc2NoZW1hCgpgYGB7ciBzY2hlbWFpbnNwZWN0fQphcnJheV9uYW1lIDwtIHVyaXNwYXJzZQoKIyBHZXQgYXJyYXkgc2NoZW1hCkEgPC0gdGlsZWRiX3NwYXJzZSh1cmkgPSBhcnJheV9uYW1lKQojIG9yIHVzZSB0aWxlZGJfZGVuc2UodXJpID0gYXJyYXlfbmFtZSkgZm9yIGRlbnNlCnNjaGVtYSA8LSBzY2hlbWEoQSkKCiMgR2V0IGFycmF5IHR5cGUKc3BhcnNlIDwtIGlzLnNwYXJzZShzY2hlbWEpCgojIEdldCB0aWxlIGNhcGFjaXR5CnRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9zY2hlbWFfZ2V0X2NhcGFjaXR5KHNjaEBwdHIpCiMgVE9ETzogUiBhY2Nlc3NvciBmb3IgdGlsZQoKIyBHZXQgdGlsZSBvcmRlcgp0X29yZGVyIDwtIHRpbGVfb3JkZXIoc2NoZW1hKQoKIyBHZXQgY2VsbCBvcmRlcgpjX29yZGVyIDwtIGNlbGxfb3JkZXIoc2NoZW1hKQoKIyBHZXQgY29vcmRpbmF0ZXMgYW5kIG9mZnNldCBmaWx0ZXIgbGlzdApyZXNsaXN0IDwtIGZpbHRlcl9saXN0KHNjaGVtYSkKCiMgR2V0IHRoZSBhcnJheSBkb21haW4KZG9tIDwtIGRvbWFpbihzY2hlbWEpCgojIEdldCBhbGwgYXR0cmlidXRlcyBhcyBsaXN0CmF0dHJzIDwtIGF0dHJzKHNjaGVtYSkKCiMgR2V0IGF0dHJpYnV0ZSBmcm9tIG5hbWUKYXR0ciA8LSBhdHRycyhzY2hlbWEsICJhdHRyIikKCiMgRHVtcCB0aGUgYXJyYXkgc2NoZW1hIGluIEFTQ0lJIGZvcm1hdCB0byBzdGRvdXQKc2hvdyhzY2hlbWEpCmBgYAoKCiMjIyMgSW5zcGVjdGluZyBEb21haW4KCmBgYHtyIGluc3BlY3Rkb21haW59CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGRvbWFpbiBmcm9tIHNjaGVtYQpkb20gPC0gZG9tYWluKHNjaGVtYSkKCiMgR2V0IHRoZSBkb21haW4gZGF0YXR5cGUgKGkuZS4sIHRoZSBkYXRhdHlwZSBvZiBhbGwgZGltZW5zaW9ucykKdHlwZSA8LSBkYXRhdHlwZShkb20pCgojIEdldCBudW1iZXIgb2YgZGltZW5zaW9ucwpkaW1fbnVtIDwtIGRpbShkb20pCgojIEdldCBhbGwgZGltZW5zaW9uCmRpbXMgPC0gZGltZW5zaW9ucyhkb20pCgojIER1bXAgdGhlIGRvbWFpbiBpbiBBU0NJSSBmb3JtYXQgaW4gdGhlIHNlbGVjdGVkIG91dHB1dApzaG93KGRvbSkKYGBgCgojIyMjIEluc3BlY3RpbmcgRGltZW5zaW9ucwoKYGBge3IgaW5zcGVjdGRpbWVuc2lvbnMsIGV2YWw9RkFMU0V9CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGRvbWFpbgojIC4uLiBnZXQgZGltZW5zaW9uIGJ5IGluZGV4IG9yIG5hbWUKCiNGSVhNRQoKIyBHZXQgZGltZW5zaW9uIG5hbWUKZGltX25hbWUgPC0gbmFtZShkaW0pCgojIEdldCBkaW1lbnNpb24gZGF0YXR5cGUKZGltX3R5cGUgPC0gZGF0YXR5cGUoZGltKQoKIyBHZXQgZGltZW5zaW9uIGRvbWFpbgpkb21haW4gPC0gZG9tYWluKGRpbSkKCiMgR2V0IHRpbGUgZXh0ZW50CnRpbGVfZXh0ZW50IDwtIHRpbGUoZGltKQoKIyBEdW1wIHRoZSBkaW1lbnNpb24gaW4gQVNDSUkgZm9ybWF0IGluIHRoZSBzZWxlY3RlZCBvdXRwdXQKc2hvdyhkaW0pCgpgYGAKCgojIyMjIEluc3BlY3RpbmcgQXR0cmlidXRlcwoKYGBge3IgaW5zcGVjdGF0dHIsIGV2YWw9RkFMU0V9CiMgLi4uIGdldCBhcnJheSBzY2hlbWEKIyAuLi4gZ2V0IGF0dHJpYnV0ZSBieSBpbmRleCBvciBuYW1lCgpzdG9waWZub3QoaXMubnVsbChhdHRyKSkKIyBHZXQgYXR0cmlidXRlIG5hbWUKYXR0cl9uYW1lIDwtIG5hbWUoYXR0cikKCiMgR2V0IGF0dHJpYnV0ZSBkYXRhdHlwZQphdHRyX3R5cGUgPC0gZGF0YXR5cGUoYXR0cikKCiMgR2V0IGZpbHRlciBsaXN0CmZpbHRlcl9saXN0IDwtIGZpbHRlcl9saXN0KGF0dHIpCgojIENoZWNrIGlmIGF0dHJpYnV0ZSBpcyB2YXJpYWJsZS1sZW5ndGgKIyB2YXJpYWJsZSBsZW5ndGggYXR0cmlidHVlcyBhcmUgbm90IHN1cHBvcnRlZCBpbiBSIGN1cnJlbnRseQoKIyBHZXQgbnVtYmVyIG9mIHZhbHVlcyBwZXIgY2VsbApudW0gPC0gbmNlbGxzKGF0dHIpCgojIEdldCBjZWxsIHNpemUgZm9yIHRoaXMgYXR0cmlidXRlCnN6IDwtLSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXR0cmlidXRlX2dldF9jZWxsX3ZhbChhdHRyQHB0cikKCiMgRHVtcCB0aGUgYXR0cmlidXRlIGluIEFTQ0lJIGZvcm1hdCBpbiB0aGUgc2VsZWN0ZWQgb3V0cHV0CnNob3coYXR0cikKYGBgCgoKCiMjIyMgSW5zcGVjdGluZyBGaWx0ZXJzCgpgYGB7ciBpbnNwZWN0ZmlsdGVycywgZXZhbD1GQUxTRX0KZmwgPC0gdGlsZWRiX2ZpbHRlcl9saXN0KCkKCiMgZ2V0IG51bWJlciBvZiBmaWx0ZXIKdGlsZWRiOjo6bGlidGlsZWRiX2ZpbHRlcl9saXN0X2dldF9uZmlsdGVycyhmbEBwdHIpCgojIGdldCBtYXggY2h1bmsgc2l6ZQp0aWxlZGI6OjpsaWJ0aWxlZGJfZmlsdGVyX2xpc3RfZ2V0X21heF9jaHVua19zaXplKGZsQHB0cikKCiMgZ2V0IGZpbHRlciBmcm9tIGluZGV4CmluZCA8LSBpCnRpbGVkYjo6OmxpYnRpbGVkYl9maWx0ZXJfbGlzdF9nZXRfZmlsdGVyX2Zyb21faW5kZXgoZmxAcHRyLCBpbmQpCmBgYAoKIyMjIEJhc2ljIFJlYWRpbmcKCmBgYHtyIGJhc2lzY3JlYWRpbmd9CiMgQ3JlYXRlIGEgVGlsZURCIGNvbnRleHQKY3R4IDwtIHRpbGVkYl9jdHgoKQoKIyBPcGVuIGEgZGVuc2UgYXJyYXkKQSA8LSB0aWxlZGJfZGVuc2UodXJpID0gdXJpZGVuc2UsIGN0eD1jdHgpCgojIE9yLCBvcGVuIGEgc3BhcnNlIGFycmF5CiMgQSA8LSB0aWxlZGJfc3BhcnNlKHVyaSA9ICI8YXJyYXktdXJpPiIsIGN0eD1jdHgpCgojIFNsaWNlIG9ubHkgcm93cyAxLCAyIGFuZCBjb2xzIDIsIDMsIDQKZGF0YSA8LSBBWzE6MiwgMjo0XQpzaG93KGRhdGEpCmBgYAoKIyMjIyBCYXNpYyBSZWFkaW5nIHVzaW5nIExvdy1MZXZlbCBDb2RlCgpgYGB7ciBiYXNpc2NyZWFkaW5nbG93bGV2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiUkVBRCIpCiMjIHN1YmFycmF5IG9mIHJvd3MgMSwyIGFuZCBjb2xzIDIsMyw0CnN1YmFyciA8LSBjKDFMLDJMLCAyTCw0TCkKCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X3N1YmFycmF5KHFyeXB0ciwgc3ViYXJyKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9sYXlvdXQocXJ5cHRyLCAiUk9XX01BSk9SIikKdiA8LSBpbnRlZ2VyKDYpICAjIHJlc2VydmUgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2KQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCnByaW50KHYpICAgICAgICAgIyB1bmZvcm1lZCBhcnJheSwgbm8gY29vcmRpbmF0ZXMKcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCmBgYAoKIyMjIFJlYWRpbmcgRW5jcnlwdGVkIEFycmF5cwoKYGBge3IgcmVhZGVuY3J5cHRlZH0KY3R4IDwtIHRpbGVkYl9jdHgoKQphcnJwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X29wZW5fd2l0aF9rZXkoY3R4QHB0ciwgdXJpZGVuc2V3a2V5LCAiUkVBRCIsIGVuY3J5cHRpb25fa2V5KQoKIyMgc3ViYXJyYXkgb2Ygcm93cyAxLDIgYW5kIGNvbHMgMiwzLDQKc3ViYXJyIDwtIGMoMUwsMkwsIDJMLDRMKQoKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeShjdHhAcHRyLCBhcnJwdHIsICJSRUFEIikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2xheW91dChxcnlwdHIsICJST1dfTUFKT1IiKQp2IDwtIGludGVnZXIoNikgICMgcmVzZXJ2ZSBzcGFjZQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHYpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKcHJpbnQodikgICAgICAgICAjIHVuZm9ybWVkIGFycmF5LCBubyBjb29yZGluYXRlcwpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKCiMjIFRPRE8gb3BlbiBhdCB0aW1lc3RhbXAgZXhhbXBsZQpgYGAKCiMjIyBNdWx0aS1yYW5nZSBTdWJhcnJheXMKCmBgYHtyIG11bHRpcmFuZ2V9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiUkVBRCIpCgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQoKIyMgcmFuZ2Ugb2Ygcm93cyAxIGFuZCAyLCBhbmQgNCBmb3IgZGltIDEsIGFsbCByb3dzIGZvciBkaW0gMgpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X2FkZF9yYW5nZShxcnlwdHIsIDAsIDFMLCAyTCkKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9hZGRfcmFuZ2UocXJ5cHRyLCAwLCA0TCwgNEwpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfYWRkX3JhbmdlKHFyeXB0ciwgMSwgMUwsIDRMKQoKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnYgPC0gaW50ZWdlcigxMikgICMgcmVzZXJ2ZSBzcGFjZQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9idWZmZXIocXJ5cHRyLCAiYSIsIHYpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc3VibWl0KHFyeXB0cikKcHJpbnQodikgICAgICAgICAjIHVuZm9ybWVkIGFycmF5LCBubyBjb29yZGluYXRlcwpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKYGBgCgojIyMgSW5jb21wbGV0ZSBRdWVyaWVzCgpgYGB7ciBpbmNvbXBsZXRlcmVhZHN9CmN0eCA8LSB0aWxlZGJfY3R4KCkKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuKGN0eEBwdHIsIHVyaWRlbnNlLCAiUkVBRCIpCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnkoY3R4QHB0ciwgYXJycHRyLCAiUkVBRCIpCnN1YmFyciA8LSBjKDFMLDRMLCAxTCw0TCkKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfc3ViYXJyYXkocXJ5cHRyLCBzdWJhcnIpCnZlYyA8LSBpbnRlZ2VyKDQpICAjIHJlc2VydmUgKGluc3VmZmljaWVudCkgc3BhY2UKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfYnVmZmVyKHFyeXB0ciwgImEiLCB2ZWMpCmZpbmlzaGVkIDwtIEZBTFNFCndoaWxlICghZmluaXNoZWQpIHsKICBxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3N1Ym1pdChxcnlwdHIpCiAgcHJpbnQodmVjKQogIGZpbmlzaGVkIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdGF0dXMocXJ5cHRyKSA9PSAiQ09NUExFVEUiCn0KcmVzIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9jbG9zZShhcnJwdHIpCmBgYAoKIyMjIFJlc3VsdCBFc3RpbWF0aW9uCgpgYGB7ciByZXN1bHRlc3RpbWF0aW9ufQpjdHggPC0gdGlsZWRiX2N0eCgpCmFycnB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfb3BlbihjdHhAcHRyLCB1cmlkZW5zZXZhciwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQplc3RzeiA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfZ2V0X2VzdF9yZXN1bHRfc2l6ZV92YXIocXJ5cHRyLCAiYTEiKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKZXN0c3oKYGBgCgojIyMgVGltZSBUcmF2ZWxpbmcKCmBgYHtyIHRpbWV0cmF2ZWx9CmN0eCA8LSB0aWxlZGJfY3R4KCkKdHN0YW1wIDwtIFN5cy50aW1lKCkgLSAxLjA7ICMgb25lIHNlY29uZHMgYWdvIChhcyB0aGUgYXJyYXlzIGNyZWF0ZWQgaGVyZSBhcmUgaW4gdGVtcC5maWxlcykKYXJycHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9hcnJheV9vcGVuX2F0KGN0eEBwdHIsIHVyaWRlbnNlLCAiUkVBRCIsIHRzdGFtcCkKc3ViYXJyIDwtIGMoMUwsMkwsIDJMLDRMKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5KGN0eEBwdHIsIGFycnB0ciwgIlJFQUQiKQpxcnlwdHIgPC0gdGlsZWRiOjo6bGlidGlsZWRiX3F1ZXJ5X3NldF9zdWJhcnJheShxcnlwdHIsIHN1YmFycikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zZXRfbGF5b3V0KHFyeXB0ciwgIlJPV19NQUpPUiIpCnYgPC0gaW50ZWdlcig2KSAgIyByZXNlcnZlIHNwYWNlCnFyeXB0ciA8LSB0aWxlZGI6OjpsaWJ0aWxlZGJfcXVlcnlfc2V0X2J1ZmZlcihxcnlwdHIsICJhIiwgdikKcXJ5cHRyIDwtIHRpbGVkYjo6OmxpYnRpbGVkYl9xdWVyeV9zdWJtaXQocXJ5cHRyKQpyZXMgPC0gdGlsZWRiOjo6bGlidGlsZWRiX2FycmF5X2Nsb3NlKGFycnB0cikKdgpgYGAKCiMjIEVtYmVkZGVkIFNRTAoKIyMgQXN5bmNocm9ub3VzIFF1ZXJpZXMKCiMjIENvbmZpZ3VyYXRpb24KCiMjIEFycmF5IE1ldGFkYXRhCgojIyMgV3JpdGluZyBBcnJheSBNZXRhZGF0YQoKYGBge3Igd3JpdGVtZXRhZGF0YX0KYXJyIDwtIHRpbGVkYl9kZW5zZSh1cmlkZW5zZSkKY2xvc2VfYW5kX3Jlb3BlbihhcnIsICJXUklURSIpCnJlcyA8LSB0aWxlZGJfcHV0X21ldGFkYXRhKGFyciwgImFhYSIsIDEwMEwpCnJlcyA8LSB0aWxlZGJfcHV0X21ldGFkYXRhKGFyciwgImJiIiwgYygxLjEsIDIuMikpCmludmlzaWJsZSh0aWxlZGI6OjpsaWJ0aWxlZGJfYXJyYXlfY2xvc2UoYXJyQHB0cikpCmBgYAoKIyMjIFJlYWRpbmcgQXJyYXkgTWV0YWRhdGEKCk9uZSBjYW4gcmVhZCBieSBrZXk6CgpgYGB7ciByZWFkbWV0YWRhdGF9CmNsb3NlX2FuZF9yZW9wZW4oYXJyLCAiUkVBRCIpCnRpbGVkYl9nZXRfbWV0YWRhdGEoYXJyLCAiYWFhIikKYGBgCgpPciBvbmUgY2FuIHJldHJpZXZlIGFsbCBtZXRhZGF0YSBhdCBvbmNlOgoKYGBge3IgcmVhZG1ldGFkYXRhYWxsfQptZCA8LSB0aWxlZGJfZ2V0X2FsbF9tZXRhZGF0YShhcnIpCnByaW50KG1kKQpgYGAKCiMjIyBEZWxldGluZyBBcnJheSBNZXRhZGF0YQoKYGBge3IgZGVsZXRlbWV0YWRhdGF9CmNsb3NlX2FuZF9yZW9wZW4oYXJyLCAiV1JJVEUiKQpyZXMgPC0gdGlsZWRiX2RlbGV0ZV9tZXRhZGF0YShhcnIsICJhYWEiKQoKYGBgCg==
diff --git a/man/tiledb_delete_metadata.Rd b/man/tiledb_delete_metadata.Rd index 77d630b4c3..2e6f66aab7 100644 --- a/man/tiledb_delete_metadata.Rd +++ b/man/tiledb_delete_metadata.Rd @@ -7,7 +7,7 @@ tiledb_delete_metadata(arr, key) } \arguments{ -\item{arr}{A TileDB Array object, or a character URI describing one} +\item{arr}{A TileDB Array object} \item{key}{A character value describing a metadata key} } diff --git a/man/tiledb_get_metadata.Rd b/man/tiledb_get_metadata.Rd index 7ecdb85388..a7358e0c8e 100644 --- a/man/tiledb_get_metadata.Rd +++ b/man/tiledb_get_metadata.Rd @@ -12,7 +12,8 @@ tiledb_get_metadata(arr, key) \item{key}{A character value describing a metadata key} } \value{ -A object stored in the Metadata under the given key +A object stored in the Metadata under the given key, +or \sQuote{NULL} if none found. } \description{ Return a TileDB Array Metadata object given by key diff --git a/man/tiledb_has_metadata.Rd b/man/tiledb_has_metadata.Rd index 5891ec9656..6c9569389b 100644 --- a/man/tiledb_has_metadata.Rd +++ b/man/tiledb_has_metadata.Rd @@ -7,7 +7,7 @@ tiledb_has_metadata(arr, key) } \arguments{ -\item{arr}{A TileDB Array object, or a character URI describing one} +\item{arr}{A TileDB Array object} \item{key}{A character value describing a metadata key} } diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 2e1c07b74e..c7cdd46ad8 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -6,172 +6,6 @@ using namespace Rcpp; -// has_metadata_simple -bool has_metadata_simple(const std::string array_name, const std::string key); -RcppExport SEXP _tiledb_has_metadata_simple(SEXP array_nameSEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(has_metadata_simple(array_name, key)); - return rcpp_result_gen; -END_RCPP -} -// has_metadata_ptr -bool has_metadata_ptr(Rcpp::XPtr array, const std::string key); -RcppExport SEXP _tiledb_has_metadata_ptr(SEXP arraySEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(has_metadata_ptr(array, key)); - return rcpp_result_gen; -END_RCPP -} -// num_metadata_simple -int num_metadata_simple(const std::string array_name); -RcppExport SEXP _tiledb_num_metadata_simple(SEXP array_nameSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - rcpp_result_gen = Rcpp::wrap(num_metadata_simple(array_name)); - return rcpp_result_gen; -END_RCPP -} -// num_metadata_ptr -int num_metadata_ptr(Rcpp::XPtr array); -RcppExport SEXP _tiledb_num_metadata_ptr(SEXP arraySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - rcpp_result_gen = Rcpp::wrap(num_metadata_ptr(array)); - return rcpp_result_gen; -END_RCPP -} -// get_metadata_simple -SEXP get_metadata_simple(const std::string array_name, const std::string key); -RcppExport SEXP _tiledb_get_metadata_simple(SEXP array_nameSEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(get_metadata_simple(array_name, key)); - return rcpp_result_gen; -END_RCPP -} -// get_metadata_ptr -SEXP get_metadata_ptr(Rcpp::XPtr array, const std::string key); -RcppExport SEXP _tiledb_get_metadata_ptr(SEXP arraySEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(get_metadata_ptr(array, key)); - return rcpp_result_gen; -END_RCPP -} -// put_metadata_simple -bool put_metadata_simple(const std::string array_name, const std::string key, const SEXP obj); -RcppExport SEXP _tiledb_put_metadata_simple(SEXP array_nameSEXP, SEXP keySEXP, SEXP objSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - Rcpp::traits::input_parameter< const SEXP >::type obj(objSEXP); - rcpp_result_gen = Rcpp::wrap(put_metadata_simple(array_name, key, obj)); - return rcpp_result_gen; -END_RCPP -} -// put_metadata_ptr -bool put_metadata_ptr(Rcpp::XPtr array, const std::string key, const SEXP obj); -RcppExport SEXP _tiledb_put_metadata_ptr(SEXP arraySEXP, SEXP keySEXP, SEXP objSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - Rcpp::traits::input_parameter< const SEXP >::type obj(objSEXP); - rcpp_result_gen = Rcpp::wrap(put_metadata_ptr(array, key, obj)); - return rcpp_result_gen; -END_RCPP -} -// get_metadata_from_index_ptr -SEXP get_metadata_from_index_ptr(Rcpp::XPtr array, const int idx); -RcppExport SEXP _tiledb_get_metadata_from_index_ptr(SEXP arraySEXP, SEXP idxSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - Rcpp::traits::input_parameter< const int >::type idx(idxSEXP); - rcpp_result_gen = Rcpp::wrap(get_metadata_from_index_ptr(array, idx)); - return rcpp_result_gen; -END_RCPP -} -// get_metadata_from_index_simple -SEXP get_metadata_from_index_simple(const std::string array_name, const int idx); -RcppExport SEXP _tiledb_get_metadata_from_index_simple(SEXP array_nameSEXP, SEXP idxSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - Rcpp::traits::input_parameter< const int >::type idx(idxSEXP); - rcpp_result_gen = Rcpp::wrap(get_metadata_from_index_simple(array_name, idx)); - return rcpp_result_gen; -END_RCPP -} -// get_all_metadata_simple -SEXP get_all_metadata_simple(const std::string array_name); -RcppExport SEXP _tiledb_get_all_metadata_simple(SEXP array_nameSEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - rcpp_result_gen = Rcpp::wrap(get_all_metadata_simple(array_name)); - return rcpp_result_gen; -END_RCPP -} -// get_all_metadata_ptr -SEXP get_all_metadata_ptr(Rcpp::XPtr array); -RcppExport SEXP _tiledb_get_all_metadata_ptr(SEXP arraySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - rcpp_result_gen = Rcpp::wrap(get_all_metadata_ptr(array)); - return rcpp_result_gen; -END_RCPP -} -// delete_metadata_simple -bool delete_metadata_simple(const std::string array_name, const std::string key); -RcppExport SEXP _tiledb_delete_metadata_simple(SEXP array_nameSEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< const std::string >::type array_name(array_nameSEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(delete_metadata_simple(array_name, key)); - return rcpp_result_gen; -END_RCPP -} -// delete_metadata_ptr -bool delete_metadata_ptr(Rcpp::XPtr array, const std::string key); -RcppExport SEXP _tiledb_delete_metadata_ptr(SEXP arraySEXP, SEXP keySEXP) { -BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; - Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< Rcpp::XPtr >::type array(arraySEXP); - Rcpp::traits::input_parameter< const std::string >::type key(keySEXP); - rcpp_result_gen = Rcpp::wrap(delete_metadata_ptr(array, key)); - return rcpp_result_gen; -END_RCPP -} // tiledb_datatype_R_type std::string tiledb_datatype_R_type(std::string datatype); RcppExport SEXP _tiledb_tiledb_datatype_R_type(SEXP datatypeSEXP) { @@ -1132,17 +966,75 @@ BEGIN_RCPP END_RCPP } // libtiledb_array_consolidate -std::string libtiledb_array_consolidate(XPtr ctx, std::string uri); -RcppExport SEXP _tiledb_libtiledb_array_consolidate(SEXP ctxSEXP, SEXP uriSEXP) { +void libtiledb_array_consolidate(XPtr ctx, std::string uri, Nullable> cfgptr); +RcppExport SEXP _tiledb_libtiledb_array_consolidate(SEXP ctxSEXP, SEXP uriSEXP, SEXP cfgptrSEXP) { BEGIN_RCPP - Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< XPtr >::type ctx(ctxSEXP); Rcpp::traits::input_parameter< std::string >::type uri(uriSEXP); - rcpp_result_gen = Rcpp::wrap(libtiledb_array_consolidate(ctx, uri)); + Rcpp::traits::input_parameter< Nullable> >::type cfgptr(cfgptrSEXP); + libtiledb_array_consolidate(ctx, uri, cfgptr); + return R_NilValue; +END_RCPP +} +// libtiledb_array_put_metadata +bool libtiledb_array_put_metadata(XPtr array, std::string key, SEXP obj); +RcppExport SEXP _tiledb_libtiledb_array_put_metadata(SEXP arraySEXP, SEXP keySEXP, SEXP objSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< XPtr >::type array(arraySEXP); + Rcpp::traits::input_parameter< std::string >::type key(keySEXP); + Rcpp::traits::input_parameter< SEXP >::type obj(objSEXP); + rcpp_result_gen = Rcpp::wrap(libtiledb_array_put_metadata(array, key, obj)); + return rcpp_result_gen; +END_RCPP +} +// libtiledb_array_get_metadata_num +R_xlen_t libtiledb_array_get_metadata_num(XPtr array); +RcppExport SEXP _tiledb_libtiledb_array_get_metadata_num(SEXP arraySEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< XPtr >::type array(arraySEXP); + rcpp_result_gen = Rcpp::wrap(libtiledb_array_get_metadata_num(array)); + return rcpp_result_gen; +END_RCPP +} +// libtiledb_array_get_metadata_from_index +SEXP libtiledb_array_get_metadata_from_index(XPtr array, int idx); +RcppExport SEXP _tiledb_libtiledb_array_get_metadata_from_index(SEXP arraySEXP, SEXP idxSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< XPtr >::type array(arraySEXP); + Rcpp::traits::input_parameter< int >::type idx(idxSEXP); + rcpp_result_gen = Rcpp::wrap(libtiledb_array_get_metadata_from_index(array, idx)); + return rcpp_result_gen; +END_RCPP +} +// libtiledb_array_get_metadata_list +SEXP libtiledb_array_get_metadata_list(XPtr array); +RcppExport SEXP _tiledb_libtiledb_array_get_metadata_list(SEXP arraySEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< XPtr >::type array(arraySEXP); + rcpp_result_gen = Rcpp::wrap(libtiledb_array_get_metadata_list(array)); return rcpp_result_gen; END_RCPP } +// libtiledb_array_delete_metadata +void libtiledb_array_delete_metadata(XPtr array, std::string key); +RcppExport SEXP _tiledb_libtiledb_array_delete_metadata(SEXP arraySEXP, SEXP keySEXP) { +BEGIN_RCPP + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< XPtr >::type array(arraySEXP); + Rcpp::traits::input_parameter< std::string >::type key(keySEXP); + libtiledb_array_delete_metadata(array, key); + return R_NilValue; +END_RCPP +} // libtiledb_query XPtr libtiledb_query(XPtr ctx, XPtr array, std::string type); RcppExport SEXP _tiledb_libtiledb_query(SEXP ctxSEXP, SEXP arraySEXP, SEXP typeSEXP) { @@ -1771,20 +1663,6 @@ END_RCPP } static const R_CallMethodDef CallEntries[] = { - {"_tiledb_has_metadata_simple", (DL_FUNC) &_tiledb_has_metadata_simple, 2}, - {"_tiledb_has_metadata_ptr", (DL_FUNC) &_tiledb_has_metadata_ptr, 2}, - {"_tiledb_num_metadata_simple", (DL_FUNC) &_tiledb_num_metadata_simple, 1}, - {"_tiledb_num_metadata_ptr", (DL_FUNC) &_tiledb_num_metadata_ptr, 1}, - {"_tiledb_get_metadata_simple", (DL_FUNC) &_tiledb_get_metadata_simple, 2}, - {"_tiledb_get_metadata_ptr", (DL_FUNC) &_tiledb_get_metadata_ptr, 2}, - {"_tiledb_put_metadata_simple", (DL_FUNC) &_tiledb_put_metadata_simple, 3}, - {"_tiledb_put_metadata_ptr", (DL_FUNC) &_tiledb_put_metadata_ptr, 3}, - {"_tiledb_get_metadata_from_index_ptr", (DL_FUNC) &_tiledb_get_metadata_from_index_ptr, 2}, - {"_tiledb_get_metadata_from_index_simple", (DL_FUNC) &_tiledb_get_metadata_from_index_simple, 2}, - {"_tiledb_get_all_metadata_simple", (DL_FUNC) &_tiledb_get_all_metadata_simple, 1}, - {"_tiledb_get_all_metadata_ptr", (DL_FUNC) &_tiledb_get_all_metadata_ptr, 1}, - {"_tiledb_delete_metadata_simple", (DL_FUNC) &_tiledb_delete_metadata_simple, 2}, - {"_tiledb_delete_metadata_ptr", (DL_FUNC) &_tiledb_delete_metadata_ptr, 2}, {"_tiledb_tiledb_datatype_R_type", (DL_FUNC) &_tiledb_tiledb_datatype_R_type, 1}, {"_tiledb_libtiledb_version", (DL_FUNC) &_tiledb_libtiledb_version, 0}, {"_tiledb_libtiledb_ctx", (DL_FUNC) &_tiledb_libtiledb_ctx, 1}, @@ -1868,7 +1746,12 @@ static const R_CallMethodDef CallEntries[] = { {"_tiledb_libtiledb_array_close", (DL_FUNC) &_tiledb_libtiledb_array_close, 1}, {"_tiledb_libtiledb_array_query_type", (DL_FUNC) &_tiledb_libtiledb_array_query_type, 1}, {"_tiledb_libtiledb_array_nonempty_domain", (DL_FUNC) &_tiledb_libtiledb_array_nonempty_domain, 1}, - {"_tiledb_libtiledb_array_consolidate", (DL_FUNC) &_tiledb_libtiledb_array_consolidate, 2}, + {"_tiledb_libtiledb_array_consolidate", (DL_FUNC) &_tiledb_libtiledb_array_consolidate, 3}, + {"_tiledb_libtiledb_array_put_metadata", (DL_FUNC) &_tiledb_libtiledb_array_put_metadata, 3}, + {"_tiledb_libtiledb_array_get_metadata_num", (DL_FUNC) &_tiledb_libtiledb_array_get_metadata_num, 1}, + {"_tiledb_libtiledb_array_get_metadata_from_index", (DL_FUNC) &_tiledb_libtiledb_array_get_metadata_from_index, 2}, + {"_tiledb_libtiledb_array_get_metadata_list", (DL_FUNC) &_tiledb_libtiledb_array_get_metadata_list, 1}, + {"_tiledb_libtiledb_array_delete_metadata", (DL_FUNC) &_tiledb_libtiledb_array_delete_metadata, 2}, {"_tiledb_libtiledb_query", (DL_FUNC) &_tiledb_libtiledb_query, 3}, {"_tiledb_libtiledb_query_type", (DL_FUNC) &_tiledb_libtiledb_query_type, 1}, {"_tiledb_libtiledb_query_set_layout", (DL_FUNC) &_tiledb_libtiledb_query_set_layout, 2}, diff --git a/src/array_metadata.cpp b/src/array_metadata.cpp deleted file mode 100644 index 52ea5ab450..0000000000 --- a/src/array_metadata.cpp +++ /dev/null @@ -1,284 +0,0 @@ - -// questions: -// - simple accessor functions or s4 instances or XPtr? -// -> s4 instance could cache more easily -// -> XPtr easiest -// - base layer here and refined interface in R function? -// -> add s4 instance on R side -// -> XPtr easier -// - other functionality: -// consolidate_metadata ? -// [DONE] delete_metadata - -#include - -#define STRICT_R_HEADERS -#include - -using namespace tiledb; - -// forward declaration -const char* _tiledb_datatype_to_string(tiledb_datatype_t dtype); - -// ---- has_metadata -bool has_metadata_impl(tiledb::Array& array, const std::string key) { - tiledb_datatype_t v_type; - return array.has_metadata(key.c_str(), &v_type); -} - -// [[Rcpp::export]] -bool has_metadata_simple(const std::string array_name, const std::string key) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_READ); // Open array for reading - return has_metadata_impl(array, key); -} - -// [[Rcpp::export]] -bool has_metadata_ptr(Rcpp::XPtr array, const std::string key) { - return has_metadata_impl(*array, key); -} - - -// ---- metadata_num -int num_metadata_impl(tiledb::Array& array) { - uint64_t nm = array.metadata_num(); - return static_cast(nm); -} - -// [[Rcpp::export]] -int num_metadata_simple(const std::string array_name) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_READ); // Open array for reading - return num_metadata_impl(array); -} - -// [[Rcpp::export]] -int num_metadata_ptr(Rcpp::XPtr array) { - return num_metadata_impl(*array); -} - -template -Rcpp::IntegerVector copy_int_vector(const uint32_t v_num, const void* v) { - // Strictly speaking a check for under/overflow would be needed here yet this for - // metadata annotation (and not data payload) so extreme ranges are less likely - Rcpp::IntegerVector vec(v_num); - const T *ivec = static_cast(v); - size_t n = static_cast(v_num); - for (size_t i=0; i(ivec[i]); - return(vec); -} - -// ---- get_metadata -SEXP convert_vector_to_sexp(const tiledb_datatype_t v_type, const uint32_t v_num, const void* v) { - // This supports a limited set of basic types as the metadata - // annotation is not meant to support complete serialization - if (v_type == TILEDB_INT32) { - Rcpp::IntegerVector vec(v_num); - std::memcpy(vec.begin(), v, v_num*sizeof(int32_t)); - return(vec); - } else if (v_type == TILEDB_FLOAT64) { - Rcpp::NumericVector vec(v_num); - std::memcpy(vec.begin(), v, v_num*sizeof(double)); - return(vec); - } else if (v_type == TILEDB_FLOAT32) { - Rcpp::NumericVector vec(v_num); - const float *fvec = static_cast(v); - size_t n = static_cast(v_num); - for (size_t i=0; i(fvec[i]); - return(vec); - } else if (v_type == TILEDB_CHAR || v_type == TILEDB_STRING_ASCII) { - Rcpp::CharacterVector vec(1); - std::string s(static_cast(v)); - s.resize(v_num); // incoming char* not null terminated, ensures v_num bytes and terminate - return(Rcpp::wrap(s)); - } else if (v_type == TILEDB_INT8) { - Rcpp::LogicalVector vec(v_num); - const int8_t *ivec = static_cast(v); - size_t n = static_cast(v_num); - for (size_t i=0; i(ivec[i]); - return(vec); - } else if (v_type == TILEDB_UINT8) { - // Strictly speaking a check for under/overflow would be needed here (and below) yet this - // is for metadata annotation (and not data payload) so extreme ranges are less likely - return copy_int_vector(v_num, v); - } else if (v_type == TILEDB_INT16) { - return copy_int_vector(v_num, v); - } else if (v_type == TILEDB_UINT16) { - return copy_int_vector(v_num, v); - } else if (v_type == TILEDB_UINT32) { - return copy_int_vector(v_num, v); - } else if (v_type == TILEDB_INT64) { - return copy_int_vector(v_num, v); - } else if (v_type == TILEDB_UINT64) { - return copy_int_vector(v_num, v); - } else { - Rcpp::stop("No support yet for %s", _tiledb_datatype_to_string(v_type)); - } -} - -SEXP get_metadata_impl(tiledb::Array& array, const std::string key) { - // Read with key - tiledb_datatype_t v_type; - uint32_t v_num; - const void* v; - array.get_metadata(key.c_str(), &v_type, &v_num, &v); - if (v == NULL) { - return R_NilValue; - } - - return convert_vector_to_sexp(v_type, v_num, v); -} - -// [[Rcpp::export]] -SEXP get_metadata_simple(const std::string array_name, const std::string key) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_READ); // Open array for reading - return get_metadata_impl(array, key); -} - -// [[Rcpp::export]] -SEXP get_metadata_ptr(Rcpp::XPtr array, const std::string key) { - return get_metadata_impl(*array, key); -} - - -// ---- put_metadata -bool put_metadata_impl(tiledb::Array array, const std::string key, const SEXP obj) { - // May want to add a mapper from SEXP type to tiledb type in libtiledb.cpp - switch(TYPEOF(obj)) { - case VECSXP: { - Rcpp::stop("List objects are not supported."); - array.close(); - return false; - break;// not reached - } - case REALSXP: { - Rcpp::NumericVector v(obj); - array.put_metadata(key.c_str(), TILEDB_FLOAT64, v.size(), v.begin()); - break; - } - case INTSXP: { - Rcpp::IntegerVector v(obj); - array.put_metadata(key.c_str(), TILEDB_INT32, v.size(), v.begin()); - break; - } - case STRSXP: { - Rcpp::CharacterVector v(obj); - std::string s(v[0]); - // We use TILEDB_CHAR interchangeably with TILEDB_STRING_ASCII is this best string type? - array.put_metadata(key.c_str(), TILEDB_CHAR, s.length(), s.c_str()); - break; - } - case LGLSXP: { // experimental: map R logical (ie TRUE, FALSE, NA) to int8 - Rcpp::LogicalVector v(obj); - size_t n = static_cast(v.size()); - std::vector ints(n); - for (size_t i=0; i(v[i]); - array.put_metadata(key.c_str(), TILEDB_INT8, ints.size(), ints.data()); - break; - } - default: { - Rcpp::stop("No support (yet) for type '%d'.", TYPEOF(obj)); - array.close(); - return false; - break; // not reached - } - } - // Close array - Important so that the metadata get flushed - array.close(); - return true; -} - -// [[Rcpp::export]] -bool put_metadata_simple(const std::string array_name, const std::string key, const SEXP obj) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_WRITE); // Open array for writing - return put_metadata_impl(array, key, obj); -} - -// [[Rcpp::export]] -bool put_metadata_ptr(Rcpp::XPtr array, const std::string key, const SEXP obj) { - return put_metadata_impl(*array, key, obj); -} - - -// ---- get by index -SEXP get_metadata_from_index_impl(tiledb::Array& array, const int idx) { - std::string key; - tiledb_datatype_t v_type; - uint32_t v_num; - const void* v; - array.get_metadata_from_index(static_cast(idx), &key, &v_type, &v_num, &v); - if (v == NULL) { - return R_NilValue; - } - - RObject vec = convert_vector_to_sexp(v_type, v_num, v); - vec.attr("names") = Rcpp::CharacterVector::create(key); - return vec; -} - -// [[Rcpp::export]] -SEXP get_metadata_from_index_ptr(Rcpp::XPtr array, const int idx) { - return get_metadata_from_index_impl(*array, idx); -} - -// [[Rcpp::export]] -SEXP get_metadata_from_index_simple(const std::string array_name, const int idx) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_READ); // Open array for reading - return get_metadata_from_index_impl(array, idx); -} - -// ---- get all metadata -SEXP get_all_metadata_impl(tiledb::Array& array) { - uint64_t nm = array.metadata_num(); - int n = static_cast(nm); - Rcpp::List lst(n); - Rcpp::CharacterVector names(n); - for (auto i=0; i array) { - return get_all_metadata_impl(*array); -} - - -// ---- delete metadata -void delete_metadata_impl(tiledb::Array& array, const std::string key) { - array.delete_metadata(key); -} - -// [[Rcpp::export]] -bool delete_metadata_simple(const std::string array_name, const std::string key) { - Context ctx; // Create TileDB context - Array array(ctx, array_name, TILEDB_WRITE); // Open array for reading - delete_metadata_impl(array, key); - return true; -} - -// [[Rcpp::export]] -bool delete_metadata_ptr(Rcpp::XPtr array, const std::string key) { - delete_metadata_impl(*array, key); - return true; -} diff --git a/src/libtiledb.cpp b/src/libtiledb.cpp index ebe49cf6fa..0b6348afd6 100644 --- a/src/libtiledb.cpp +++ b/src/libtiledb.cpp @@ -921,15 +921,15 @@ void libtiledb_attribute_dump(XPtr attr) { * TileDB Array Schema */ //[[Rcpp::export]] -XPtr libtiledb_array_schema( - XPtr ctx, - XPtr domain, - List attributes, - std::string cell_order, - std::string tile_order, - Nullable> coords_filter_list = R_NilValue, - Nullable> offsets_filter_list = R_NilValue, - bool sparse = false) { +XPtr +libtiledb_array_schema(XPtr ctx, + XPtr domain, + List attributes, + std::string cell_order, + std::string tile_order, + Nullable> coords_filter_list = R_NilValue, + Nullable> offsets_filter_list = R_NilValue, + bool sparse = false) { // check that external pointers are supported R_xlen_t nattr = attributes.length(); if (nattr == 0) { @@ -1195,12 +1195,12 @@ bool libtiledb_array_is_open(XPtr array) { // [[Rcpp::export]] bool libtiledb_array_is_open_for_reading(XPtr array) { - return array->is_open() && array->query_type() != TILEDB_READ; + return array->is_open() && array->query_type() == TILEDB_READ; } // [[Rcpp::export]] bool libtiledb_array_is_open_for_writing(XPtr array) { - return array->is_open() && array->query_type() != TILEDB_WRITE; + return array->is_open() && array->query_type() == TILEDB_WRITE; } // [[Rcpp::export]] @@ -1260,10 +1260,169 @@ List libtiledb_array_nonempty_domain(XPtr array) { } // [[Rcpp::export]] -std::string libtiledb_array_consolidate(XPtr ctx, - std::string uri) { - tiledb::Array::consolidate(*ctx.get(), uri); - return uri; +void libtiledb_array_consolidate(XPtr ctx, + std::string uri, + Nullable> cfgptr = R_NilValue) { + + if (cfgptr.isNotNull()) { + XPtr cfg(cfgptr); + tiledb::Array::consolidate(*ctx.get(), uri, cfg); + } else { + tiledb::Array::consolidate(*ctx.get(), uri); + } +} + +// [[Rcpp::export]] +bool libtiledb_array_put_metadata(XPtr array, + std::string key, SEXP obj) { + + // we implement a simpler interface here as the 'type' is given from + // the supplied SEXP, as is the extend + switch(TYPEOF(obj)) { + case VECSXP: { + Rcpp::stop("List objects are not supported."); + break;// not reached + } + case REALSXP: { + Rcpp::NumericVector v(obj); + array->put_metadata(key.c_str(), TILEDB_FLOAT64, v.size(), v.begin()); + break; + } + case INTSXP: { + Rcpp::IntegerVector v(obj); + array->put_metadata(key.c_str(), TILEDB_INT32, v.size(), v.begin()); + break; + } + case STRSXP: { + Rcpp::CharacterVector v(obj); + std::string s(v[0]); + // We use TILEDB_CHAR interchangeably with TILEDB_STRING_ASCII is this best string type? + array->put_metadata(key.c_str(), TILEDB_CHAR, s.length(), s.c_str()); + break; + } + case LGLSXP: { // experimental: map R logical (ie TRUE, FALSE, NA) to int8 + Rcpp::LogicalVector v(obj); + size_t n = static_cast(v.size()); + std::vector ints(n); + for (size_t i=0; i(v[i]); + array->put_metadata(key.c_str(), TILEDB_INT8, ints.size(), ints.data()); + break; + } + default: { + Rcpp::stop("No support (yet) for type '%d'.", TYPEOF(obj)); + break; // not reached + } + } + // Close array - Important so that the metadata get flushed + // not here, array opening and closing responsibility of caller: array.close(); + return true; +} + +// [[Rcpp::export]] +R_xlen_t libtiledb_array_get_metadata_num(XPtr array) { + uint64_t num = array->metadata_num(); + return static_cast(num); +} + +// helper function to copy int vector +template +Rcpp::IntegerVector copy_int_vector(const uint32_t v_num, const void* v) { + // Strictly speaking a check for under/overflow would be needed here yet this for + // metadata annotation (and not data payload) so extreme ranges are less likely + Rcpp::IntegerVector vec(v_num); + const T *ivec = static_cast(v); + size_t n = static_cast(v_num); + for (size_t i=0; i(ivec[i]); + return(vec); +} + +// helper function to convert_metadata +SEXP _metadata_to_sexp(const tiledb_datatype_t v_type, const uint32_t v_num, const void* v) { + // This supports a limited set of basic types as the metadata + // annotation is not meant to support complete serialization + if (v_type == TILEDB_INT32) { + Rcpp::IntegerVector vec(v_num); + std::memcpy(vec.begin(), v, v_num*sizeof(int32_t)); + return(vec); + } else if (v_type == TILEDB_FLOAT64) { + Rcpp::NumericVector vec(v_num); + std::memcpy(vec.begin(), v, v_num*sizeof(double)); + return(vec); + } else if (v_type == TILEDB_FLOAT32) { + Rcpp::NumericVector vec(v_num); + const float *fvec = static_cast(v); + size_t n = static_cast(v_num); + for (size_t i=0; i(fvec[i]); + return(vec); + } else if (v_type == TILEDB_CHAR || v_type == TILEDB_STRING_ASCII) { + Rcpp::CharacterVector vec(1); + std::string s(static_cast(v)); + s.resize(v_num); // incoming char* not null terminated, ensures v_num bytes and terminate + return(Rcpp::wrap(s)); + } else if (v_type == TILEDB_INT8) { + Rcpp::LogicalVector vec(v_num); + const int8_t *ivec = static_cast(v); + size_t n = static_cast(v_num); + for (size_t i=0; i(ivec[i]); + return(vec); + } else if (v_type == TILEDB_UINT8) { + // Strictly speaking a check for under/overflow would be needed here (and below) yet this + // is for metadata annotation (and not data payload) so extreme ranges are less likely + return copy_int_vector(v_num, v); + } else if (v_type == TILEDB_INT16) { + return copy_int_vector(v_num, v); + } else if (v_type == TILEDB_UINT16) { + return copy_int_vector(v_num, v); + } else if (v_type == TILEDB_UINT32) { + return copy_int_vector(v_num, v); + } else if (v_type == TILEDB_INT64) { + return copy_int_vector(v_num, v); + } else if (v_type == TILEDB_UINT64) { + return copy_int_vector(v_num, v); + } else { + Rcpp::stop("No support yet for %s", _tiledb_datatype_to_string(v_type)); + } +} + +// [[Rcpp::export]] +SEXP libtiledb_array_get_metadata_from_index(XPtr array, int idx) { + std::string key; + tiledb_datatype_t v_type; + uint32_t v_num; + const void* v; + array->get_metadata_from_index(static_cast(idx), &key, &v_type, &v_num, &v); + if (v == NULL) { + return R_NilValue; + } + + RObject vec = _metadata_to_sexp(v_type, v_num, v); + vec.attr("names") = Rcpp::CharacterVector::create(key); + return vec; +} + +// [[Rcpp::export]] +SEXP libtiledb_array_get_metadata_list(XPtr array) { + uint64_t num = array->metadata_num(); + int n = static_cast(num); + Rcpp::List lst(n); + Rcpp::CharacterVector names(n); + for (auto i=0; i array, std::string key) { + array->delete_metadata(key.c_str()); } /** diff --git a/src/tiledb_declarations.h b/src/tiledb_declarations.h index f290863ef9..033f5fe4b4 100644 --- a/src/tiledb_declarations.h +++ b/src/tiledb_declarations.h @@ -278,7 +278,7 @@ void libtiledb_array_schema_check(XPtr ## static void consolidate_metadata(const Context& ctx, const std::string& uri, Config* const config = nullptr) ## static void consolidate_metadata(const Context& ctx, const std::string& uri, tiledb_encryption_type_t encryption_type, const void* encryption_key, uint32_t key_length, Config* const config = nullptr) ## static void consolidate_metadata(const Context& ctx, const std::string& uri, tiledb_encryption_type_t encryption_type, const std::string& encryption_key, Config* const config = nullptr) -## void put_metadata(const std::string& key, tiledb_datatype_t value_type, uint32_t value_num, const void* value) +## y void put_metadata(const std::string& key, tiledb_datatype_t value_type, uint32_t value_num, const void* value) ## void delete_metadata(const std::string& key) ## void get_metadata(const std::string& key, tiledb_datatype_t* value_type, uint32_t* value_num, const void** value) ## bool has_metadata(const std::string& key, tiledb_datatype_t* value_type) @@ -301,6 +301,10 @@ XPtr libtiledb_array_close(XPtr array); std::string libtiledb_array_query_type(XPtr array); List libtiledb_array_nonempty_domain(XPtr array); std::string libtiledb_array_consolidate(XPtr ctx, std::string uri); +bool libtiledb_array_put_metadata(XPtr array, std::string key, SEXP obj); +R_xlen_t libtiledb_array_get_metadata_num(XPtr array); +SEXP libtiledb_array_get_metadata_from_index(XPtr array, int idx); +void libtiledb_array_delete_metadata(XPtr array, std::string key); ## Query @@ -377,6 +381,29 @@ DataFrame libtiledb_object_walk(XPtr ctx, std:: ## VFS +## +## C++ API +## +## VFS(const Context& ctx, const Config& config) +## void create_bucket(const std::string& uri) +## void remove_bucket(const std::string& uri) +## bool is_bucket(const std::string& uri) +## void empty_bucket(const std::string& bucket) +## bool is_empty_bucket(const std::string& bucket) +## void create_dir(const std::string& uri) +## bool is_dir(const std::string& uri) +## bool is_file(const std::string& uri) +## void remove_file(const std::string& uri) +## uint64_t dir_size(const std::string& uri) +## std::vector ls(const std::string& uri) +## uint64_t file_size(const std::string& uri) +## void move_file(const std::string& old_uri, const std::string& new_uri) +## void move_dir(const std::string& old_uri, const std::string& new_uri) +## void touch(const std::string& uri) +## const Context& context() +## std::shared_ptr ptr() +## Config config() +## static int ls_getter(const char* path, void* data) XPtr tiledb_vfs(XPtr ctx, Nullable> config=R_NilValue); std::string tiledb_vfs_create_bucket(XPtr vfs, std::string uri); std::string tiledb_vfs_remove_bucket(XPtr vfs, std::string uri); @@ -393,6 +420,23 @@ std::string tiledb_vfs_move_file(XPtr vfs, std::strin std::string tiledb_vfs_move_dir(XPtr vfs, std::string old_uri, std::string new_uri); std::string tiledb_vfs_touch(XPtr vfs, std::string uri); +## VFSFilebuf +## +## C++ API +## +## VFSFilebuf(const VFS& vfs) +## VFSFilebuf* open(const std::string& uri, std::ios::openmode openmode = std::ios::in) +## bool is_open() +## VFSFilebuf* close() +## const std::string& get_uri() +## std::streambuf::pos_type seekoff( off_type offset, std::ios::seekdir seekdir, std::ios::openmode openmode) +## pos_type seekpos(pos_type pos, std::ios::openmode openmode) +## std::streamsize showmanyc() +## std::streamsize xsgetn(char_type* s, std::streamsize n) +## int_type uflow() +## std::streamsize xsputn(const char_type* s, std::streamsize n) +## int_type overflow(int_type c) + ## Stats void libtiledb_stats_enable(); diff --git a/tests/testthat/test_Metadata.R b/tests/testthat/test_Metadata.R index 3a26ae992e..95b26336bd 100644 --- a/tests/testthat/test_Metadata.R +++ b/tests/testthat/test_Metadata.R @@ -14,23 +14,34 @@ unlink_and_create_simple <- function(tmp) { sch <- tiledb_array_schema(dom, c(a1, a2), sparse=TRUE) tiledb_array_create(tmp, sch) + arr <- tiledb_sparse(tmp, as.data.frame=FALSE) + + tiledb:::libtiledb_array_close(arr@ptr) + tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "WRITE") + ## write one record directly to (text) URI - tiledb_put_metadata(tmp, "vec", c(1.1, 2.2, 3.3)) + tiledb_put_metadata(arr, "vec", c(1.1, 2.2, 3.3)) - arr <- tiledb_sparse(tmp, as.data.frame=FALSE) arr } unlink_and_create_ptr <- function(tmp) { arr <- unlink_and_create_simple(tmp) + tiledb:::libtiledb_array_close(arr@ptr) ## write one record via ptr arrW <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "WRITE") - tiledb:::put_metadata_ptr(arrW, "txt", "the quick brown fox") + tiledb:::libtiledb_array_put_metadata(arrW, "txt", "the quick brown fox") tiledb:::libtiledb_array_close(arrW) arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") - return(arrR) + ##return(arrR) + arr <- tiledb_sparse(tmp, as.data.frame=FALSE) +} + +close_and_reopen <- function(arr, txt) { + res <- tiledb:::libtiledb_array_close(arr@ptr) + res <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, txt) } ## infrastructure @@ -47,10 +58,12 @@ teardown({ test_that("Can check presence of metadata", { arr <- unlink_and_create_ptr(tmp) - expect_error(tiledb:::has_metadata_ptr(NULL, "")) - expect_false(tiledb:::has_metadata_ptr(arr, "")) - expect_true(tiledb:::has_metadata_ptr(arr, "vec")) - expect_true(tiledb:::has_metadata_ptr(arr, "txt")) + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") + + expect_error(tiledb_has_metadata(NULL, "")) + expect_false(tiledb_has_metadata(arr, "")) + expect_true(tiledb_has_metadata(arr, "vec")) + expect_true(tiledb_has_metadata(arr, "txt")) unlink(tmp, recursive = TRUE, force = TRUE) }) @@ -58,8 +71,10 @@ test_that("Can check presence of metadata", { test_that("Can retrieve count of metadata", { arr <- unlink_and_create_ptr(tmp) - expect_error(tiledb:::num_metadata_ptr(NULL)) - expect_equal(tiledb:::num_metadata_ptr(arr), 2L) + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") + + expect_error(tiledb_num_metadata(NULL)) + expect_equal(tiledb_num_metadata(arr), 2L) unlink(tmp, recursive = TRUE, force = TRUE) }) @@ -67,9 +82,11 @@ test_that("Can retrieve count of metadata", { test_that("Can get metadata", { arr <- unlink_and_create_ptr(tmp) - expect_error(tiledb:::get_metadata_ptr(NULL, "")) - expect_equal(tiledb:::get_metadata_ptr(arr, ""), NULL) - expect_equal(tiledb:::get_metadata_ptr(arr, "vec"), c(1.1, 2.2, 3.3)) + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") + + expect_error(tiledb_get_metadata(NULL, "")) + expect_equal(tiledb_get_metadata(arr, ""), NULL) + expect_equal(tiledb_get_metadata(arr, "vec"), c(1.1, 2.2, 3.3)) unlink(tmp, recursive = TRUE, force = TRUE) }) @@ -77,36 +94,42 @@ test_that("Can get metadata", { test_that("Can put metadata", { arr <- unlink_and_create_ptr(tmp) - tiledb:::libtiledb_array_close(arr) - arrW <- tiledb:::libtiledb_array_open_with_ptr(arr, "WRITE") + tiledb:::libtiledb_array_close(arr@ptr) + arrW <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "WRITE") - expect_true(tiledb:::put_metadata_ptr(arrW, "foo", "the quick brown fox")) - expect_error(tiledb:::put_metadata_ptr(arrW, "foo", list(a=c(1,2,3), b=c("a", "b")))) + expect_true(tiledb_put_metadata(arr, "foo", "the quick brown fox")) + expect_error(tiledb_put_metadata(arr, "foo", list(a=c(1,2,3), b=c("a", "b")))) - tiledb:::libtiledb_array_close(arrW) + tiledb:::libtiledb_array_close(arr@ptr) unlink(tmp, recursive = TRUE, force = TRUE) }) test_that("Can do round trip", { - ## will use 'simpler' accessors to not have to flip between read and write arr <- unlink_and_create_simple(tmp) vec <- c(1.1, 2.2, 3.3) - expect_true(tiledb:::put_metadata_simple(tmp, "dvec", vec)) - expect_equal(tiledb:::get_metadata_simple(tmp, "dvec"), vec) + expect_true(tiledb_put_metadata(arr, "dvec", vec)) + close_and_reopen(arr, "READ") + expect_equal(tiledb_get_metadata(arr, "dvec"), vec) vec <- c(1L, 2L, 3L) - expect_true(tiledb:::put_metadata_simple(tmp, "ivec", vec)) - expect_equal(tiledb:::get_metadata_simple(tmp, "ivec"), vec) + close_and_reopen(arr, "WRITE") + expect_true(tiledb_put_metadata(arr, "ivec", vec)) + close_and_reopen(arr, "READ") + expect_equal(tiledb_get_metadata(arr, "ivec"), vec) vec <- "the quick brown fox" - expect_true(tiledb:::put_metadata_simple(tmp, "char", vec)) - expect_equal(tiledb:::get_metadata_simple(tmp, "char"), vec) + close_and_reopen(arr, "WRITE") + expect_true(tiledb_put_metadata(arr, "char", vec)) + close_and_reopen(arr, "READ") + expect_equal(tiledb_get_metadata(arr, "char"), vec) vec <- c(TRUE, FALSE, TRUE) - expect_true(tiledb:::put_metadata_simple(tmp, "lvec", vec)) - expect_equal(tiledb:::get_metadata_simple(tmp, "lvec"), vec) + close_and_reopen(arr, "WRITE") + expect_true(tiledb_put_metadata(arr, "lvec", vec)) + close_and_reopen(arr, "READ") + expect_equal(tiledb_get_metadata(arr, "lvec"), vec) unlink(tmp, recursive = TRUE, force = TRUE) }) @@ -114,10 +137,13 @@ test_that("Can do round trip", { test_that("Can get by index", { arr <- unlink_and_create_ptr(tmp) - expect_error(tiledb:::get_metadata_from_index_ptr(NULL, "")) - expect_error(tiledb:::get_metadata_from_index_ptr(arr, -1)) - expect_equal(tiledb:::get_metadata_from_index_ptr(arr, 0), c(txt="the quick brown fox")) - expect_equal(unname(tiledb:::get_metadata_from_index_ptr(arr, 1)), c(1.1, 2.2, 3.3)) + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") + + expect_error(tiledb:::libtiledb_get_metadata_from_index(NULL, "")) + expect_error(tiledb:::libtiledb_get_metadata_from_index(arr@ptr, -1)) + expect_equal(tiledb:::libtiledb_array_get_metadata_from_index(arr@ptr, 0), + c(txt="the quick brown fox")) + expect_equal(unname(tiledb:::libtiledb_array_get_metadata_from_index(arr@ptr, 1)), c(1.1, 2.2, 3.3)) unlink(tmp, recursive = TRUE, force = TRUE) }) @@ -125,7 +151,9 @@ test_that("Can get by index", { test_that("Can get all", { arr <- unlink_and_create_ptr(tmp) - res <- tiledb:::get_all_metadata_ptr(arr) + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") + + res <- tiledb_get_all_metadata(arr) expect_equal(length(res), 2L) expect_true("vec" %in% names(res)) expect_true("txt" %in% names(res)) @@ -134,28 +162,23 @@ test_that("Can get all", { test_that("Can deleye by key", { arr <- unlink_and_create_ptr(tmp) - ## should be two before we add - expect_equal(tiledb:::num_metadata_ptr(arr), 2L) - - tiledb:::libtiledb_array_close(arr) - arrW <- tiledb:::libtiledb_array_open_with_ptr(arr, "WRITE") + arrR <- tiledb:::libtiledb_array_open_with_ptr(arr@ptr, "READ") - expect_true(tiledb:::put_metadata_ptr(arrW, "foo", "the quick brown fox")) + ## should be two before we add + expect_equal(tiledb_num_metadata(arr), 2L) - tiledb:::libtiledb_array_close(arrW) - arr <- tiledb:::libtiledb_array_open_with_ptr(arrW, "READ") + close_and_reopen(arr, "WRITE") + expect_true(tiledb_put_metadata(arr, "foo", "the quick brown fox")) + close_and_reopen(arr, "READ") ## should be three after we add - expect_equal(tiledb:::num_metadata_ptr(arr), 3L) - - tiledb:::libtiledb_array_close(arr) - arrW <- tiledb:::libtiledb_array_open_with_ptr(arr, "WRITE") + expect_equal(tiledb_num_metadata(arr), 3L) - expect_true(tiledb:::delete_metadata_ptr(arr, "foo")) + close_and_reopen(arr, "WRITE") + expect_true(tiledb_delete_metadata(arr, "foo")) - tiledb:::libtiledb_array_close(arrW) - arr <- tiledb:::libtiledb_array_open_with_ptr(arrW, "READ") + close_and_reopen(arr, "READ") ## should be two after we delete - expect_equal(tiledb:::num_metadata_ptr(arr), 2L) + expect_equal(tiledb_num_metadata(arr), 2L) })