-
Notifications
You must be signed in to change notification settings - Fork 25
/
metadata.cpp
193 lines (174 loc) · 7.83 KB
/
metadata.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <Rcpp/Lighter> // for R interface to C++
#include <nanoarrow/r.h> // for C/C++ interface to Arrow (via header exported from the R package)
#include <nanoarrow/nanoarrow.hpp> // for C/C++ interface to Arrow (vendored)
#include <RcppInt64> // for fromInteger64
#include <tiledbsoma/tiledbsoma>
#include <tiledbsoma/reindexer/reindexer.h>
#include "rutilities.h" // local declarations
#include "xptr-utils.h" // xptr taggging utilities
namespace tdbs = tiledbsoma;
std::unique_ptr<tdbs::SOMAObject> getObjectUniquePointer(bool is_array, OpenMode mode,
std::string& uri,
std::shared_ptr<tdbs::SOMAContext> ctx,
Rcpp::Nullable<Rcpp::DatetimeVector> tsvec = R_NilValue) {
// optional timestamp range
std::optional<tdbs::TimestampRange> tsrng = makeTimestampRange(tsvec);
if (is_array) {
return tdbs::SOMAArray::open(mode, uri, ctx, "unnamed", {}, "auto",
ResultOrder::automatic, tsrng);
} else {
return tdbs::SOMAGroup::open(mode, uri, ctx, "unnamed", tsrng);
}
}
//' Get nnumber of metadata items
//' @param uri The array URI
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @export
// [[Rcpp::export]]
int32_t get_metadata_num(std::string& uri, bool is_array, Rcpp::XPtr<somactx_wrap_t> ctxxp) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::read, uri, sctx);
int32_t nb = soup->metadata_num();
return nb;
}
//' Read all metadata (as named list)
//'
//' This function currently supports metadata as either a string or an 'int64' (or 'int32').
//' It will error if a different datatype is encountered.
//' @param uri The array URI
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @export
// [[Rcpp::export]]
Rcpp::List get_all_metadata(std::string& uri, bool is_array, Rcpp::XPtr<somactx_wrap_t> ctxxp) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::read, uri, sctx);
auto mvmap = soup->get_metadata();
std::vector<std::string> namvec;
Rcpp::List lst;
for (auto it = mvmap.begin(); it != mvmap.end(); it++) {
std::string key = it->first;
namvec.push_back(key);
tdbs::MetadataValue val = it->second;
auto dtype = std::get<0>(val);
auto len = std::get<1>(val);
const void* ptr = std::get<2>(val);
if (dtype == TILEDB_STRING_UTF8 || dtype == TILEDB_STRING_ASCII) {
auto str = std::string((char*) ptr, len);
lst.push_back(str);
} else if (dtype == TILEDB_INT64) {
std::vector<int64_t> v(len);
std::memcpy(&(v[0]), ptr, len*sizeof(int64_t));
lst.push_back(Rcpp::toInteger64(v));
} else if (dtype == TILEDB_INT32) {
Rcpp::IntegerVector v(len);
std::memcpy(v.begin(), ptr, len*sizeof(int32_t));
} else {
auto txt = tiledb::impl::type_to_str(dtype);
Rcpp::stop("Currently unsupported type '%s'", txt.c_str());
}
}
lst.attr("names") = Rcpp::CharacterVector(namvec.begin(), namvec.end());
return lst;
}
//' Read metadata (as a string)
//'
//' @param uri The array URI
//' @param key The array metadata key
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @export
// [[Rcpp::export]]
std::string get_metadata(std::string& uri, std::string& key, bool is_array,
Rcpp::XPtr<somactx_wrap_t> ctxxp) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::read, uri, sctx);
auto mv = soup->get_metadata(key);
if (!mv.has_value()) {
Rcpp::stop("No value for '%s'", key.c_str());
}
tdbs::MetadataValue val = *mv;
auto dtype = std::get<0>(val);
auto txt = tiledb::impl::type_to_str(dtype);
if (txt != "STRING_UTF8" && txt != "STRING_ASCII") {
Rcpp::stop("Currently unsupported type '%s'", txt.c_str());
}
auto len = std::get<1>(val);
const void* ptr = std::get<2>(val);
auto str = std::string((char*) ptr, len);
return str;
}
//' Check for metadata given key
//'
//' @param uri The array URI
//' @param key The array metadata key
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @export
// [[Rcpp::export]]
bool has_metadata(std::string& uri, std::string& key, bool is_array,
Rcpp::XPtr<somactx_wrap_t> ctxxp) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::read, uri, sctx);
return soup->has_metadata(key);
}
//' Delete metadata for given key
//'
//' @param uri The array URI
//' @param key The array metadata key
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @export
// [[Rcpp::export]]
void delete_metadata(std::string& uri, std::string& key, bool is_array,
Rcpp::XPtr<somactx_wrap_t> ctxxp) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::write, uri, sctx);
soup->delete_metadata(key);
soup->close();
}
//' Set metadata (as a string)
//'
//' @param uri The array URI
//' @param key The array metadata key
//' @param valuesxp The metadata value
//' @param type The datatype
//' @param is_array A boolean to indicate array or group
//' @param ctxxp An external pointer to the SOMAContext wrapper
//' @param tsvec An optional two-element datetime vector
//' @export
// [[Rcpp::export]]
void set_metadata(std::string& uri, std::string& key, SEXP valuesxp, std::string& type,
bool is_array, Rcpp::XPtr<somactx_wrap_t> ctxxp,
Rcpp::Nullable<Rcpp::DatetimeVector> tsvec = R_NilValue) {
// shared pointer to SOMAContext from external pointer wrapper
std::shared_ptr<tdbs::SOMAContext> sctx = ctxxp->ctxptr;
// SOMA Object unique pointer (aka soup)
auto soup = getObjectUniquePointer(is_array, OpenMode::write, uri, sctx, tsvec);
if (type == "character") {
const tiledb_datatype_t value_type = TILEDB_STRING_UTF8;
std::string value = Rcpp::as<std::string>(valuesxp);
spdl::debug("[set_metadata] key {} value {} is_array {} type {}", key, value, is_array, type);
soup->set_metadata(key, value_type, value.length(), (void*) value.c_str(), true);
} else if (type == "integer64") {
const tiledb_datatype_t value_type = TILEDB_INT64;
double dv = Rcpp::as<double>(valuesxp);
int64_t value = Rcpp::fromInteger64(dv);
spdl::debug("[set_metadata] key {} value {} is_array {} type {}", key, value, is_array, type);
soup->set_metadata(key, value_type, 1, (void*) &value, true);
} else {
Rcpp::stop("Unsupported type '%s'", type);
}
soup->close();
}