Developer Application Interface (ARC API) v4.5.8
ARC, Inc. GenIV Application Interface
CArcBase.h
1// +------------------------------------------------------------------------------------------------------------------+
2// | FILE: ArcBase.h ( GenIV ) |
3// +------------------------------------------------------------------------------------------------------------------+
4// | PURPOSE: This file defines the ARC base class. |
5// | |
6// | AUTHOR: Scott Streit DATE: Sept 25, 2014 |
7// | |
8// | Copyright 2013 Astronomical Research Cameras, Inc. All rights reserved. |
9// +------------------------------------------------------------------------------------------------------------------+
12#pragma once
13
14#ifdef _WINDOWS
15
16 #include <windows.h>
17
18#else
19
20 #include <cstring>
21
22#endif
23
24#ifdef __cpp_lib_format
25 #include <format>
26#endif
27
28#include <type_traits>
29#include <filesystem>
30#include <stdexcept>
31#include <string>
32#include <sstream>
33#include <cstdint>
34#include <cstdarg>
35#include <chrono>
36#include <thread>
37#include <concepts>
38#include <string_view>
39#include <source_location>
40
41#include <CArcBaseDllMain.h>
42#include <CArcStringList.h>
43
44using namespace std::string_literals;
45using namespace std::string_view_literals;
46
47
48
49namespace arc
50{
51 namespace gen4
52 {
53
54 // +----------------------------------------------------------------------------------------------------------+
55 // | throwArcGen4xxx functions |
56 // +----------------------------------------------------------------------------------------------------------+
57 // | Convenience to auto fill filename, method name and line number |
58 // +----------------------------------------------------------------------------------------------------------+
59
64 template <typename... Args>
66 {
72 throwFormat_t( const char* pszFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( pszFormat ), m_location( tLocation )
73 {
74 }
75
81 throwFormat_t( const std::string& sFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( sFormat ), m_location( tLocation )
82 {
83 }
84
90 throwFormat_t( std::string_view svFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( svFormat ), m_location( tLocation )
91 {
92 }
93
94 std::string m_format;
96 std::source_location m_location;
97 };
98
99
105 template <typename... Args>
106 void throwArcGen4Error( const throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
107 {
108 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
109
110 #ifdef __cpp_lib_format
111
112 throw std::runtime_error( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
113 std::format( " at file: {}, func: {}, line: {}",
114 sFile,
115 tFormat.m_location.function_name(),
116 tFormat.m_location.line() ) );
117
118 #else
119
120 std::ostringstream oss;
121
122 oss << tFormat.m_format << " at file: " << sFile << ", func: "
123 << tFormat.m_location.function_name() << ", line: "
124 << tFormat.m_location.line() << std::ends;
125
126 throw std::runtime_error( oss.str() );
127
128 #endif
129 }
130
131
137 template <typename... Args>
138 void throwArcGen4InvalidArgument( const throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
139 {
140 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
141
142 #ifdef __cpp_lib_format
143
144 throw std::invalid_argument( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
145 std::format( " at file: {}, func: {}, line: {}",
146 sFile,
147 tFormat.m_location.function_name(),
148 tFormat.m_location.line() ) );
149
150 #else
151
152 std::ostringstream oss;
153
154 oss << tFormat.m_format << " at file: " << sFile << ", func: "
155 << tFormat.m_location.function_name() << ", line: "
156 << tFormat.m_location.line() << std::ends;
157
158 throw std::invalid_argument( oss.str() );
159
160 #endif
161 }
162
163
169 template <typename... Args>
171 {
172 throwArcGen4OutOfRange( const std::uint32_t uiElement, const std::pair<std::uint32_t, std::uint32_t>&& tRange , const std::source_location& location = std::source_location::current() )
173 {
174 auto [uiMin, uiMax] { tRange };
175
176 auto sFile = std::filesystem::path( location.file_name() ).filename().string();
177
178 #ifdef __cpp_lib_format
179
180 throw std::out_of_range( std::format( "Element [ {} ] out of range [ {} - {} ]\nTrace: ( {} {}() line: {} )"sv, uiElement, uiMin, uiMax, sFile, location.function_name(), location.line() ) );
181
182 #else
183
184 std::ostringstream oss;
185
186 oss << "Element [ " << uiElement << " ] out of range [ " << uiMin << " - " << uiMax << " ]\nTrace: ( " << sFile << " " << location.function_name() << "() line: " << location.line() << " )" << std::ends;
187
188 throw std::out_of_range( oss.str() );
189
190 #endif
191 }
192 };
193
194
200 template <typename... Args>
201 void throwArcGen4LengthError( throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
202 {
203 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
204
205 #ifdef __cpp_lib_format
206
207 throw std::length_error( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
208 std::format( " at file: {}, func: {}, line: {}",
209 sFile,
210 tFormat.m_location.function_name(),
211 tFormat.m_location.line() ) );
212
213 #else
214
215 std::ostringstream oss;
216
217 oss << tFormat.m_format << " at file: " << sFile << ", func: "
218 << tFormat.m_location.function_name() << ", line: "
219 << tFormat.m_location.line() << std::ends;
220
221 throw std::length_error( oss.str() );
222
223 #endif
224 }
225
226
227 // +----------------------------------------------------------------------------------------------------------+
228 // | CArcBase Class |
229 // +----------------------------------------------------------------------------------------------------------+
230
236 class GEN4_CARCBASE_API CArcBase
237 {
238 public:
239
243 static const std::string version( void );
244
245
251 static void zeroMemory( void* pDest, std::size_t uiSize );
252
253
260 static void copyMemory( void* pDest, void* pSrc, std::size_t uiSize );
261
262
269 template<typename T> static std::tuple<T*,T*> copyAndIncrement( void* pDest, void* pSrc, const std::size_t uiSize )
270 {
271 T* pInserter = reinterpret_cast<T*>( pDest );
272 T* pReader = reinterpret_cast<T*>( pSrc );
273
274 if ( std::is_integral_v<T> )
275 {
276 if ( pInserter != nullptr && pReader != nullptr )
277 {
278 for ( std::remove_const_t<decltype( uiSize )> i = 0; i < uiSize; i++, pInserter++, pReader++ )
279 {
280 *pInserter = *pReader;
281 }
282 }
283
284 else
285 {
286 throwArcGen4InvalidArgument( "Source and/or destination pointer(s) cannot be NULL!"sv );
287 }
288 }
289
290 else
291 {
292 throwArcGen4InvalidArgument( "Must be integral type!"sv );
293 }
294
295 return { pInserter, pReader };
296 }
297
298
304 template<typename ErrCode>
305 //static std::enable_if_t<std::is_integral_v<ErrCode>, const std::string> getSystemErrorMessage( ErrCode iErrCode )
306 static const std::string getSystemErrorMessage( ErrCode iErrCode ) requires std::is_integral_v<ErrCode>
307 {
308 #ifdef _WINDOWS
309
310 std::ostringstream oss;
311 std::string sMsg;
312
313 LPTSTR lpBuffer;
314
315 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
316 NULL,
317 ( DWORD )iErrCode,
318 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
319 ( LPTSTR )&lpBuffer,
320 0,
321 NULL );
322
323 char szBuffer[ 1024 ] = { '\0' };
324
325 std::int32_t iBytes = WideCharToMultiByte( CP_ACP, 0, reinterpret_cast< LPWSTR >( lpBuffer ), -1, szBuffer, sizeof( szBuffer ), NULL, NULL );
326
327 if ( iBytes > 0 )
328 {
329 oss << szBuffer;
330 }
331
332 LocalFree( lpBuffer );
333
334 #else
335
336 std::ostringstream oss;
337 std::string sMsg;
338
339 if ( iErrCode != -1 )
340 {
341 oss << "( errno: " << iErrCode << " ) - " << strerror( iErrCode );
342 }
343
344 //
345 // Remove and return characters '\r' or '\n' at the end of the string.
346 //
347 sMsg = oss.str();
348
349 if ( sMsg.back() == '\n' || sMsg.back() == '\r' )
350 {
351 sMsg.erase( sMsg.end() - 1, sMsg.end() );
352 }
353
354 #endif
355
356 //
357 // Remove and return characters '\r' or '\n' at the end of the string.
358 //
359 sMsg = oss.str();
360
361 if ( sMsg.back() == '\n' || sMsg.back() == '\r' )
362 {
363 sMsg.erase( sMsg.end() - 1, sMsg.end() );
364 }
365
366 return sMsg;
367 }
368
369
374 static const std::string getSystemErrorMessage( void );
375
376
380 #ifdef _WINDOWS
381 static std::uint32_t getSystemError( void ) noexcept
382 {
383 return static_cast< std::uint32_t >( ::GetLastError() );
384 }
385 #else
386 static std::int32_t getSystemError( void ) noexcept
387 {
388 return static_cast< std::int32_t >( errno );
389 }
390 #endif
391
392
399 static pStringList_t splitString( const std::string& sString, const char& zDelim = ' ' );
400
401
422 [[ deprecated( "Will be removed in a future release. Use std::format() instead." ) ]]
423 static std::string formatString( const char* pszFmt, ... );
424
425
433 static const std::filesystem::path incrementFileName( const std::filesystem::path& tFilePath = "", const std::int32_t iStartValue = -1 );
434
435
440 static std::string convertWideToAnsi( const wchar_t wzString[] ) noexcept;
441
442
448 static std::string convertWideToAnsi( const std::wstring& wsString );
449
450
456 static std::wstring convertAnsiToWide( const char* pszString );
457
458
468 static std::string cmdToString( const std::uint32_t uiCmd );
469
470
485 template <typename T> static std::string iterToString( T* begin, T* end, const char zSeperator = ' ' )
486 {
487 std::ostringstream oss;
488
489 if ( begin == nullptr )
490 {
491 throwArcGen4Error( "Invalid \"begin\" parameter ( nullptr )."sv );
492 }
493
494 if ( end == nullptr )
495 {
496 throwArcGen4Error( "Invalid \"end\" parameter ( nullptr )."sv );
497 }
498
499 while ( begin != end )
500 {
501 oss << cmdToString( *begin++ ) << zSeperator;
502 }
503
504 return oss.str();
505 }
506
507
516 static std::string setDots( const std::string& sText, const std::size_t uiMaxLength, const char szDot = '.' );
517
518
523 static std::string trim( const std::string& sText ) noexcept;
524
525
530 static const std::chrono::time_point<std::chrono::high_resolution_clock> startCodeTime( void ) noexcept;
531
532
538 template <typename T>
539 static constexpr auto endCodeTime( const std::chrono::time_point<std::chrono::high_resolution_clock> tStartTimePoint ) noexcept
540 {
541 return std::chrono::duration_cast< T >( std::chrono::high_resolution_clock::now() - tStartTimePoint ).count();
542 }
543
544
546 virtual ~CArcBase( void );
547
548 protected:
549
551 CArcBase( void ) = default;
552
554 CArcBase( const CArcBase& ) = delete;
555
557 CArcBase( CArcBase&& ) = delete;
558
560 CArcBase& operator=( const CArcBase& ) = delete;
561
564
566 static const std::string m_sVersion;
567
568 };
569
570
571
572 } // end gen4 namespace
573} // end arc namespace
574
CArcBase(void)=default
static std::string cmdToString(const std::uint32_t uiCmd)
static std::tuple< T *, T * > copyAndIncrement(void *pDest, void *pSrc, const std::size_t uiSize)
Definition: CArcBase.h:269
static const std::string version(void)
static std::wstring convertAnsiToWide(const char *pszString)
static std::string formatString(const char *pszFmt,...)
CArcBase(const CArcBase &)=delete
CArcBase & operator=(const CArcBase &)=delete
virtual ~CArcBase(void)
static const std::filesystem::path incrementFileName(const std::filesystem::path &tFilePath="", const std::int32_t iStartValue=-1)
static std::string iterToString(T *begin, T *end, const char zSeperator=' ')
Definition: CArcBase.h:485
CArcBase(CArcBase &&)=delete
static std::uint32_t getSystemError(void) noexcept
Definition: CArcBase.h:381
CArcBase & operator=(CArcBase &&)=delete
static constexpr auto endCodeTime(const std::chrono::time_point< std::chrono::high_resolution_clock > tStartTimePoint) noexcept
Definition: CArcBase.h:539
static const std::string getSystemErrorMessage(void)
static std::string trim(const std::string &sText) noexcept
static pStringList_t splitString(const std::string &sString, const char &zDelim=' ')
static std::string setDots(const std::string &sText, const std::size_t uiMaxLength, const char szDot='.')
static std::string convertWideToAnsi(const wchar_t wzString[]) noexcept
static std::string convertWideToAnsi(const std::wstring &wsString)
static void copyMemory(void *pDest, void *pSrc, std::size_t uiSize)
static const std::chrono::time_point< std::chrono::high_resolution_clock > startCodeTime(void) noexcept
static const std::string m_sVersion
Definition: CArcBase.h:566
static const std::string getSystemErrorMessage(ErrCode iErrCode)
Definition: CArcBase.h:306
static void zeroMemory(void *pDest, std::size_t uiSize)
std::unique_ptr< arc::gen4::CArcStringList > pStringList_t
void throwArcGen4InvalidArgument(const throwFormat_t<> tFormat, Args &&... args)
Definition: CArcBase.h:138
void throwArcGen4Error(const throwFormat_t<> tFormat, Args &&... args)
Definition: CArcBase.h:106
void throwArcGen4LengthError(throwFormat_t<> tFormat, Args &&... args)
Definition: CArcBase.h:201
Definition: CArcBase.h:50
throwArcGen4OutOfRange(const std::uint32_t uiElement, const std::pair< std::uint32_t, std::uint32_t > &&tRange, const std::source_location &location=std::source_location::current())
Definition: CArcBase.h:172
throwFormat_t(const char *pszFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:72
std::source_location m_location
Definition: CArcBase.h:96
throwFormat_t(std::string_view svFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:90
std::string m_format
Definition: CArcBase.h:94
throwFormat_t(const std::string &sFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:81