Developer Application Interface (ARC API) v4.5.9
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 #include <windows.h>
16#else
17 #include <cstring>
18#endif
19
20#ifdef __cpp_lib_format
21 #include <format>
22#endif
23
24#include <type_traits>
25#include <filesystem>
26#include <stdexcept>
27#include <string>
28#include <sstream>
29#include <cstdint>
30#include <cstdarg>
31#include <chrono>
32#include <thread>
33#include <concepts>
34#include <string_view>
35#include <source_location>
36
37#include <CArcBaseDllMain.h>
38#include <CArcStringList.h>
39
40using namespace std::string_literals;
41using namespace std::string_view_literals;
42
43
44
45namespace arc
46{
47 namespace gen4
48 {
49
50 // +----------------------------------------------------------------------------------------------------------+
51 // | throwArcGen4xxx functions |
52 // +----------------------------------------------------------------------------------------------------------+
53 // | Convenience to auto fill filename, method name and line number |
54 // +----------------------------------------------------------------------------------------------------------+
55
60 template <typename... Args>
62 {
68 throwFormat_t( const char* pszFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( pszFormat ), m_location( tLocation )
69 {
70 }
71
77 throwFormat_t( const std::string& sFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( sFormat ), m_location( tLocation )
78 {
79 }
80
86 throwFormat_t( std::string_view svFormat, const std::source_location& tLocation = std::source_location::current() ) : m_format( svFormat ), m_location( tLocation )
87 {
88 }
89
90 std::string m_format;
92 std::source_location m_location;
93 };
94
95
101 template <typename... Args>
102 void throwArcGen4Error( const throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
103 {
104 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
105
106 #ifdef __cpp_lib_format
107
108 throw std::runtime_error( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
109 std::format( " at file: {}, func: {}, line: {}",
110 sFile,
111 tFormat.m_location.function_name(),
112 tFormat.m_location.line() ) );
113
114 #else
115
116 std::ostringstream oss;
117
118 oss << tFormat.m_format << " at file: " << sFile << ", func: "
119 << tFormat.m_location.function_name() << ", line: "
120 << tFormat.m_location.line() << std::ends;
121
122 throw std::runtime_error( oss.str() );
123
124 #endif
125 }
126
127
133 template <typename... Args>
134 void throwArcGen4InvalidArgument( const throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
135 {
136 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
137
138 #ifdef __cpp_lib_format
139
140 throw std::invalid_argument( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
141 std::format( " at file: {}, func: {}, line: {}",
142 sFile,
143 tFormat.m_location.function_name(),
144 tFormat.m_location.line() ) );
145
146 #else
147
148 std::ostringstream oss;
149
150 oss << tFormat.m_format << " at file: " << sFile << ", func: "
151 << tFormat.m_location.function_name() << ", line: "
152 << tFormat.m_location.line() << std::ends;
153
154 throw std::invalid_argument( oss.str() );
155
156 #endif
157 }
158
159
165 template <typename... Args>
167 {
168 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() )
169 {
170 auto [uiMin, uiMax] { tRange };
171
172 auto sFile = std::filesystem::path( location.file_name() ).filename().string();
173
174 #ifdef __cpp_lib_format
175
176 throw std::out_of_range( std::format( "Element [ {} ] out of range [ {} - {} ]\nTrace: ( {} {}() line: {} )"sv, uiElement, uiMin, uiMax, sFile, location.function_name(), location.line() ) );
177
178 #else
179
180 std::ostringstream oss;
181
182 oss << "Element [ " << uiElement << " ] out of range [ " << uiMin << " - " << uiMax << " ]\nTrace: ( " << sFile << " " << location.function_name() << "() line: " << location.line() << " )" << std::ends;
183
184 throw std::out_of_range( oss.str() );
185
186 #endif
187 }
188 };
189
190
196 template <typename... Args>
197 void throwArcGen4LengthError( throwFormat_t<> tFormat, [[ maybe_unused ]] Args&&... args )
198 {
199 auto sFile = std::filesystem::path( tFormat.m_location.file_name() ).filename().string();
200
201 #ifdef __cpp_lib_format
202
203 throw std::length_error( std::format( tFormat.m_format, std::forward<Args&&>( args )... ) +
204 std::format( " at file: {}, func: {}, line: {}",
205 sFile,
206 tFormat.m_location.function_name(),
207 tFormat.m_location.line() ) );
208
209 #else
210
211 std::ostringstream oss;
212
213 oss << tFormat.m_format << " at file: " << sFile << ", func: "
214 << tFormat.m_location.function_name() << ", line: "
215 << tFormat.m_location.line() << std::ends;
216
217 throw std::length_error( oss.str() );
218
219 #endif
220 }
221
222
223
224 // +----------------------------------------------------------------------------------------------------------+
225 // | CArcBase Class |
226 // +----------------------------------------------------------------------------------------------------------+
227
233 class GEN4_CARCBASE_API CArcBase
234 {
235 public:
236
240 static const std::string version( void );
241
242
248 static void zeroMemory( void* pDest, std::size_t uiSize );
249
250
257 static void copyMemory( void* pDest, void* pSrc, std::size_t uiSize );
258
259
266 template<typename T> static std::tuple<T*,T*> copyAndIncrement( void* pDest, void* pSrc, const std::size_t uiSize )
267 {
268 T* pInserter = reinterpret_cast<T*>( pDest );
269 T* pReader = reinterpret_cast<T*>( pSrc );
270
271 if ( std::is_integral_v<T> )
272 {
273 if ( pInserter != nullptr && pReader != nullptr )
274 {
275 for ( std::remove_const_t<decltype( uiSize )> i = 0; i < uiSize; i++, pInserter++, pReader++ )
276 {
277 *pInserter = *pReader;
278 }
279 }
280
281 else
282 {
283 throwArcGen4InvalidArgument( "Source and/or destination pointer(s) cannot be NULL!"sv );
284 }
285 }
286
287 else
288 {
289 throwArcGen4InvalidArgument( "Must be integral type!"sv );
290 }
291
292 return { pInserter, pReader };
293 }
294
295
301 template<typename ErrCode>
302 static const std::string getSystemErrorMessage( ErrCode iErrCode ) requires std::is_integral_v<ErrCode>
303 {
304 #ifdef _WINDOWS
305
306 std::ostringstream oss;
307 std::string sMsg;
308
309 LPTSTR lpBuffer;
310
311 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
312 NULL,
313 ( DWORD )iErrCode,
314 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
315 ( LPTSTR )&lpBuffer,
316 0,
317 NULL );
318
319 char szBuffer[ 1024 ] = { '\0' };
320
321 std::int32_t iBytes = WideCharToMultiByte( CP_ACP, 0, reinterpret_cast< LPWSTR >( lpBuffer ), -1, szBuffer, sizeof( szBuffer ), NULL, NULL );
322
323 if ( iBytes > 0 )
324 {
325 oss << szBuffer;
326 }
327
328 LocalFree( lpBuffer );
329
330 #else
331
332 std::ostringstream oss;
333 std::string sMsg;
334
335 if ( iErrCode != -1 )
336 {
337 oss << "( errno: " << iErrCode << " ) - " << strerror( iErrCode );
338 }
339
340 //
341 // Remove and return characters '\r' or '\n' at the end of the string.
342 //
343 sMsg = oss.str();
344
345 if ( sMsg.back() == '\n' || sMsg.back() == '\r' )
346 {
347 sMsg.erase( sMsg.end() - 1, sMsg.end() );
348 }
349
350 #endif
351
352 //
353 // Remove and return characters '\r' or '\n' at the end of the string.
354 //
355 sMsg = oss.str();
356
357 if ( sMsg.back() == '\n' || sMsg.back() == '\r' )
358 {
359 sMsg.erase( sMsg.end() - 1, sMsg.end() );
360 }
361
362 return sMsg;
363 }
364
365
370 static const std::string getSystemErrorMessage( void );
371
372
376 #ifdef _WINDOWS
377 static std::uint32_t getSystemError( void ) noexcept
378 {
379 return static_cast< std::uint32_t >( ::GetLastError() );
380 }
381 #else
382 static std::int32_t getSystemError( void ) noexcept
383 {
384 return static_cast< std::int32_t >( errno );
385 }
386 #endif
387
388
395 static pStringList_t splitString( const std::string& sString, const char& zDelim = ' ' );
396
397
418 [[ deprecated( "Will be removed in a future release. Use std::format() instead." ) ]]
419 static std::string formatString( const char* pszFmt, ... );
420
421
429 static const std::filesystem::path incrementFileName( const std::filesystem::path& tFilePath = "", const std::int32_t iStartValue = -1 );
430
431
438 static std::filesystem::path getFileName( const std::string& sFilter = "Gen IV Microcontroller binary file\0*.bin\0All\0*.*\0"s ) noexcept;
439
440
445 static std::string convertWideToAnsi( const wchar_t wzString[] ) noexcept;
446
447
453 static std::string convertWideToAnsi( const std::wstring& wsString );
454
455
461 static std::wstring convertAnsiToWide( const char* pszString );
462
463
473 static std::string cmdToString( const std::uint32_t uiCmd );
474
475
482 static std::string uintToString( const std::uint32_t uiValue ) noexcept;
483
484
499 template <typename T> static std::string iterToString( T* begin, T* end, const char zSeperator = ' ' )
500 {
501 std::ostringstream oss;
502
503 if ( begin == nullptr )
504 {
505 throwArcGen4Error( "Invalid \"begin\" parameter ( nullptr )."sv );
506 }
507
508 if ( end == nullptr )
509 {
510 throwArcGen4Error( "Invalid \"end\" parameter ( nullptr )."sv );
511 }
512
513 while ( begin != end )
514 {
515 oss << cmdToString( *begin++ ) << zSeperator;
516 }
517
518 return oss.str();
519 }
520
521
530 static std::unique_ptr<std::uint8_t[]> readFileBytes( const std::filesystem::path& tFilePath, std::uint32_t& uiFileLength );
531
532
541 static std::string setDots( std::string_view svText, const std::size_t uiMaxLength, const char szDot = '.' );
542
543
548 static std::string trim( const std::string& sText ) noexcept;
549
550
559 static std::size_t replaceAll( std::string& sText, std::string_view svWhat, std::string_view svWith );
560
561
568 static float uintToFloat( const std::uint32_t uiValue );
569
570
575 static const std::chrono::time_point<std::chrono::high_resolution_clock> startCodeTime( void ) noexcept;
576
577
583 template <typename T>
584 static constexpr auto endCodeTime( const std::chrono::time_point<std::chrono::high_resolution_clock> tStartTimePoint ) noexcept
585 {
586 return std::chrono::duration_cast< T >( std::chrono::high_resolution_clock::now() - tStartTimePoint ).count();
587 }
588
589
591 virtual ~CArcBase( void );
592
593 protected:
594
596 CArcBase( void ) = default;
597
599 CArcBase( const CArcBase& ) = delete;
600
602 CArcBase( CArcBase&& ) = delete;
603
605 CArcBase& operator=( const CArcBase& ) = delete;
606
609
611 static const std::string m_sVersion;
612
613 private:
614
618 struct tFloatConverter
619 {
620
621 std::uint64_t uiValue;
622 float* pfValue;
623 };
624
625 };
626
627
628
629 } // end gen4 namespace
630} // end arc namespace
631
CArcBase(void)=default
static std::string cmdToString(const std::uint32_t uiCmd)
static std::filesystem::path getFileName(const std::string &sFilter="Gen IV Microcontroller binary file\0*.bin\0All\0*.*\0"s) noexcept
static std::tuple< T *, T * > copyAndIncrement(void *pDest, void *pSrc, const std::size_t uiSize)
Definition: CArcBase.h:266
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 std::string setDots(std::string_view svText, const std::size_t uiMaxLength, const char szDot='.')
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:499
CArcBase(CArcBase &&)=delete
static std::uint32_t getSystemError(void) noexcept
Definition: CArcBase.h:377
CArcBase & operator=(CArcBase &&)=delete
static constexpr auto endCodeTime(const std::chrono::time_point< std::chrono::high_resolution_clock > tStartTimePoint) noexcept
Definition: CArcBase.h:584
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 float uintToFloat(const std::uint32_t uiValue)
static std::string uintToString(const std::uint32_t uiValue) noexcept
static std::string convertWideToAnsi(const wchar_t wzString[]) noexcept
static std::string convertWideToAnsi(const std::wstring &wsString)
static std::size_t replaceAll(std::string &sText, std::string_view svWhat, std::string_view svWith)
static void copyMemory(void *pDest, void *pSrc, std::size_t uiSize)
static std::unique_ptr< std::uint8_t[]> readFileBytes(const std::filesystem::path &tFilePath, std::uint32_t &uiFileLength)
static const std::chrono::time_point< std::chrono::high_resolution_clock > startCodeTime(void) noexcept
static const std::string m_sVersion
Definition: CArcBase.h:611
static const std::string getSystemErrorMessage(ErrCode iErrCode)
Definition: CArcBase.h:302
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:134
void throwArcGen4Error(const throwFormat_t<> tFormat, Args &&... args)
Definition: CArcBase.h:102
void throwArcGen4LengthError(throwFormat_t<> tFormat, Args &&... args)
Definition: CArcBase.h:197
Definition: CArcBase.h:46
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:168
throwFormat_t(const char *pszFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:68
std::source_location m_location
Definition: CArcBase.h:92
throwFormat_t(std::string_view svFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:86
std::string m_format
Definition: CArcBase.h:90
throwFormat_t(const std::string &sFormat, const std::source_location &tLocation=std::source_location::current())
Definition: CArcBase.h:77