Commit d2a1e1c9 authored by Steven Murray's avatar Steven Murray
Browse files

Moved castor::tape::utils::copyString() to castor::utils.

parent 47511bc6
......@@ -29,6 +29,7 @@
#include "castor/tape/net/net.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/utils/SmartFd.hpp"
#include "castor/utils/utils.hpp"
#include "h/serrno.h"
#include "h/net.h"
......@@ -393,7 +394,7 @@ void castor::tape::net::getSockHostName(
": " << gai_strerror(error));
}
utils::copyString(buf, len, hostName);
castor::utils::copyString(buf, len, hostName);
}
......@@ -486,7 +487,7 @@ void castor::tape::net::getPeerHostName(
": " << gai_strerror(rc));
}
utils::copyString(buf, len, hostName);
castor::utils::copyString(buf, len, hostName);
}
}
......
......@@ -1028,11 +1028,11 @@ bool castor::tape::tapebridge::BridgeProtocolEngine::startMigrationSession()
// Give volume to rtcpd
legacymsg::RtcpTapeRqstErrMsgBody rtcpVolume;
utils::setBytes(rtcpVolume, '\0');
utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
utils::copyString(rtcpVolume.vsn , EMPTYVSN );
utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
utils::copyString(rtcpVolume.density, m_volume.density().c_str());
utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
castor::utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
castor::utils::copyString(rtcpVolume.vsn , EMPTYVSN );
castor::utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
castor::utils::copyString(rtcpVolume.density, m_volume.density().c_str());
castor::utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
rtcpVolume.volReqId = m_jobRequest.volReqId;
rtcpVolume.mode = WRITE_ENABLE;
rtcpVolume.tStartRequest = time(NULL);
......@@ -1093,7 +1093,7 @@ bool castor::tape::tapebridge::BridgeProtocolEngine::startMigrationSession()
unsigned char blockId[4];
utils::setBytes(blockId, '\0');
char nshost[CA_MAXHOSTNAMELEN+1];
utils::copyString(nshost, firstFileToMigrate->nshost().c_str());
castor::utils::copyString(nshost, firstFileToMigrate->nshost().c_str());
RtcpTxRx::giveFileToRtcpd(
m_cuuid,
......@@ -1139,11 +1139,11 @@ void castor::tape::tapebridge::BridgeProtocolEngine::startRecallSession()
// Give volume to rtcpd
legacymsg::RtcpTapeRqstErrMsgBody rtcpVolume;
utils::setBytes(rtcpVolume, '\0');
utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
utils::copyString(rtcpVolume.vsn , EMPTYVSN );
utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
utils::copyString(rtcpVolume.density, m_volume.density().c_str());
utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
castor::utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
castor::utils::copyString(rtcpVolume.vsn , EMPTYVSN );
castor::utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
castor::utils::copyString(rtcpVolume.density, m_volume.density().c_str());
castor::utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
rtcpVolume.volReqId = m_jobRequest.volReqId;
rtcpVolume.mode = WRITE_DISABLE;
rtcpVolume.tStartRequest = time(NULL);
......@@ -1176,11 +1176,11 @@ void castor::tape::tapebridge::BridgeProtocolEngine::startDumpSession()
// Give volume to rtcpd
legacymsg::RtcpTapeRqstErrMsgBody rtcpVolume;
utils::setBytes(rtcpVolume, '\0');
utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
utils::copyString(rtcpVolume.vsn , EMPTYVSN );
utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
utils::copyString(rtcpVolume.density, m_volume.density().c_str());
utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
castor::utils::copyString(rtcpVolume.vid , m_volume.vid().c_str() );
castor::utils::copyString(rtcpVolume.vsn , EMPTYVSN );
castor::utils::copyString(rtcpVolume.label , m_volume.label().c_str() );
castor::utils::copyString(rtcpVolume.density, m_volume.density().c_str());
castor::utils::copyString(rtcpVolume.unit , m_jobRequest.driveUnit );
rtcpVolume.volReqId = m_jobRequest.volReqId;
rtcpVolume.mode = WRITE_DISABLE;
rtcpVolume.tStartRequest = time(NULL);
......@@ -1894,7 +1894,7 @@ void castor::tape::tapebridge::BridgeProtocolEngine::sendFileToRecallToRtcpd(
fileToRecall.blockId2,
fileToRecall.blockId3};
char nshost[CA_MAXHOSTNAMELEN+1];
utils::copyString(nshost, fileToRecall.nsHost.c_str());
castor::utils::copyString(nshost, fileToRecall.nsHost.c_str());
// The file size is not specified when recalling
const uint64_t fileSize = 0;
......@@ -3038,7 +3038,7 @@ void castor::tape::tapebridge::BridgeProtocolEngine::sendFileToMigrateToRtcpd(
unsigned char blockId[4];
utils::setBytes(blockId, '\0');
char nshost[CA_MAXHOSTNAMELEN+1];
utils::copyString(nshost, fileToMigrate.nsHost.c_str());
castor::utils::copyString(nshost, fileToMigrate.nsHost.c_str());
RtcpTxRx::giveFileToRtcpd(
m_cuuid,
......
......@@ -32,6 +32,7 @@
#include "castor/tape/net/net.hpp"
#include "castor/tape/tapegateway/NoMoreFiles.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/utils/utils.hpp"
#include "h/common.h"
#include "h/Ctape_constants.h"
#include "h/rtcp.h"
......@@ -570,9 +571,9 @@ void castor::tape::tapebridge::RtcpTxRx::askRtcpdToRequestMoreWork(
utils::setBytes(msgBody, '\0');
utils::copyString(msgBody.rqst.recfm_noLongerUsed, "F");
castor::utils::copyString(msgBody.rqst.recfm_noLongerUsed, "F");
utils::copyString(msgBody.rqst.tapePath, tapePath);
castor::utils::copyString(msgBody.rqst.tapePath, tapePath);
msgBody.rqst.volReqId = volReqId;
msgBody.rqst.jobId = -1;
msgBody.rqst.stageSubReqId = -1;
......@@ -666,10 +667,10 @@ void castor::tape::tapebridge::RtcpTxRx::giveFileToRtcpd(
// Give file information to RTCPD
utils::setBytes(msgBody, '\0');
utils::copyString(msgBody.rqst.filePath, filePath );
utils::copyString(msgBody.rqst.tapePath, tapePath );
utils::copyString(msgBody.rqst.recfm_noLongerUsed, "F");
utils::copyString(msgBody.rqst.fid , tapeFileId );
castor::utils::copyString(msgBody.rqst.filePath, filePath );
castor::utils::copyString(msgBody.rqst.tapePath, tapePath );
castor::utils::copyString(msgBody.rqst.recfm_noLongerUsed, "F");
castor::utils::copyString(msgBody.rqst.fid , tapeFileId );
msgBody.rqst.volReqId = volReqId;
msgBody.rqst.jobId = -1;
......@@ -693,7 +694,7 @@ void castor::tape::tapebridge::RtcpTxRx::giveFileToRtcpd(
msgBody.rqst.blockId[2] = blockId[2];
msgBody.rqst.blockId[3] = blockId[3];
msgBody.rqst.bytesIn = fileSize;
utils::copyString(msgBody.rqst.segAttr.nameServerHostName,
castor::utils::copyString(msgBody.rqst.segAttr.nameServerHostName,
nameServerHostName);
msgBody.rqst.segAttr.castorFileId = castorFileId;
msgBody.err.severity = RTCP_OK;
......
......@@ -49,6 +49,7 @@
#include "castor/tape/utils/SmartFdList.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/utils/SmartFd.hpp"
#include "castor/utils/utils.hpp"
#include "h/common.h"
#include "h/Ctape_constants.h"
#include "h/rtcp_constants.h"
......@@ -400,11 +401,13 @@ castor::tape::legacymsg::RtcpJobReplyMsgBody
clientInfoMsgBody.maxFilesBeforeFlush = 1;
}
utils::copyString(clientInfoMsgBody.bridgeHost, bridgeCallbackHost);
utils::copyString(clientInfoMsgBody.bridgeClientHost, jobRequest.clientHost);
utils::copyString(clientInfoMsgBody.dgn, jobRequest.dgn);
utils::copyString(clientInfoMsgBody.drive, jobRequest.driveUnit);
utils::copyString(clientInfoMsgBody.clientName, jobRequest.clientUserName);
castor::utils::copyString(clientInfoMsgBody.bridgeHost, bridgeCallbackHost);
castor::utils::copyString(clientInfoMsgBody.bridgeClientHost,
jobRequest.clientHost);
castor::utils::copyString(clientInfoMsgBody.dgn, jobRequest.dgn);
castor::utils::copyString(clientInfoMsgBody.drive, jobRequest.driveUnit);
castor::utils::copyString(clientInfoMsgBody.clientName,
jobRequest.clientUserName);
try {
castor::tape::tapebridge::BridgeClientInfo2Sender::send(
......
......@@ -59,7 +59,7 @@ void castor::tape::tapebridge::VmgrTxRx::getTapeInfoFromVmgr(
char *p = NULL;
if((p = getenv("VMGR_HOST")) || (p = getconfent("VMGR", "HOST", 0))) {
utils::copyString(vmgrHost, p);
castor::utils::copyString(vmgrHost, p);
} else {
castor::exception::Exception ex(EVMGRNOHOST);
......@@ -110,7 +110,7 @@ void castor::tape::tapebridge::VmgrTxRx::getTapeInfoFromVmgr(
utils::setBytes(request, '\0');
request.uid = uid;
request.gid = gid;
utils::copyString(request.vid, vid);
castor::utils::copyString(request.vid, vid);
request.side = 0; // HARDCODED side
// Marshal the request
......
......@@ -137,7 +137,7 @@ void castor::tape::tpcp::DumpTpCommand::parseCommandLine(const int argc,
case 's':
m_cmdLine.serverSet = true;
try {
utils::copyString(m_cmdLine.server, optarg);
castor::utils::copyString(m_cmdLine.server, optarg);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy the argument of the server command-line option"
......@@ -321,7 +321,7 @@ void castor::tape::tpcp::DumpTpCommand::parseCommandLine(const int argc,
// Parse the VID command-line argument
try {
utils::copyString(m_cmdLine.vid, argv[optind]);
castor::utils::copyString(m_cmdLine.vid, argv[optind]);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy VID comand-line argument into the internal data"
......
......@@ -148,7 +148,7 @@ void castor::tape::tpcp::ReadTpCommand::parseCommandLine(const int argc,
case 's':
m_cmdLine.serverSet = true;
try {
utils::copyString(m_cmdLine.server, optarg);
castor::utils::copyString(m_cmdLine.server, optarg);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy the argument of the server command-line option"
......@@ -266,7 +266,7 @@ void castor::tape::tpcp::ReadTpCommand::parseCommandLine(const int argc,
// Parse the VID command-line argument
try {
utils::copyString(m_cmdLine.vid, argv[optind]);
castor::utils::copyString(m_cmdLine.vid, argv[optind]);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy VID comand-line argument into the internal data"
......
......@@ -136,7 +136,7 @@ void castor::tape::tpcp::WriteTpCommand::parseCommandLine(const int argc,
case 's':
m_cmdLine.serverSet = true;
try {
utils::copyString(m_cmdLine.server, optarg);
castor::utils::copyString(m_cmdLine.server, optarg);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy the argument of the server command-line option"
......@@ -222,7 +222,7 @@ void castor::tape::tpcp::WriteTpCommand::parseCommandLine(const int argc,
// Parse the VID command-line argument
try {
utils::copyString(m_cmdLine.vid, argv[optind]);
castor::utils::copyString(m_cmdLine.vid, argv[optind]);
} catch(castor::exception::Exception &ex) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to copy VID comand-line argument into the internal data"
......
......@@ -144,46 +144,6 @@ void castor::tape::utils::toHex(const uint64_t i, char *dst,
dst[nbDigits] = '\0';
}
//-----------------------------------------------------------------------------
// copyString
//-----------------------------------------------------------------------------
void castor::tape::utils::copyString(char *const dst, const size_t dstSize,
const char *const src) throw(castor::exception::Exception) {
if(dst == NULL) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Pointer to destination string is NULL";
throw ex;
}
if(src == NULL) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Pointer to source string is NULL";
throw ex;
}
const size_t srcLen = strlen(src);
if(srcLen >= dstSize) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Source string is longer than destination. Source length: "
<< srcLen << " Max destination length: " << (dstSize - 1);
throw ex;
}
strncpy(dst, src, dstSize);
*(dst + dstSize -1) = '\0'; // Ensure destination string is null terminated
}
//-----------------------------------------------------------------------------
// writeStrings
//-----------------------------------------------------------------------------
......
......@@ -178,33 +178,6 @@ template<typename T> void setBytes(T &object, const int c) throw() {
memset(&object, c, sizeof(object));
}
/**
* Safely copies source string into destination string. The destination
* will always be null terminated if this function is successful.
*
* @param dst Destination string.
* @param dstSize The size of the destination string including the terminating
* null character.
* @param src Source string.
* destination.
*/
void copyString(char *const dst, const size_t dstSize, const char *const src)
throw(castor::exception::Exception);
/**
* Safely copies source string into destination string. The destination
* will always be null terminated if this function is successful.
*
* @param dst Destination string.
* @param src Source string.
*/
template<size_t dstSize> void copyString(char (&dst)[dstSize],
const char *const src)
throw(castor::exception::Exception) {
copyString(dst, dstSize, src);
}
/**
* Writes the specified array of strings to the specified output stream as a
* list of strings separated by the specified separator.
......
......@@ -34,11 +34,21 @@
namespace unitTests {
class castor_utils : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
}
};
/**
* Tests the good day senario of passing a multi-column string to the
* splitString() method.
*/
TEST(castor_utils, testGoodDaySplitString) {
TEST_F(castor_utils, testGoodDaySplitString) {
using namespace castor::utils;
const std::string line("col0 col1 col2 col3 col4 col5 col6 col7");
std::vector<std::string> columns;
......@@ -58,7 +68,7 @@ TEST(castor_utils, testGoodDaySplitString) {
/**
* Test the case of an empty string being passed to the splitString() method.
*/
TEST(castor_utls, testSplitStringWithEmptyString) {
TEST_F(castor_utils, testSplitStringWithEmptyString) {
using namespace castor::utils;
const std::string emptyString;
std::vector<std::string> columns;
......@@ -71,7 +81,7 @@ TEST(castor_utls, testSplitStringWithEmptyString) {
* Test the case of a non-empty string containing no separator character
* passed to the splitString() method.
*/
TEST(castor_utils, testSplitStringWithNoSeparatorInString) {
TEST_F(castor_utils, testSplitStringWithNoSeparatorInString) {
using namespace castor::utils;
const std::string stringContainingNoSeparator =
"stringContainingNoSeparator";
......@@ -82,7 +92,7 @@ TEST(castor_utils, testSplitStringWithNoSeparatorInString) {
ASSERT_EQ(stringContainingNoSeparator, columns[0]);
}
TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec) {
TEST_F(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec) {
using namespace castor::utils;
const timeval bigger = {6, 5};
const timeval smaller = {5, 4};
......@@ -91,7 +101,7 @@ TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec) {
ASSERT_EQ(expected, timevalGreaterThan(bigger, smaller));
}
TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec_swapped) {
TEST_F(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec_swapped) {
using namespace castor::utils;
const timeval bigger = {6, 5};
const timeval smaller = {5, 4};
......@@ -100,7 +110,7 @@ TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_BigUsecSmallUsec_swappe
ASSERT_EQ(expected, timevalGreaterThan(smaller, bigger));
}
TEST (castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec) {
TEST_F(castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec) {
using namespace castor::utils;
const timeval bigger = {4, 3};
const timeval smaller = {2, 7};
......@@ -109,7 +119,7 @@ TEST (castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec) {
ASSERT_EQ(expected, timevalGreaterThan(bigger, smaller));
}
TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec_swapped) {
TEST_F(castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec_swapped) {
using namespace castor::utils;
const timeval bigger = {4, 3};
const timeval smaller = {2, 7};
......@@ -118,7 +128,7 @@ TEST(castor_utils, testTimevalGreaterThan_BigSecSmallSec_SmallUsecBigUsec_swappe
ASSERT_EQ(expected, timevalGreaterThan(smaller, bigger));
}
TEST(castor_utils, testTimevalGreaterThan_EqualSec_EqualUsec) {
TEST_F(castor_utils, testTimevalGreaterThan_EqualSec_EqualUsec) {
using namespace castor::utils;
const timeval a = {8, 9};
const timeval b = {8, 9};
......@@ -127,7 +137,7 @@ TEST(castor_utils, testTimevalGreaterThan_EqualSec_EqualUsec) {
ASSERT_EQ(expected, timevalGreaterThan(a, b));
}
TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec) {
TEST_F(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec) {
using namespace castor::utils;
const timeval bigger = {6, 5};
const timeval smaller = {5, 4};
......@@ -140,7 +150,7 @@ TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec) {
ASSERT_EQ(true, isAMatch);
}
TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec_swapped) {
TEST_F(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec_swapped) {
using namespace castor::utils;
const timeval bigger = {6, 5};
const timeval smaller = {5, 4};
......@@ -153,7 +163,7 @@ TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_BigUsecSmallUsec_swapped) {
ASSERT_EQ(true, isAMatch);
}
TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec) {
TEST_F(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec) {
using namespace castor::utils;
const timeval bigger = {4, 3};
const timeval smaller = {2, 7};
......@@ -166,7 +176,7 @@ TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec) {
ASSERT_EQ(true, isAMatch);
}
TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec_swapped) {
TEST_F(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec_swapped) {
using namespace castor::utils;
const timeval bigger = {4, 3};
const timeval smaller = {2, 7};
......@@ -179,7 +189,7 @@ TEST(castor_utils, testTimevalAbsDiff_BigSecSmallSec_SmallUsecBigUsec_swapped) {
ASSERT_EQ(true, isAMatch);
}
TEST(castor_utils, testTimevalAbsDiff_EqualSec_EqualUsec) {
TEST_F(castor_utils, testTimevalAbsDiff_EqualSec_EqualUsec) {
using namespace castor::utils;
const timeval a = {8, 9};
const timeval b = {8, 9};
......@@ -191,7 +201,7 @@ TEST(castor_utils, testTimevalAbsDiff_EqualSec_EqualUsec) {
ASSERT_EQ(true, isAMatch);
}
TEST(castor_utils, testTimevalToDouble) {
TEST_F(castor_utils, testTimevalToDouble) {
using namespace castor::utils;
const timeval tv = {1234, 999992};
const double expected = 1234.999992;
......@@ -200,4 +210,29 @@ TEST(castor_utils, testTimevalToDouble) {
ASSERT_EQ(expected, actual);
}
TEST_F(castor_utils, testCopyStringNullDst) {
using namespace castor::utils;
char dummy[6] = "Dummy";
ASSERT_THROW(copyString(NULL, 0, dummy),
castor::exception::Exception);
}
TEST_F(castor_utils, testCopyStringNullSrc) {
using namespace castor::utils;
char dummy[6] = "Dummy";
ASSERT_THROW(copyString(dummy, sizeof(dummy), NULL),
castor::exception::Exception);
}
TEST_F(castor_utils, testCopyString) {
using namespace castor::utils;
char src[12] = "Hello World";
char dst[12];
copyString(dst, src);
ASSERT_EQ(0, strcmp(dst, src));
}
} // namespace unitTests
......@@ -23,6 +23,7 @@
#include "castor/utils/utils.hpp"
#include <algorithm>
#include <errno.h>
#include <fstream>
#include <iomanip>
#include <iostream>
......@@ -174,3 +175,43 @@ timeval castor::utils::timevalAbsDiff(const timeval &a, const timeval &b)
double castor::utils::timevalToDouble(const timeval &tv) throw() {
return tv.tv_sec + tv.tv_usec / 1000000.0;
}
//-----------------------------------------------------------------------------
// copyString
//-----------------------------------------------------------------------------
void castor::utils::copyString(char *const dst, const size_t dstSize,
const char *const src) throw(castor::exception::Exception) {
if(dst == NULL) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Pointer to destination string is NULL";
throw ex;
}
if(src == NULL) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Pointer to source string is NULL";
throw ex;
}
const size_t srcLen = strlen(src);
if(srcLen >= dstSize) {
castor::exception::Exception ex(EINVAL);
ex.getMessage() << __FUNCTION__
<< ": Source string is longer than destination. Source length: "
<< srcLen << " Max destination length: " << (dstSize - 1);
throw ex;
}
strncpy(dst, src, dstSize);
*(dst + dstSize -1) = '\0'; // Ensure destination string is null terminated
}
......@@ -112,6 +112,33 @@ timeval timevalAbsDiff(const timeval &a, const timeval &b) throw();
*/
double timevalToDouble(const timeval &tv) throw();
/**
* Safely copies source string into destination string. The destination
* will always be null terminated if this function is successful.
*
* @param dst Destination string.
* @param dstSize The size of the destination string including the terminating
* null character.
* @param src Source string.
* destination.
*/
void copyString(char *const dst, const size_t dstSize, const char *const src)
throw(castor::exception::Exception);
/**
* Safely copies source string into destination string. The destination
* will always be null terminated if this function is successful.
*
* @param dst Destination string.
* @param src Source string.
*/
template<size_t dstSize> void copyString(char (&dst)[dstSize],
const char *const src)
throw(castor::exception::Exception) {
copyString(dst, dstSize, src);
}
} // namespace utils
} // namespace castor
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment