bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, bool = false) const { if (v1.is_null() != v2.is_null()) return false; return v1.size() == v2.size() && equal_case_fold(v2, v1_upper, v1_lower); }
bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, bool = false) const { if (v2.is_null() && !v1.is_null()) return false; if (v1.size() == 0 && !v2.is_null()) return true; return search_case_fold(v2, v1_upper, v1_lower, v1.size()) != v2.size(); }
// Slow version, used if caller hasn't stored an upper and lower case version bool operator()(StringData v1, StringData v2, bool = false, bool = false) const { if (v2.is_null() && !v1.is_null()) return false; if (v1.size() > v2.size()) return false; std::string v1_upper = case_map(v1, true, IgnoreErrors); std::string v1_lower = case_map(v1, false, IgnoreErrors); return equal_case_fold(v2.suffix(v1.size()), v1_upper.c_str(), v1_lower.c_str()); }
// Slow version, used if caller hasn't stored an upper and lower case version bool operator()(StringData v1, StringData v2, bool = false, bool = false) const { if (v1.is_null() != v2.is_null()) return true; if (v1.size() != v2.size()) return true; std::string v1_upper = case_map(v1, true); std::string v1_lower = case_map(v1, false); return !equal_case_fold(v2, v1_upper.c_str(), v1_lower.c_str()); }
// Slow version, used if caller hasn't stored an upper and lower case version bool operator()(StringData v1, StringData v2, bool = false, bool = false) const { if (v2.is_null() && !v1.is_null()) return false; if (v1.size() == 0 && !v2.is_null()) return true; std::string v1_upper = case_map(v1, true, IgnoreErrors); std::string v1_lower = case_map(v1, false, IgnoreErrors); return search_case_fold(v2, v1_upper.c_str(), v1_lower.c_str(), v1.size()) != v2.size(); }
util::Optional<std::string> SyncFileActionMetadata::new_name() const { REALM_ASSERT(m_realm); m_realm->verify_thread(); StringData result = m_row.get_string(m_schema.idx_new_name); return result.is_null() ? util::none : util::make_optional(std::string(result)); }
inline void StringEnumColumn::add(StringData value) { REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); size_t row_ndx = realm::npos; size_t num_rows = 1; do_insert(row_ndx, value, num_rows); // Throws }
string concat_stringdata(const char* message, StringData strData) { if (strData.is_null()) { return std::string(message); } return std::string(message) + std::string(strData.data(), strData.size()); }
util::Optional<std::string> SyncUserMetadata::get_optional_string_field(size_t col_idx) const { REALM_ASSERT(m_realm); m_realm->verify_thread(); StringData result = m_row.get_string(col_idx); return result.is_null() ? util::none : util::make_optional(std::string(result)); }
inline void StringColumn::insert(std::size_t row_ndx, StringData value) { REALM_ASSERT(!(value.is_null() && !m_nullable)); std::size_t size = this->size(); REALM_ASSERT_3(row_ndx, <=, size); std::size_t num_rows = 1; bool is_append = row_ndx == size; do_insert(row_ndx, value, num_rows, is_append); // Throws }
inline void StringEnumColumn::insert(size_t row_ndx, StringData value) { REALM_ASSERT_DEBUG(!(!m_nullable && value.is_null())); size_t column_size = this->size(); REALM_ASSERT_3(row_ndx, <=, column_size); size_t num_rows = 1; bool is_append = row_ndx == column_size; do_insert(row_ndx, value, num_rows, is_append); // Throws }
inline void BinaryColumn::set_string(size_t ndx, StringData value) { if (value.is_null() && !m_nullable) throw LogicError(LogicError::column_not_nullable); BinaryData bin(value.data(), value.size()); bool add_zero_term = true; set(ndx, bin, add_zero_term); }
REALM_EXPORT size_t table_get_string(const Table* table_ptr, size_t column_ndx, size_t row_ndx, uint16_t * datatochsarp, size_t bufsize, bool* is_null) { return handle_errors([&]() -> size_t { StringData fielddata = table_ptr->get_string(column_ndx, row_ndx); if ((*is_null = fielddata.is_null())) return 0; return stringdata_to_csharpstringbuffer(fielddata, datatochsarp, bufsize); }); }
REALM_EXPORT size_t object_get_string(const Object& object, size_t property_ndx, uint16_t * datatochsarp, size_t bufsize, bool* is_null, NativeException::Marshallable& ex) { return handle_errors(ex, [&]() -> size_t { verify_can_get(object); const size_t column_ndx = get_column_index(object, property_ndx); const StringData fielddata(object.row().get_string(column_ndx)); if ((*is_null = fielddata.is_null())) return 0; return stringdata_to_csharpstringbuffer(fielddata, datatochsarp, bufsize); }); }
// Index works as follows: All non-NULL values are stored as if they had appended an 'X' character at the end. So // "foo" is stored as if it was "fooX", and "" (empty string) is stored as "X". And NULLs are stored as empty strings. inline StringIndex::key_type StringIndex::create_key(StringData str, size_t offset) noexcept { if (str.is_null()) return 0; if (offset > str.size()) return 0; // for very short strings size_t tail = str.size() - offset; if (tail <= sizeof(key_type)-1) { char buf[sizeof(key_type)]; memset(buf, 0, sizeof(key_type)); buf[tail] = 'X'; memcpy(buf, str.data() + offset, tail); return create_key(StringData(buf, tail + 1)); } // else fallback return create_key(str.substr(offset)); }
inline int StringColumn::compare_values(std::size_t row1, std::size_t row2) const { StringData a = get(row1); StringData b = get(row2); if (a.is_null() && !b.is_null()) return 1; else if (b.is_null() && !a.is_null()) return -1; else if (a.is_null() && b.is_null()) return 0; if (a == b) return 0; return utf8_compare(a, b) ? 1 : -1; }
jstring to_jstring(JNIEnv* env, StringData str) { if (str.is_null()) { return NULL; } // For efficiency, if the incoming UTF-8 string is sufficiently // small, we will attempt to store the UTF-16 output into a stack // allocated buffer of static size. Otherwise we will have to // dynamically allocate the output buffer after calculating its // size. const size_t stack_buf_size = 48; jchar stack_buf[stack_buf_size]; std::unique_ptr<jchar[]> dyn_buf; const char* in_begin = str.data(); const char* in_end = str.data() + str.size(); jchar* out_begin = stack_buf; jchar* out_curr = stack_buf; jchar* out_end = stack_buf + stack_buf_size; typedef Utf8x16<jchar, JcharTraits> Xcode; if (str.size() <= stack_buf_size) { size_t retcode = Xcode::to_utf16(in_begin, in_end, out_curr, out_end); if (retcode != 0) { throw std::runtime_error(string_to_hex("Failure when converting short string to UTF-16", str, in_begin, in_end, out_curr, out_end, size_t(0), retcode)); } if (in_begin == in_end) { goto transcode_complete; } } { const char* in_begin2 = in_begin; size_t error_code; size_t size = Xcode::find_utf16_buf_size(in_begin2, in_end, error_code); if (in_begin2 != in_end) { throw std::runtime_error(string_to_hex("Failure when computing UTF-16 size", str, in_begin, in_end, out_curr, out_end, size, error_code)); } if (int_add_with_overflow_detect(size, stack_buf_size)) { throw std::runtime_error("String size overflow"); } dyn_buf.reset(new jchar[size]); out_curr = copy(out_begin, out_curr, dyn_buf.get()); out_begin = dyn_buf.get(); out_end = dyn_buf.get() + size; size_t retcode = Xcode::to_utf16(in_begin, in_end, out_curr, out_end); if (retcode != 0) { throw std::runtime_error(string_to_hex("Failure when converting long string to UTF-16", str, in_begin, in_end, out_curr, out_end, size_t(0), retcode)); } REALM_ASSERT(in_begin == in_end); } transcode_complete : { jsize out_size; if (int_cast_with_overflow_detect(out_curr - out_begin, out_size)) { throw std::runtime_error("String size overflow"); } return env->NewString(out_begin, out_size); } }
inline void StringColumn::set_string(std::size_t row_ndx, StringData value) { REALM_ASSERT(!(value.is_null() && !m_nullable)); set(row_ndx, value); // Throws }