blob: d096ba4d47d2cc7530e55f9b60fe794a4cf3a69d [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "utils.hpp"
#include "constants.hpp"
#include <algorithm>
#include <assert.h>
#include <functional>
#include <uv.h>
#if (defined(WIN32) || defined(_WIN32))
#include <windows.h>
#else
#include <sched.h>
#include <unistd.h>
#endif
namespace datastax { namespace internal {
String opcode_to_string(int opcode) {
switch (opcode) {
case CQL_OPCODE_ERROR:
return "CQL_OPCODE_ERROR";
case CQL_OPCODE_STARTUP:
return "CQL_OPCODE_STARTUP";
case CQL_OPCODE_READY:
return "CQL_OPCODE_READY";
case CQL_OPCODE_AUTHENTICATE:
return "CQL_OPCODE_AUTHENTICATE";
case CQL_OPCODE_CREDENTIALS:
return "CQL_OPCODE_CREDENTIALS";
case CQL_OPCODE_OPTIONS:
return "CQL_OPCODE_OPTIONS";
case CQL_OPCODE_SUPPORTED:
return "CQL_OPCODE_SUPPORTED";
case CQL_OPCODE_QUERY:
return "CQL_OPCODE_QUERY";
case CQL_OPCODE_RESULT:
return "CQL_OPCODE_RESULT";
case CQL_OPCODE_PREPARE:
return "CQL_OPCODE_PREPARE";
case CQL_OPCODE_EXECUTE:
return "CQL_OPCODE_EXECUTE";
case CQL_OPCODE_REGISTER:
return "CQL_OPCODE_REGISTER";
case CQL_OPCODE_EVENT:
return "CQL_OPCODE_EVENT";
case CQL_OPCODE_BATCH:
return "CQL_OPCODE_BATCH";
case CQL_OPCODE_AUTH_CHALLENGE:
return "CQL_OPCODE_AUTH_CHALLENGE";
case CQL_OPCODE_AUTH_RESPONSE:
return "CQL_OPCODE_AUTH_RESPONSE";
case CQL_OPCODE_AUTH_SUCCESS:
return "CQL_OPCODE_AUTH_SUCCESS";
};
assert(false);
return "";
}
String to_string(const CassUuid& uuid) {
char str[CASS_UUID_STRING_LENGTH];
cass_uuid_string(uuid, str);
return String(str);
}
void explode(const String& str, Vector<String>& vec, const char delimiter /* = ',' */) {
IStringStream stream(str);
while (!stream.eof()) {
String token;
std::getline(stream, token, delimiter);
if (!trim(token).empty()) {
vec.push_back(token);
}
}
}
String implode(const Vector<String>& vec, const char delimiter /* = ' ' */) {
String str;
for (Vector<String>::const_iterator it = vec.begin(), end = vec.end(); it != end; ++it) {
if (!str.empty()) {
str.push_back(delimiter);
}
str.append(*it);
}
return str;
}
bool not_isspace(int c) { return !::isspace(c); }
String& trim(String& str) {
// Trim front
str.erase(str.begin(), std::find_if(str.begin(), str.end(), not_isspace));
// Trim back
str.erase(std::find_if(str.rbegin(), str.rend(), not_isspace).base(), str.end());
return str;
}
static bool is_lowercase(const String& str) {
if (str.empty()) return true;
char c = str[0];
if (!(c >= 'a' && c <= 'z')) return false;
for (String::const_iterator it = str.begin() + 1, end = str.end(); it != end; ++it) {
char c = *it;
if (!((c >= '0' && c <= '9') || (c == '_') || (c >= 'a' && c <= 'z'))) {
return false;
}
}
return true;
}
static String& quote_id(String& str) {
String temp(str);
str.clear();
str.push_back('"');
for (String::const_iterator i = temp.begin(), end = temp.end(); i != end; ++i) {
if (*i == '"') {
str.push_back('"');
str.push_back('"');
} else {
str.push_back(*i);
}
}
str.push_back('"');
return str;
}
String& escape_id(String& str) { return is_lowercase(str) ? str : quote_id(str); }
int32_t get_pid() {
#if (defined(WIN32) || defined(_WIN32))
return static_cast<int32_t>(GetCurrentProcessId());
#else
return static_cast<int32_t>(getpid());
#endif
}
void thread_yield() {
#if defined(WIN32) || defined(_WIN32)
SwitchToThread();
#else
sched_yield();
#endif
}
// Code was taken from MSDN documentation see:
// https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
#if defined(_MSC_VER) && defined(_DEBUG)
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO {
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
#endif
void set_thread_name(const String& thread_name) {
#if defined(_MSC_VER) && defined(_DEBUG)
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = thread_name.c_str();
info.dwThreadID = (DWORD)-1;
info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable : 6320 6322)
__try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
reinterpret_cast<ULONG_PTR*>(&info));
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
#pragma warning(pop)
#endif
}
}} // namespace datastax::internal