[ox] Cleanup

This commit is contained in:
Gary Talent 2024-04-18 23:32:54 -05:00
parent 3b8d13dce3
commit 922323833c
15 changed files with 103 additions and 99 deletions

View File

@ -64,7 +64,7 @@ Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept {
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept { Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept {
oxRequire(header, readClawHeader(buff, buffLen)); oxRequire(header, readClawHeader(buff, buffLen));
Buffer out(header.dataSize); Buffer out(header.dataSize);
ox_memcpy(out.data(), header.data, out.size()); ox::listcpy(out.data(), header.data, out.size());
return out; return out;
} }

View File

@ -279,7 +279,7 @@ Error FileStoreTemplate<size_t>::write(uint64_t id64, const void *data, FsSize_t
oxAssert(destData.size() == dataSize, "Allocation size does not match data."); oxAssert(destData.size() == dataSize, "Allocation size does not match data.");
// write data if any was provided // write data if any was provided
if (data != nullptr) { if (data != nullptr) {
ox_memcpy(destData, data, dest->size()); ox::memcpy(destData, data, dest->size());
oxTrace("ox.fs.FileStoreTemplate.write", "Data written"); oxTrace("ox.fs.FileStoreTemplate.write", "Data written");
} }
auto fsData = fileStoreData(); auto fsData = fileStoreData();
@ -336,7 +336,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, void *out, FsSize_t outSize,
return OxError(1); return OxError(1);
} }
ox_memcpy(out, srcData, srcData.size()); ox::memcpy(out, srcData, srcData.size());
if (size) { if (size) {
*size = src.size(); *size = src.size();
} }
@ -367,7 +367,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart, FsSize_t
return OxError(1); return OxError(1);
} }
ox_memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
if (size) { if (size) {
*size = src.size(); *size = src.size();
} }
@ -400,7 +400,7 @@ Error FileStoreTemplate<size_t>::read(uint64_t id, FsSize_t readStart,
return OxError(1); return OxError(1);
} }
ox_memcpy(out, srcData.get() + readStart, readSize); ox::memcpy(out, srcData.get() + readStart, readSize);
if (size) { if (size) {
*size = src.size(); *size = src.size();
} }

View File

@ -48,7 +48,7 @@ FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
if (other.m_data.path) { if (other.m_data.path) {
auto strSize = ox::strlen(other.m_data.path) + 1; auto strSize = ox::strlen(other.m_data.path) + 1;
m_data.path = new char[strSize]; m_data.path = new char[strSize];
ox_memcpy(m_data.path, other.m_data.path, strSize); ox::memcpy(m_data.path, other.m_data.path, strSize);
} else { } else {
m_data.constPath = ""; m_data.constPath = "";
m_type = FileAddressType::ConstPath; m_type = FileAddressType::ConstPath;

View File

@ -44,13 +44,10 @@ class FileAddress {
protected: protected:
FileAddressType m_type = FileAddressType::None; FileAddressType m_type = FileAddressType::None;
Data m_data; Data m_data{};
public: public:
constexpr FileAddress() noexcept { constexpr FileAddress() noexcept = default;
m_data.inode = 0;
m_type = FileAddressType::None;
}
FileAddress(const FileAddress &other) noexcept; FileAddress(const FileAddress &other) noexcept;

View File

@ -173,15 +173,15 @@ class OX_PACKED NodeBuffer {
template<typename size_t, typename Item> template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept { NodeBuffer<size_t, Item>::NodeBuffer(std::size_t size) noexcept {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
ox_memset(this + 1, 0, size - sizeof(*this)); ox::memset(this + 1, 0, size - sizeof(*this));
oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get()); oxTracef("ox.NodeBuffer.constructor", "{}", m_header.firstItem.get());
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept { NodeBuffer<size_t, Item>::NodeBuffer(const NodeBuffer &other, std::size_t size) noexcept {
oxTracef("ox.ptrarith.NodeBuffer.copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get()); oxTracef("ox.ptrarith.NodeBuffer.copy", "other.m_header.firstItem: {}", other.m_header.firstItem.get());
ox_memset(this + 1, 0, size - sizeof(*this)); ox::memset(this + 1, 0, size - sizeof(*this));
ox_memcpy(this, &other, size); ox::memcpy(this, &other, size);
} }
template<typename size_t, typename Item> template<typename size_t, typename Item>
@ -291,7 +291,7 @@ Result<typename NodeBuffer<size_t, Item>::ItemPtr> NodeBuffer<size_t, Item>::mal
oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown"); oxTrace("ox.ptrarith.NodeBuffer.malloc.fail", "Unknown");
return OxError(1, "NodeBuffer::malloc: unknown failure"); return OxError(1, "NodeBuffer::malloc: unknown failure");
} }
ox_memset(out, 0, fullSize); ox::memset(out, 0, fullSize);
new (out) Item; new (out) Item;
out->setSize(sz); out->setSize(sz);
@ -367,7 +367,7 @@ Error NodeBuffer<size_t, Item>::setSize(std::size_t size) noexcept {
} else { } else {
m_header.size = static_cast<size_t>(size); m_header.size = static_cast<size_t>(size);
auto data = reinterpret_cast<uint8_t*>(this) + end; auto data = reinterpret_cast<uint8_t*>(this) + end;
ox_memset(data, 0, size - end); ox::memset(data, 0, size - end);
return OxError(0); return OxError(0);
} }
} }
@ -405,7 +405,7 @@ Error NodeBuffer<size_t, Item>::compact(F cb) noexcept {
return OxError(2); return OxError(2);
} }
// move node // move node
ox_memcpy(dest, src, src->fullSize()); ox::memcpy(dest, src, src->fullSize());
oxReturnError(cb(src, dest)); oxReturnError(cb(src, dest));
// update surrounding nodes // update surrounding nodes
auto prev = ptr(dest->prev); auto prev = ptr(dest->prev);

View File

@ -47,13 +47,13 @@ class CirculerBuffer {
} }
// write seg 1 // write seg 1
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt); const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
ox_memcpy(&m_buff[m_writePt], &buff[0], seg1Sz); ox::listcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
m_writePt += sz; m_writePt += sz;
if (seg1Sz != sz) { if (seg1Sz != sz) {
m_writePt -= m_buff.size(); m_writePt -= m_buff.size();
// write seg 2 // write seg 2
const auto seg2Sz = sz - seg1Sz; const auto seg2Sz = sz - seg1Sz;
ox_memcpy(&m_buff[0], &buff[seg1Sz], seg2Sz); ox::listcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
oxAssert(m_buff[0] == buff[seg1Sz], "break"); oxAssert(m_buff[0] == buff[seg1Sz], "break");
} }
return {}; return {};
@ -70,7 +70,7 @@ class CirculerBuffer {
return {}; return {};
} }
constexpr ox::Error seekp(int, ios_base::seekdir) { constexpr ox::Error seekp(int, ios_base::seekdir) noexcept {
return OxError(1, "Unimplemented"); return OxError(1, "Unimplemented");
} }
@ -84,13 +84,13 @@ class CirculerBuffer {
const auto bytesRead = ox::min(outSize, m_buff.size() - avail()); const auto bytesRead = ox::min(outSize, m_buff.size() - avail());
// read seg 1 // read seg 1
const auto seg1Sz = ox::min(bytesRead, m_buff.size() - m_readPt); const auto seg1Sz = ox::min(bytesRead, m_buff.size() - m_readPt);
ox_memcpy(&out[0], &m_buff[m_readPt], seg1Sz); ox::listcpy(&out[0], &m_buff[m_readPt], seg1Sz);
m_readPt += bytesRead; m_readPt += bytesRead;
if (seg1Sz != bytesRead) { if (seg1Sz != bytesRead) {
m_readPt -= m_buff.size(); m_readPt -= m_buff.size();
// read seg 2 // read seg 2
const auto seg2Sz = bytesRead - seg1Sz; const auto seg2Sz = bytesRead - seg1Sz;
ox_memcpy(&out[seg1Sz], &m_buff[0], seg2Sz); ox::listcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
} }
return bytesRead; return bytesRead;
} }

View File

@ -71,7 +71,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
// move input to uint64_t to allow consistent bit manipulation, and to avoid // move input to uint64_t to allow consistent bit manipulation, and to avoid
// overflow concerns // overflow concerns
uint64_t val = 0; uint64_t val = 0;
ox_memcpy(&val, &input, sizeof(input)); ox::memcpy(&val, &input, sizeof(input));
if (val) { if (val) {
// bits needed to represent number factoring in space possibly // bits needed to represent number factoring in space possibly
// needed for signed bit // needed for signed bit
@ -94,7 +94,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
} }
if (bytes == 9) { if (bytes == 9) {
out.data[0] = bytesIndicator; out.data[0] = bytesIndicator;
ox_memcpy(&out.data[1], &leVal, 8); ox::memcpy(&out.data[1], &leVal, 8);
if (inputNegative) { if (inputNegative) {
out.data[1] |= 0b1000'0000; out.data[1] |= 0b1000'0000;
} }
@ -104,7 +104,7 @@ constexpr McInt encodeInteger(I pInput) noexcept {
auto intermediate = auto intermediate =
static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes | static_cast<uint64_t>(leVal.raw() | (negBit << (valBits - 1))) << bytes |
static_cast<uint64_t>(bytesIndicator); static_cast<uint64_t>(bytesIndicator);
ox_memcpy(out.data, &intermediate, sizeof(intermediate)); ox::memcpy(out.data, &intermediate, sizeof(intermediate));
} }
out.length = bytes; out.length = bytes;
} }
@ -160,7 +160,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
ox::Array<uint32_t, 2> d = {}; ox::Array<uint32_t, 2> d = {};
//d[0] = decoded & 0xffff'ffff; //d[0] = decoded & 0xffff'ffff;
//d[1] = decoded >> 32; //d[1] = decoded >> 32;
ox_memcpy(d.data(), &decoded, sizeof(decoded)); ox::memcpy(d.data(), &decoded, sizeof(decoded));
auto bit = negBit; auto bit = negBit;
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) { for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
d[0] |= 1 << bit; d[0] |= 1 << bit;
@ -175,7 +175,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
d[0] = d[1]; d[0] = d[1];
d[1] = d0Tmp; d[1] = d0Tmp;
} }
ox_memcpy(&out, d.data(), sizeof(out)); ox::memcpy(&out, d.data(), sizeof(out));
return out; return out;
} }
} }

View File

@ -995,7 +995,7 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox_memcpy(&m_data, &other.m_data, sizeof(m_data)); ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
break; break;
case Type::String: case Type::String:
m_data.str = new String(other.get<String>()); m_data.str = new String(other.get<String>());
@ -1028,8 +1028,8 @@ constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox_memcpy(&m_data, &other.m_data, sizeof(m_data)); ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
ox_memset(&other.m_data, 0, sizeof(m_data)); ox::memset(&other.m_data, 0, sizeof(m_data));
break; break;
case Type::String: case Type::String:
m_data.str = other.m_data.str; m_data.str = other.m_data.str;
@ -1220,7 +1220,7 @@ constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox_memcpy(&m_data, &other.m_data, sizeof(m_data)); ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
break; break;
case Type::String: case Type::String:
m_data.str = new String(other.get<String>()); m_data.str = new String(other.get<String>());
@ -1258,8 +1258,8 @@ constexpr ModelValue &ModelValue::operator=(ModelValue &&other) noexcept {
case Type::SignedInteger16: case Type::SignedInteger16:
case Type::SignedInteger32: case Type::SignedInteger32:
case Type::SignedInteger64: case Type::SignedInteger64:
ox_memcpy(&m_data, &other.m_data, sizeof(m_data)); ox::memcpy(&m_data, &other.m_data, sizeof(m_data));
ox_memset(&other.m_data, 0, sizeof(m_data)); ox::memset(&other.m_data, 0, sizeof(m_data));
break; break;
case Type::String: case Type::String:
m_data.str = other.m_data.str; m_data.str = other.m_data.str;

View File

@ -34,7 +34,7 @@ namespace ox {
template<typename To, typename From> template<typename To, typename From>
constexpr typename enable_if<sizeof(To) == sizeof(From), To>::type cbit_cast(From src) noexcept { constexpr typename enable_if<sizeof(To) == sizeof(From), To>::type cbit_cast(From src) noexcept {
To dst = {}; To dst = {};
ox_memcpy(&dst, &src, sizeof(src)); ox::memcpy(&dst, &src, sizeof(src));
return dst; return dst;
} }

View File

@ -119,7 +119,7 @@ constexpr BString<size> &BString<size>::operator=(ox::CRStringView str) noexcept
if (cap() < strLen) { if (cap() < strLen) {
strLen = cap(); strLen = cap();
} }
ox_memcpy(m_buff, str.data(), strLen); ox::memcpy(m_buff, str.data(), strLen);
// make sure last element is a null terminator // make sure last element is a null terminator
m_buff[strLen] = 0; m_buff[strLen] = 0;
return *this; return *this;
@ -131,7 +131,7 @@ constexpr BString<size> &BString<size>::operator=(const char *str) noexcept {
if (cap() < strLen) { if (cap() < strLen) {
strLen = cap(); strLen = cap();
} }
ox_memcpy(m_buff, str, strLen); ox::memcpy(m_buff, str, strLen);
// make sure last element is a null terminator // make sure last element is a null terminator
m_buff[cap()] = 0; m_buff[cap()] = 0;
return *this; return *this;

View File

@ -192,7 +192,7 @@ class BufferReader {
if (m_it + sz > m_size) [[unlikely]] { if (m_it + sz > m_size) [[unlikely]] {
return OxError(1, "Read failed: Buffer overrun"); return OxError(1, "Read failed: Buffer overrun");
} }
ox_memcpy(v, &m_buff[m_it], sz); ox::memcpy(v, &m_buff[m_it], sz);
m_it += sz; m_it += sz;
return sz; return sz;
} }

View File

@ -6,6 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include "defines.hpp"
#include "types.hpp" #include "types.hpp"
#include "memops.hpp" #include "memops.hpp"
@ -16,15 +17,15 @@
extern "C" { extern "C" {
void *ox_inhibit_loop_to_libcall memcpy(void *dest, const void *src, std::size_t size) { void *ox_inhibit_loop_to_libcall memcpy(void *dest, const void *src, std::size_t size) {
return ox_memcpy(dest, src, size); return ox::memcpy(dest, src, size);
} }
void *ox_inhibit_loop_to_libcall memmove(void *dest, const void *src, std::size_t size) { void *ox_inhibit_loop_to_libcall memmove(void *dest, const void *src, std::size_t size) {
return ox_memcpy(dest, src, size); return ox::memcpy(dest, src, size);
} }
void *ox_inhibit_loop_to_libcall memset(void *ptr, int val, std::size_t size) { void *ox_inhibit_loop_to_libcall memset(void *ptr, int val, std::size_t size) {
return ox_memset(ptr, val, size); return ox::memset(ptr, val, size);
} }
@ -50,6 +51,48 @@ int ox_inhibit_loop_to_libcall memcmp(const void *ptr1, const void *ptr2, std::s
#endif #endif
int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept { namespace ox {
return memcmp(ptr1, ptr2, size);
void *memmove(void *dest, const void *src, std::size_t size) noexcept {
if constexpr(!ox::defines::UseStdLib) {
auto srcBuf = static_cast<const char*>(src);
auto dstBuf = static_cast<char*>(dest);
for (std::size_t i = 0; i < size; ++i) {
dstBuf[i] = static_cast<char>(srcBuf[i]);
}
return dest;
} else {
return ::memmove(dest, src, size);
}
}
void *memset(void *ptr, int val, std::size_t size) noexcept {
if constexpr(!ox::defines::UseStdLib) {
auto buf = static_cast<uint8_t*>(ptr);
for (std::size_t i = 0; i < size; ++i) {
buf[i] = static_cast<uint8_t>(val);
}
return ptr;
} else {
return ::memset(ptr, val, size);
}
}
void *memcpy(void *dest, const void *src, std::size_t size) noexcept {
if constexpr(!ox::defines::UseStdLib) {
auto srcBuf = static_cast<const char*>(src);
auto dstBuf = static_cast<char*>(dest);
for (std::size_t i = 0; i < size; ++i) {
dstBuf[i] = static_cast<char>(srcBuf[i]);
}
return dest;
} else {
return ::memcpy(dest, src, size);
}
}
int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
return ::memcmp(ptr1, ptr2, size);
}
} }

View File

@ -8,7 +8,6 @@
#pragma once #pragma once
#include "defines.hpp"
#include "types.hpp" #include "types.hpp"
#include "typetraits.hpp" #include "typetraits.hpp"
@ -28,63 +27,28 @@ int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
} }
#endif #endif
int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
constexpr void *ox_memcpy(void *dest, const void *src, std::size_t size) noexcept {
if (std::is_constant_evaluated() || !ox::defines::UseStdLib) {
auto srcBuf = static_cast<const char*>(src);
auto dstBuf = static_cast<char*>(dest);
for (std::size_t i = 0; i < size; ++i) {
dstBuf[i] = static_cast<char>(srcBuf[i]);
}
return dest;
} else {
return memcpy(dest, src, size);
}
}
constexpr void *ox_memmove(void *dest, const void *src, std::size_t size) noexcept {
if (std::is_constant_evaluated() || !ox::defines::UseStdLib) {
auto srcBuf = static_cast<const char *>(src);
auto dstBuf = static_cast<char *>(dest);
for (std::size_t i = 0; i < size; ++i) {
dstBuf[i] = static_cast<char>(srcBuf[i]);
}
return dest;
} else {
return memmove(dest, src, size);
}
}
constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
if (std::is_constant_evaluated() || !ox::defines::UseStdLib) {
auto buf = static_cast<uint8_t*>(ptr);
for (std::size_t i = 0; i < size; ++i) {
buf[i] = static_cast<uint8_t>(val);
}
return ptr;
} else {
return memset(ptr, val, size);
}
}
namespace ox { namespace ox {
constexpr void *memmove(void *dest, const void *src, std::size_t size) { template<typename T1, typename T2>
return ox_memmove(dest, src, size); constexpr T1 *listcpy(T1 *dest, T2 *src, std::size_t maxLen) noexcept {
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
std::size_t i = 0;
while (i < maxLen && src[i]) {
dest[i] = static_cast<T1Type>(src[i]);
++i;
}
// set null terminator
dest[i] = 0;
return dest;
} }
constexpr void *memset(void *ptr, int val, std::size_t size) noexcept { void *memmove(void *dest, const void *src, std::size_t size) noexcept;
return ox_memset(ptr, val, size);
}
constexpr void *memcpy(void *dest, const void *src, std::size_t size) noexcept { void *memset(void *ptr, int val, std::size_t size) noexcept;
return ox_memcpy(dest, src, size);
}
inline int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept { void *memcpy(void *dest, const void *src, std::size_t size) noexcept;
return ox_memcmp(ptr1, ptr2, size);
} int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
template<typename T> template<typename T>
void *memsetElements(T *ptr, T val, std::size_t elements) noexcept { void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {

View File

@ -167,7 +167,7 @@ class BasicString {
constexpr Error append(const char *str, std::size_t strLen) noexcept { constexpr Error append(const char *str, std::size_t strLen) noexcept {
auto currentLen = len(); auto currentLen = len();
m_buff.resize(m_buff.size() + strLen); m_buff.resize(m_buff.size() + strLen);
ox_memcpy(&m_buff[currentLen], str, strLen); ox::memcpy(&m_buff[currentLen], str, strLen);
// make sure last element is a null terminator // make sure last element is a null terminator
m_buff[currentLen + strLen] = 0; m_buff[currentLen + strLen] = 0;
// this can't fail, but it returns an Error to match BString::append // this can't fail, but it returns an Error to match BString::append

View File

@ -44,25 +44,25 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
{ {
"ABCDEFG != HIJKLMN", "ABCDEFG != HIJKLMN",
[]() { []() {
return OxError(ox_memcmp("ABCDEFG", "HIJKLMN", 7) >= 0); return OxError(ox::memcmp("ABCDEFG", "HIJKLMN", 7) >= 0);
} }
}, },
{ {
"HIJKLMN != ABCDEFG", "HIJKLMN != ABCDEFG",
[]() { []() {
return OxError(ox_memcmp("HIJKLMN", "ABCDEFG", 7) <= 0); return OxError(ox::memcmp("HIJKLMN", "ABCDEFG", 7) <= 0);
} }
}, },
{ {
"ABCDEFG == ABCDEFG", "ABCDEFG == ABCDEFG",
[]() { []() {
return OxError(ox_memcmp("ABCDEFG", "ABCDEFG", 7) != 0); return OxError(ox::memcmp("ABCDEFG", "ABCDEFG", 7) != 0);
} }
}, },
{ {
"ABCDEFGHI == ABCDEFG", "ABCDEFGHI == ABCDEFG",
[]() { []() {
return OxError(ox_memcmp("ABCDEFGHI", "ABCDEFG", 7) != 0); return OxError(ox::memcmp("ABCDEFGHI", "ABCDEFG", 7) != 0);
} }
}, },
{ {