#pragma once
#include <cstring>
#include "common/types/string_t.h"
#include "function/list/functions/list_len_function.h"
namespace lbug {
namespace function {
struct ArrayExtract {
static inline void operation(common::string_t& str, int64_t& idx, common::string_t& result) {
if (idx == 0) {
result.len = 0;
return;
}
auto stringVal = str.getAsString();
int64_t strLen = 0;
ListLen::operation(str, strLen);
auto idxPos = idx > 0 ? std::min(idx, strLen) : std::max(strLen + idx, (int64_t)0) + 1;
auto startPos = idxPos - 1;
auto endPos = startPos + 1;
bool isAscii = true;
for (auto i = 0u; i < std::min((size_t)idxPos + 1, stringVal.size()); i++) {
if (stringVal[i] & 0x80) {
isAscii = false;
break;
}
}
if (isAscii) {
copySubstr(str, idxPos, 1 , result, isAscii);
} else {
int64_t characterCount = 0, startBytePos = 0, endBytePos = 0;
lbug::utf8proc::utf8proc_grapheme_callback(stringVal.c_str(), stringVal.size(),
[&](int64_t gstart, int64_t ) {
if (characterCount == startPos) {
startBytePos = gstart;
} else if (characterCount == endPos) {
endBytePos = gstart;
return false;
}
characterCount++;
return true;
});
if (endBytePos == 0) {
endBytePos = str.len;
}
copySubstr(str, startBytePos, endBytePos - startBytePos, result, isAscii);
}
}
static inline void copySubstr(common::string_t& src, int64_t start, int64_t len,
common::string_t& result, bool isAscii) {
result.len = std::min(len, src.len - start + 1);
if (isAscii) {
memcpy((uint8_t*)result.getData(), src.getData() + start - 1, result.len);
} else {
memcpy((uint8_t*)result.getData(), src.getData() + start, result.len);
}
}
};
} }