diff --git a/src/applications/bmqtool/cbmq_test.cpp b/src/applications/bmqtool/cbmq_test.cpp new file mode 100644 index 0000000000..a2b424d306 --- /dev/null +++ b/src/applications/bmqtool/cbmq_test.cpp @@ -0,0 +1,219 @@ +// Copyright 2016-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed 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. + +// m_bmqtool_filelogger.cpp -*-C++-*- +#include + +// BMQ +#include +#include +#include +#include +#include + +// MWC +#include + +// BDE +#include +#include +#include +#include +#include +#include +#include +#include + +namespace BloombergLP { +namespace m_bmqtool { + +namespace { + +const char k_LOG_SESSION_CATEGORY[] = "SESSION"; +const char k_LOG_PUSH_CATEGORY[] = "PUSH"; +const char k_LOG_ACK_CATEGORY[] = "ACK"; +const char k_LOG_PUT_CATEGORY[] = "PUT"; +const char k_LOG_CONFIRM_CATEGORY[] = "CONFIRM"; + +class LogRecord { + private: + ball::Record d_record; + ball::FileObserver2& d_out; + bsl::ostream d_os; + + public: + LogRecord(ball::FileObserver2& out, + const char* category, + int severity = ball::Severity::INFO) + : d_record() + , d_out(out) + , d_os(init(d_record, category, severity)) + { + } + + ~LogRecord() + { + d_out.publish( + d_record, + ball::Context(ball::Transmission::e_MANUAL_PUBLISH, 0, 1)); + } + + template + friend LogRecord& operator<<(LogRecord& record, const T& value); + + private: + static bdlsb::MemOutStreamBuf* + init(ball::Record& record, const char* category, int severity) + { + ball::RecordAttributes& attributes = record.fixedFields(); + + attributes.setTimestamp(bdlt::CurrentTime::utc()); + attributes.setProcessID(bdls::ProcessUtil::getProcessId()); + attributes.setThreadID(bslmt::ThreadUtil::selfIdAsUint64()); + attributes.setCategory(category); + attributes.setSeverity(severity); + // attributes.setFileName(__FILE__); + // attributes.setLineNumber(__LINE__); + + attributes.clearMessage(); + return &attributes.messageStreamBuf(); + } +}; + +template +LogRecord& operator<<(LogRecord& record, const T& value) +{ + record.d_os << value; + return record; +} +static void printSingleLine(LogRecord& record, const bdlbb::Blob& blob) +{ + for (int i = 0; i < blob.numDataBuffers(); ++i) { + record << bslstl::StringRef(blob.buffer(i).data(), + mwcu::BlobUtil::bufferSize(blob, i)); + } +} + +}; // close unnamed namespace + +// ================ +// class FileLogger +// ================ + +FileLogger::FileLogger(const bsl::string& filePath, + bslma::Allocator* allocator) +: d_filePath(filePath) +, d_out(allocator) +{ + // NOTHING +} + +FileLogger::~FileLogger() +{ + close(); +} + +bool FileLogger::open() +{ + d_out.enableFileLogging(d_filePath.c_str()); + + d_out.setLogFileFunctor( + ball::RecordStringFormatter("\n%I %p:%t %s %c %m %u")); + return d_out.isFileLoggingEnabled(); +} + +void FileLogger::close() +{ + d_out.disableFileLogging(); +} + +void FileLogger::writeSessionEvent(const bmqa::SessionEvent& event) +{ + if (!isOpen()) { + // FileLogging is disabled. + return; // RETURN + } + + LogRecord record(d_out, k_LOG_SESSION_CATEGORY); + record << event.type() << "|"; // session event type + + if (event.type() == bmqt::SessionEventType::e_QUEUE_OPEN_RESULT || + event.type() == bmqt::SessionEventType::e_QUEUE_REOPEN_RESULT || + event.type() == bmqt::SessionEventType::e_QUEUE_CLOSE_RESULT) { + record << event.queueId().uri().asString(); // queueUri + } +} + +void FileLogger::writeAckMessage(const bmqa::Message& message) +{ + if (!isOpen()) { + // FileLogging is disabled. + return; // RETURN + } + + LogRecord record(d_out, k_LOG_ACK_CATEGORY); + record << message.queueId().uri().asString() << "|" // QueueUri + << message.correlationId() << "|" // CorrelationId + << message.messageGUID() << "|" // MessageGUID + << message.ackStatus() << "|"; // AckStatus +} + +void FileLogger::writeConfirmMessage(const bmqa::Message& message) +{ + if (!isOpen()) { + // FileLogging is disabled. + return; // RETURN + } + + LogRecord record(d_out, k_LOG_CONFIRM_CATEGORY); + record << message.queueId().uri().asString() << "|" // QueueUri + << message.messageGUID() << "|"; // MessageGUID +} + +void FileLogger::writePushMessage(const bmqa::Message& message) +{ + if (!isOpen()) { + // FileLogging is disabled. + return; // RETURN + } + + LogRecord record(d_out, k_LOG_PUSH_CATEGORY); + record << message.queueId().uri().asString() << "|" // QueueUri + << message.messageGUID() << "|"; // MessageGUID + + bdlbb::Blob payload; + message.getData(&payload); + printSingleLine(record, payload); // Payload +} + +void FileLogger::writePutMessage(const bmqa::Message& message) +{ + if (!isOpen()) { + // FileLogging is disabled. + return; // RETURN + } + + LogRecord record(d_out, k_LOG_PUT_CATEGORY); + record << message.queueId().uri().asString() << "|" // QueueUri + << message.correlationId() << "|" // CorrelationId + << message.messageGUID() << "|"; // MessageGUID + + bdlbb::Blob payload; + message.getData(&payload); + printSingleLine(record, payload); // Payload +} + +} // close package namespace +} // close enterprise namespace diff --git a/src/docstring_replace.py b/src/docstring_replace.py new file mode 100644 index 0000000000..e2643f4957 --- /dev/null +++ b/src/docstring_replace.py @@ -0,0 +1,40 @@ +import os + +bmqa_directory = "bmqa" +z_bmqa_directory = "z_bmqa" + +for filename in os.listdir(bmqa_directory): + if filename.endswith(".h"): + with open(os.path.join(bmqa_directory, filename), "r") as bmqa_file: + lines = bmqa_file.readlines() + docstring_lines = [] + copy_docstring = False + for line in lines: + if "@PURPOSE" in line: + docstring_lines.append(line) + copy_docstring = True + elif copy_docstring and line.strip() == "": + break + elif copy_docstring: + docstring_lines.append(line) + + with open(os.path.join(z_bmqa_directory, "z_" + filename), "r+") as z_bmqa_file: + lines = z_bmqa_file.readlines() + z_bmqa_file.seek(0) + z_bmqa_file.truncate() + include_found = False + copied = False + + for line in lines: + print("line:", line, end="") + if line.startswith("#include"): + z_bmqa_file.write(line) + z_bmqa_file.write("\n") + include_found = True + elif include_found and not copied: + z_bmqa_file.writelines(docstring_lines) + z_bmqa_file.write(line) + include_found = False + copied = True + else: + z_bmqa_file.write(line) diff --git a/src/function_comments.py b/src/function_comments.py new file mode 100644 index 0000000000..198d623513 --- /dev/null +++ b/src/function_comments.py @@ -0,0 +1,114 @@ +import re + + +non_functions = set(["if", "else if", "else", "for", "while", "do"]) + + +def append_to_file(string, filename): + try: + with open(filename, 'a') as file: + file.write(string) + except IOError: + print("Error: Unable to append string to file.") + + +def extract_words(lines): #we need to change this function to find the keywords after '(' because of templated types such as + # Regular expression to match words followed by ',' or ')' + # \b asserts position at a word boundary + # \w+ matches one or more word characters (a-z, A-Z, 0-9, _) + # (?=[,)]) is a positive lookahead to ensure the word is followed by ',' or ')' + pattern = r'\b\w+(?=[,)])' + + extracted_words = set() # Use a set to avoid duplicate words + + for line in lines: + matches = re.findall(pattern, line) + extracted_words.update(matches) # Add found words to the set + + return list(extracted_words) # Convert set to list before returning + + +def process_cpp_file(file_path): + buffer = [] # to store lines temporarily + current_function = "" # to keep track of the current function + function_descriptors = {} + + with open(file_path, 'r') as file: + for line in file: + line = line.strip() # remove leading/trailing whitespaces + + # Clear buffer if line is '}' or empty + if line == '}' or line == '': + buffer.clear() + else: + buffer.append(line) # add line to buffer + + # Update current_function if line contains '{' + if '{' in line: + previous_func = current_function + keyword_found = False + for buf_line in buffer: + if '(' in buf_line: + # Extract function name + func_name = buf_line.split('(')[0].split()[-1] + if func_name not in non_functions: + # print(current_function) + current_function = func_name + function_descriptors[current_function] = extract_words( + buffer) + break + else: + keyword_found = True + if previous_func == current_function and not keyword_found: + print( + f"Function name could not be extracted for buffer: {buffer}") + print(function_descriptors) + return function_descriptors + +def write_commented_file(file_path, new_file_name, function_descriptors): + buffer = [] # to store lines temporarily + current_function = "" # to keep track of the current function + # print(fd['z_bmqt_CorrelationId__delete']) + + with open(file_path, 'r') as file: + for line in file: + temp_line = line + line = line.strip() # remove leading/trailing whitespaces + + # Clear buffer if line is '}' or empty + if line == '}' or line == '': + for p in buffer: + append_to_file(p, new_file_name) + append_to_file(temp_line, new_file_name) + buffer.clear() + else: + buffer.append(temp_line) # add line to buffer + + # Update current_function if line contains '{' + if '{' in line: + previous_func = current_function + keyword_found = False + for buf_line in buffer: + if '(' in buf_line: + # Extract function name + func_name = buf_line.split('(')[0].split()[-1] + if func_name not in non_functions: + current_function = func_name + append_to_file(str(function_descriptors[current_function]), new_file_name) + break + else: + keyword_found = True + else: + append_to_file(buf_line, new_file_name) + + if previous_func == current_function and not keyword_found: + print( + f"Function name could not be extracted for buffer: {buffer}") + +# Example of how to use the function +file_path = 'test_file.cpp' +fd = process_cpp_file(file_path) +print("-----------------------------") +print(fd) +print() +write_commented_file(file_path, "output.cpp", fd) diff --git a/src/groups/wrappers/z_bmq/z_bmqa/bmqt_resultcode.cpp b/src/groups/wrappers/z_bmq/z_bmqa/bmqt_resultcode.cpp new file mode 100644 index 0000000000..6ef992db73 --- /dev/null +++ b/src/groups/wrappers/z_bmq/z_bmqa/bmqt_resultcode.cpp @@ -0,0 +1,540 @@ +// Copyright 2014-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed 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. + +// bmqt_resultcode.cpp -*-C++-*- +#include + +#include +// BDE +#include +#include +#include + +namespace BloombergLP { +namespace bmqt { + +// -------------------- +// struct GenericResult +// -------------------- + +bsl::ostream& GenericResult::print(bsl::ostream& stream, + GenericResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << GenericResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* GenericResult::toAscii(GenericResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool GenericResult::fromAscii(GenericResult::Enum* out, + const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(GenericResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = GenericResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// ---------------------- +// struct OpenQueueResult +// ---------------------- + +bsl::ostream& OpenQueueResult::print(bsl::ostream& stream, + OpenQueueResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << OpenQueueResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* OpenQueueResult::toAscii(OpenQueueResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + BMQT_CASE(ALREADY_OPENED) + BMQT_CASE(ALREADY_IN_PROGRESS) + BMQT_CASE(INVALID_URI) + BMQT_CASE(INVALID_FLAGS) + BMQT_CASE(CORRELATIONID_NOT_UNIQUE) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool OpenQueueResult::fromAscii(OpenQueueResult::Enum* out, + const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(OpenQueueResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = OpenQueueResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + BMQT_CHECKVALUE(ALREADY_OPENED) + BMQT_CHECKVALUE(ALREADY_IN_PROGRESS) + BMQT_CHECKVALUE(INVALID_URI) + BMQT_CHECKVALUE(INVALID_FLAGS) + BMQT_CHECKVALUE(CORRELATIONID_NOT_UNIQUE) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// --------------------------- +// struct ConfigureQueueResult +// --------------------------- + +bsl::ostream& ConfigureQueueResult::print(bsl::ostream& stream, + ConfigureQueueResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << ConfigureQueueResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* ConfigureQueueResult::toAscii(ConfigureQueueResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + BMQT_CASE(ALREADY_IN_PROGRESS) + BMQT_CASE(INVALID_QUEUE) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool ConfigureQueueResult::fromAscii(ConfigureQueueResult::Enum* out, + const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(ConfigureQueueResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = ConfigureQueueResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + BMQT_CHECKVALUE(ALREADY_IN_PROGRESS) + BMQT_CHECKVALUE(INVALID_QUEUE) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// ----------------------- +// struct CloseQueueResult +// ----------------------- + +bsl::ostream& CloseQueueResult::print(bsl::ostream& stream, + CloseQueueResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << CloseQueueResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* CloseQueueResult::toAscii(CloseQueueResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + BMQT_CASE(ALREADY_CLOSED) + BMQT_CASE(ALREADY_IN_PROGRESS) + BMQT_CASE(UNKNOWN_QUEUE) + BMQT_CASE(INVALID_QUEUE) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool CloseQueueResult::fromAscii(CloseQueueResult::Enum* out, + const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(CloseQueueResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = CloseQueueResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + BMQT_CHECKVALUE(ALREADY_CLOSED) + BMQT_CHECKVALUE(ALREADY_IN_PROGRESS) + BMQT_CHECKVALUE(UNKNOWN_QUEUE) + BMQT_CHECKVALUE(INVALID_QUEUE) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// ------------------------- +// struct EventBuilderResult +// ------------------------- + +bsl::ostream& EventBuilderResult::print(bsl::ostream& stream, + EventBuilderResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << EventBuilderResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* EventBuilderResult::toAscii(EventBuilderResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(QUEUE_INVALID) + BMQT_CASE(QUEUE_READONLY) + BMQT_CASE(MISSING_CORRELATION_ID) + BMQT_CASE(EVENT_TOO_BIG) + BMQT_CASE(PAYLOAD_TOO_BIG) + BMQT_CASE(PAYLOAD_EMPTY) + BMQT_CASE(OPTION_TOO_BIG) +#ifdef BMQ_ENABLE_MSG_GROUPID + BMQT_CASE(INVALID_MSG_GROUP_ID) +#endif + BMQT_CASE(QUEUE_SUSPENDED) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool EventBuilderResult::fromAscii(EventBuilderResult::Enum* out, + const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(EventBuilderResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = EventBuilderResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(QUEUE_INVALID) + BMQT_CHECKVALUE(QUEUE_READONLY) + BMQT_CHECKVALUE(MISSING_CORRELATION_ID) + BMQT_CHECKVALUE(EVENT_TOO_BIG) + BMQT_CHECKVALUE(PAYLOAD_TOO_BIG) + BMQT_CHECKVALUE(PAYLOAD_EMPTY) + BMQT_CHECKVALUE(OPTION_TOO_BIG) +#ifdef BMQ_ENABLE_MSG_GROUPID + BMQT_CHECKVALUE(INVALID_MSG_GROUP_ID) +#endif + BMQT_CHECKVALUE(QUEUE_SUSPENDED) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// ---------------- +// struct AckResult +// ---------------- + +bsl::ostream& AckResult::print(bsl::ostream& stream, + AckResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << AckResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* AckResult::toAscii(AckResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + BMQT_CASE(LIMIT_MESSAGES) + BMQT_CASE(LIMIT_BYTES) + BMQT_CASE(LIMIT_QUEUE_MESSAGES) + BMQT_CASE(LIMIT_QUEUE_BYTES) + BMQT_CASE(STORAGE_FAILURE) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool AckResult::fromAscii(AckResult::Enum* out, const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(AckResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = AckResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + BMQT_CHECKVALUE(LIMIT_MESSAGES) + BMQT_CHECKVALUE(LIMIT_BYTES) + BMQT_CHECKVALUE(LIMIT_DOMAIN_MESSAGES) + BMQT_CHECKVALUE(LIMIT_DOMAIN_BYTES) + BMQT_CHECKVALUE(LIMIT_QUEUE_MESSAGES) + BMQT_CHECKVALUE(LIMIT_QUEUE_BYTES) + BMQT_CHECKVALUE(STORAGE_FAILURE) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +// ----------------- +// struct PostResult +// ----------------- + +bsl::ostream& PostResult::print(bsl::ostream& stream, + PostResult::Enum value, + int level, + int spacesPerLevel) +{ + bdlb::Print::indent(stream, level, spacesPerLevel); + stream << PostResult::toAscii(value); + + if (spacesPerLevel >= 0) { + stream << '\n'; + } + + return stream; +} + +const char* PostResult::toAscii(PostResult::Enum value) +{ +#define BMQT_CASE(X) \ + case e_##X: return #X; + + switch (value) { + BMQT_CASE(SUCCESS) + BMQT_CASE(UNKNOWN) + BMQT_CASE(TIMEOUT) + BMQT_CASE(NOT_CONNECTED) + BMQT_CASE(CANCELED) + BMQT_CASE(NOT_SUPPORTED) + BMQT_CASE(REFUSED) + BMQT_CASE(INVALID_ARGUMENT) + BMQT_CASE(NOT_READY) + BMQT_CASE(BW_LIMIT) + default: return "(* UNKNOWN *)"; + } + +#undef BMQT_CASE +} + +bool PostResult::fromAscii(PostResult::Enum* out, const bslstl::StringRef& str) +{ +#define BMQT_CHECKVALUE(M) \ + if (bdlb::String::areEqualCaseless(toAscii(PostResult::e_##M), \ + str.data(), \ + str.length())) { \ + *out = PostResult::e_##M; \ + return true; \ + } + + BMQT_CHECKVALUE(SUCCESS) + BMQT_CHECKVALUE(UNKNOWN) + BMQT_CHECKVALUE(TIMEOUT) + BMQT_CHECKVALUE(NOT_CONNECTED) + BMQT_CHECKVALUE(CANCELED) + BMQT_CHECKVALUE(NOT_SUPPORTED) + BMQT_CHECKVALUE(REFUSED) + BMQT_CHECKVALUE(INVALID_ARGUMENT) + BMQT_CHECKVALUE(NOT_READY) + BMQT_CHECKVALUE(BW_LIMIT) + + // Invalid string + return false; + +#undef BMQT_CHECKVALUE +} + +} // close package namespace +} // close enterprise namespace diff --git a/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.cpp b/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.cpp new file mode 100644 index 0000000000..eb56d72a58 --- /dev/null +++ b/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include + +const char* z_bmqt_CompressionAlgorithmType::toAscii( + z_bmqt_CompressionAlgorithmType::Enum value) +{ + using namespace BloombergLP; + + return bmqt::CompressionAlgorithmType::toAscii( + static_cast(value)); +} + +bool fromAscii(z_bmqt_CompressionAlgorithmType::Enum* out, const char* str) +{ + using namespace BloombergLP; + bmqt::CompressionAlgorithmType::Enum type; + bool result = bmqt::CompressionAlgorithmType::fromAscii(&type, str); + *out = static_cast(type); + return result; +} + +bool isValid(const char* str, char** error) +{ + using namespace BloombergLP; + bsl::ostringstream os; + bsl::string temp_str(str); + bool result = bmqt::CompressionAlgorithmType::isValid(&temp_str, os); + + bsl::string error_str = os.str(); + + if (error_str.size() != 0) { + *error = new char[error_str.size() + 1]; + (*error)[error_str.size()] = '\0'; + strncpy(*error, error_str.c_str()); + } + else { + *error = NULL; + } + + return result; +} \ No newline at end of file diff --git a/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.t.cpp b/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.t.cpp new file mode 100644 index 0000000000..bb6397550f --- /dev/null +++ b/src/groups/wrappers/z_bmq/z_bmqa/z_bmqt_compressionalgorithmtype.t.cpp @@ -0,0 +1,120 @@ +// Copyright 2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed 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. + +// bmqt_compressionalgorithmtype.t.cpp +#include + +// MWC +#include + +// TEST DRIVER +#include + +// BDE +#include +#include + +// CONVENIENCE +using namespace BloombergLP; +using namespace bsl; + +// ============================================================================ +// TEST HELPERS UTILITY +// ---------------------------------------------------------------------------- +namespace { + +struct ToAsciiTestData { + int d_type; + const char* d_expected; +}; + +} // close unnamed namespace + +// ============================================================================ +// TESTS +// ---------------------------------------------------------------------------- + +template +static void enumToAsciiHelper(ARRAY (&data)[SIZE]) +{ + for (size_t idx = 0; idx < SIZE; ++idx) { + const ToAsciiTestData& test = data[idx]; + z_bmqt_CompressionAlgorithmType::Enum type = + static_cast(test.d_type); + const char* result = z_bmqt_CompressionAlgorithmType::toAscii(type); + ASSERT_EQ(strcmp(result, test.d_expected), 0); + } +} + +static void test1_enumToAscii() +// ------------------------------------------------------------------------ +// ENUM LAYOUT +// +// Concerns: +// Check that enums toAscii methods work correct +// +// Plan: +// 1. For every type of enum for which there is a corresponding toAscii +// function check that output of the print function. +// equal to expected value +// 2. Check that the result for invalid value is equal to expected. +// +// Testing: +// z_bmqt_CompressionAlgorithmType::toAscii +// operator<<(bsl::ostream&, CompressionAlgorithmType::Enum) +// ------------------------------------------------------------------------ +{ + mwctst::TestHelper::printTestName("ENUM LAYOUT"); + + PV("Test bmqt::CompressionAlgorithmType printing"); + { + BSLMF_ASSERT( + z_bmqt_CompressionAlgorithmType::k_LOWEST_SUPPORTED_TYPE == + z_bmqt_CompressionAlgorithmType::ec_NONE); + + BSLMF_ASSERT( + z_bmqt_CompressionAlgorithmType::k_HIGHEST_SUPPORTED_TYPE == + z_bmqt_CompressionAlgorithmType::ec_ZLIB); + + ToAsciiTestData k_DATA[] = { + {z_bmqt_CompressionAlgorithmType::ec_UNKNOWN, "UNKNOWN"}, + {z_bmqt_CompressionAlgorithmType::ec_NONE, "NONE"}, + {z_bmqt_CompressionAlgorithmType::ec_ZLIB, "ZLIB"}, + {z_bmqt_CompressionAlgorithmType::k_HIGHEST_SUPPORTED_TYPE + 1, + "(* UNKNOWN *)"}}; + + enumToAsciiHelper(k_DATA); + } +} + +// ============================================================================ +// MAIN PROGRAM +// ---------------------------------------------------------------------------- + +int main(int argc, char* argv[]) +{ + TEST_PROLOG(mwctst::TestHelper::e_DEFAULT); + + switch (_testCase) { + case 0: + case 1: test1_enumToAscii(); break; + default: { + cerr << "WARNING: CASE '" << _testCase << "' NOT FOUND." << endl; + s_testStatus = -1; + } break; + } + + TEST_EPILOG(mwctst::TestHelper::e_CHECK_DEF_GBL_ALLOC); +}