// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2021 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_SIMD_STR_H // String toolset. // // Whole vectors are in play at a time, with null termination allowing for // string ops at character granularity. A few basic rules: // // - Strings are laid onto vectors with character elements; the templates // accept c8/i8/u8 in combination with vector sizes of 16, 32 and 64. This // is not always addressable memory, so this is a value-oriented interface // and uses no character pointers; only pointers to vectors (whole strings). // // - Strings are null terminated iff there is room for a null character. If // a vector does not contain a null character the string's length is the // vector size itself. It is up to the caller (or a derived interface) to // compose long strings out of unterminated blocks. // // - Null termination *must* be padded out to the end of the vector. This is // important for performance. Unless otherwise noted there is one string on // a vector at a time and the first character is lane[0] // namespace ircd::simd { template typename std::enable_if() == 1, u8>::type strlen(const T) noexcept; template typename std::enable_if() == 1, bool>::type streq(const T, const T) noexcept; template typename std::enable_if() == 1, T &>::type strcpy(T &, const T) noexcept; template typename std::enable_if() == 1, T &>::type strcpy(T &, const const_buffer &) noexcept; template typename std::enable_if() == 1, T &>::type strcat(T &, const T) noexcept; } template inline typename std::enable_if() == 1, T &>::type ircd::simd::strcat(T &a, const T b) noexcept { static_assert ( sizeof_lane() == 1, "internal template; for 8-bit character basis only" ); size_t j{0}, i { strlen(a) }; while(b[j] && i < lanes()) a[i++] = b[j++]; while(i < lanes()) a[i++] = 0; return a; } template inline typename std::enable_if() == 1, T &>::type ircd::simd::strcpy(T &a, const const_buffer &b) noexcept { static_assert ( sizeof_lane() == 1, "internal template; for 8-bit character basis only" ); size_t i{0}; for(; i < lanes() && i < size(b); ++i) a[i] = b[i]; while(i < lanes()) a[i++] = 0; return a; } template inline typename std::enable_if() == 1, T &>::type ircd::simd::strcpy(T &a, const T b) noexcept { static_assert ( sizeof_lane() == 1, "internal template; for 8-bit character basis only" ); size_t i{0}; for(; b[i] && i < lanes(); ++i) a[i] = b[i]; while(i < lanes()) a[i++] = 0; return a; } template inline typename std::enable_if() == 1, bool>::type ircd::simd::streq(const T a, const T b) noexcept { static_assert ( sizeof_lane() == 1, "internal template; for 8-bit character basis only" ); const auto equal { a == b }; return all(equal); } template inline typename std::enable_if() == 1, ircd::u8>::type ircd::simd::strlen(const T str) noexcept { static_assert ( sizeof_lane() == 1, "internal template; for 8-bit character basis only" ); u8 ret(0); for(; ret < lanes(); ++ret) if(!str[ret]) break; return ret; }