const char *pDir = sbTrgt.GetExecutable().GetDirectory();
const char *pFileName = sbTrgt.GetExecutable().GetFilename();
const CMIUtilString strFile(
- CMIUtilString::Format("%s/%s", pDir, pFileName));
+ CMIUtilString::Format("%s/%s",
+ CMIUtilString::WithNullAsEmpty(pDir),
+ CMIUtilString::WithNullAsEmpty(pFileName)));
const CMICmnMIValueConst miValueConst4(strFile);
const CMICmnMIValueResult miValueResult4("executable", miValueConst4);
miTuple.Add(miValueResult4);
// Add "target-id"
const char *pThreadName = rThread.GetName();
- const MIuint len =
- (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0;
- const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) &&
- CMIUtilString::IsAllValidAlphaAndNumeric(
- pThreadName)); // 32 is arbitrary number
+ const MIuint len = CMIUtilString(pThreadName).length();
+ const bool bHaveName = (len > 0) && (len < 32) && // 32 is arbitrary number
+ CMIUtilString::IsAllValidAlphaAndNumeric(pThreadName);
const char *pThrdFmt = bHaveName ? "%s" : "Thread %d";
CMIUtilString strThread;
if (bHaveName)
lldb::BasicType type_code = value_type.GetBasicType();
if (type_code == lldb::eBasicTypeSignedChar)
- stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue());
+ stream.Printf("%d %s", (int)value.GetValueAsSigned(),
+ CMIUtilString::WithNullAsEmpty(value.GetValue()));
else if (type_code == lldb::eBasicTypeUnsignedChar)
stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(),
- value.GetValue());
+ CMIUtilString::WithNullAsEmpty(value.GetValue()));
else
return false;
//--
static CMIUtilString
BuildAsyncRecord(CMICmnMIOutOfBandRecord::OutOfBand_e veType) {
- return CMIUtilString::Format("%s%s", MapOutOfBandToToken(veType),
- MapOutOfBandToText(veType));
+ auto Token = MapOutOfBandToToken(veType);
+ auto Text = MapOutOfBandToText(veType);
+ return CMIUtilString::Format("%s%s", CMIUtilString::WithNullAsEmpty(Token),
+ CMIUtilString::WithNullAsEmpty(Text));
}
//++
BuildResultRecord(const CMIUtilString &vrToken,
CMICmnMIResultRecord::ResultClass_e veType) {
const char *pStrResultRecord = MapResultClassToResultClassText(veType);
- return CMIUtilString::Format("%s^%s", vrToken.c_str(), pStrResultRecord);
+ return CMIUtilString::Format("%s^%s", vrToken.c_str(),
+ CMIUtilString::WithNullAsEmpty(pStrResultRecord));
}
//++
bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
} else {
for (MIint i = 1; i < argc; i++) {
- strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]);
+ strArgs += CMIUtilString::Format("%d:'%s' ", i,
+ CMIUtilString::WithNullAsEmpty(argv[i]));
}
bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
}
// Return: None.
// Throws: None.
//--
-CMIUtilString::CMIUtilString(const char *vpData) : std::string(vpData) {}
+CMIUtilString::CMIUtilString(const char *vpData)
+ : std::string(WithNullAsEmpty(vpData)) {}
//++
//------------------------------------------------------------------------------------
// Throws: None.
//--
CMIUtilString &CMIUtilString::operator=(const char *vpRhs) {
- assign(vpRhs);
+ assign(WithNullAsEmpty(vpRhs));
return *this;
}
MIint n = vrFormat.size();
// IOR: mysterious crash in this function on some windows builds not able to
- // duplicate
- // but found article which may be related. Crash occurs in vsnprintf() or
- // va_copy()
+ // duplicate but found article which may be related. Crash occurs in
+ // vsnprintf() or va_copy().
// Duplicate vArgs va_list argument pointer to ensure that it can be safely
- // used in
- // a new frame
+ // used in a new frame.
// http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
va_list argsDup;
va_copy(argsDup, vArgs);
pFormatted.reset(new char[n + 1]); // +1 for safety margin
::strncpy(&pFormatted[0], vrFormat.c_str(), n);
- // We need to restore the variable argument list pointer to the start again
- // before running vsnprintf() more then once
+ // We need to restore the variable argument list pointer to the start again
+ // before running vsnprintf() more then once
va_copy(argsDup, argsCpy);
nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup);
CMIUtilString CMIUtilString::Format(const char *vFormating, ...) {
va_list args;
va_start(args, vFormating);
- CMIUtilString strResult = CMIUtilString::FormatPriv(vFormating, args);
+ CMIUtilString strResult =
+ CMIUtilString::FormatPriv(WithNullAsEmpty(vFormating), args);
va_end(args);
return strResult;
// Throws: None.
//--
bool CMIUtilString::IsAllValidAlphaAndNumeric(const char *vpText) {
- const size_t len = ::strlen(vpText);
+ const size_t len = ::strlen(WithNullAsEmpty(vpText));
if (len == 0)
return false;
static CMIUtilString FormatValist(const CMIUtilString &vrFormating,
va_list vArgs);
static bool IsAllValidAlphaAndNumeric(const char *vpText);
+ static const char *WithNullAsEmpty(const char *vpText) {
+ return vpText ? vpText : "";
+ }
static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs);
static CMIUtilString ConvertToPrintableASCII(const char vChar,
bool bEscapeQuotes = false);
+add_subdirectory(lldb-mi)
if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|NetBSD")
if ((CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_TEST_DEBUGSERVER) OR (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_LLDB_SERVER_BUILD))
# These tests are meant to test lldb-server/debugserver in isolation, and
--- /dev/null
+include_directories(${LLDB_SOURCE_DIR}/tools/lldb-mi)
+add_subdirectory(utils)
--- /dev/null
+add_library(lldb-mi-utils OBJECT
+ ${LLDB_SOURCE_DIR}/tools/lldb-mi/MIUtilString.cpp
+ )
+
+add_lldb_unittest(LLDBMiUtilTests
+ StringTest.cpp
+
+ LINK_COMPONENTS
+ Support
+ )
+
+target_sources(LLDBMiUtilTests PRIVATE $<TARGET_OBJECTS:lldb-mi-utils>)
--- /dev/null
+//===-- StringTest.cpp ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MIUtilString.h"
+#include "gtest/gtest.h"
+
+TEST(StringTest, ConstructFromNullptr) {
+ auto str = CMIUtilString(nullptr);
+ EXPECT_TRUE(str.empty());
+ EXPECT_NE(nullptr, str.c_str());
+ EXPECT_EQ(CMIUtilString(""), str);
+}
+
+TEST(StringTest, AssignNullptr) {
+ CMIUtilString str;
+ str = nullptr;
+ EXPECT_TRUE(str.empty());
+ EXPECT_NE(nullptr, str.c_str());
+ EXPECT_EQ(CMIUtilString(""), str);
+}
+
+TEST(StringTest, IsAllValidAlphaAndNumeric) {
+ EXPECT_TRUE(CMIUtilString::IsAllValidAlphaAndNumeric("123abc"));
+ EXPECT_FALSE(CMIUtilString::IsAllValidAlphaAndNumeric(""));
+ EXPECT_FALSE(CMIUtilString::IsAllValidAlphaAndNumeric(nullptr));
+}
+