gpib_parser_numutils.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #ifndef GPIB_PARSER_NUMUTILS_H
  2. #define GPIB_PARSER_NUMUTILS_H
  3. #include <ctype.h> // isalpha, isdigit
  4. #include <stddef.h> // ptrdiff_t
  5. #include <string.h> // NULL
  6. #include <stdint.h> // size_t
  7. #include "gpib_parser_casts.h"
  8. #include "gpib_parser_chars.h" // Service characters definitions
  9. #include "gpib_parser_validators_numbers.h"
  10. // String check mode for GPIB_StrChkFormat()
  11. typedef enum
  12. {
  13. eSCM_DEC, // Check mode: for demical number
  14. eSCM_HEX, // Check mode: for hexademical number
  15. eSCM_FLOAT, // Check mode: for float number
  16. eSCM_BIN, // Check mode: for binary number
  17. eSCM_OCT, // Check mode: for octal number
  18. eSCM_EXP, // Check mode: for exponential number
  19. eSCM_MNEMONIC, // Check mode: for mnemonic parameter
  20. eSCM_DIGIT // Check mode: for demical digits
  21. }
  22. eStringCheckMode_t;
  23. //-----------------------------------------------------------------------------
  24. // sFormatDouble2Str_t:
  25. // Compound Literal structure for GPIB_Double2Str()
  26. typedef union
  27. {
  28. uint32_t format;
  29. struct
  30. {
  31. uint32_t nLeadDigits : 8;
  32. uint32_t nFracDigits : 8;
  33. uint32_t bSciFormat : 1;
  34. uint32_t reserved :15;
  35. };
  36. }
  37. sFormatDouble2Str_t;
  38. //-----------------------------------------------------------------------------
  39. // sFormatInt2Str_t:
  40. // Compound Literal structure for GPIB_Integer2Str()
  41. typedef union
  42. {
  43. uint32_t format;
  44. struct
  45. {
  46. uint32_t nLeadDigits : 4;
  47. uint32_t reserved :28;
  48. };
  49. }
  50. sFormatInt2Str_t;
  51. #define Format_Float2Str_NdotN ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 0, .nFracDigits = 0 }).format
  52. #define Format_Float2Str_Ndot3 ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 0, .nFracDigits = 3 }).format
  53. #define Format_Float2Str_2dot3 ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 2, .nFracDigits = 3 }).format
  54. #define Format_Float2Str_Sci ((sFormatDouble2Str_t){ .bSciFormat = 1, .nLeadDigits = 0, .nFracDigits = 0 }).format
  55. #define Format_Double2Str_NdotN ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 0, .nFracDigits = 0 }).format
  56. #define Format_Double2Str_Ndot3 ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 0, .nFracDigits = 3 }).format
  57. #define Format_Double2Str_2dot3 ((sFormatDouble2Str_t){ .bSciFormat = 0, .nLeadDigits = 2, .nFracDigits = 3 }).format
  58. #define Format_Double2Str_Sci ((sFormatDouble2Str_t){ .bSciFormat = 1, .nLeadDigits = 0, .nFracDigits = 0 }).format
  59. #define Format_Int2Str_N ( (sFormatInt2Str_t) { .nLeadDigits = 0 }).format
  60. #define Format_Int2Str_10N ( (sFormatInt2Str_t) { .nLeadDigits = 10 }).format
  61. size_t GPIB_Float2Str( float value, char * strBuf, size_t strBufSize, uint32_t compound_format );
  62. size_t GPIB_Double2Str( double value, char * strBuf, size_t strBufSize, uint32_t compound_format );
  63. size_t GPIB_Integer2Str( int32_t value, char * strBuf, size_t strBufSize, uint32_t compound_format );
  64. //-----------------------------------------------------------------------------
  65. // GPIB_NUMBER_NSYSPREFIX_SIZE:
  66. // Numeric string-prefix length in bytes:
  67. // e.g. For '#HDEADBEED' the prefix '#H' specifies the hexademical numeric system.
  68. // There are three types of numeric systems: binary (#B), octal(#O) and hexademical (#H).
  69. // The prefix length for all of them is 2.
  70. #define GPIB_NUMBER_NSYSPREFIX_SIZE (2)
  71. //-----------------------------------------------------------------------------
  72. // eGPIB_ParseNumbers_type_t:
  73. // Mode of GPIB_ParseNumbers() call.
  74. // Describes the @type parameter.
  75. typedef enum
  76. {
  77. USBTMC_PARSENUMBERS_TYPE_FLOAT,
  78. USBTMC_PARSENUMBERS_TYPE_INT,
  79. }
  80. eGPIB_ParseNumbers_type_t;
  81. //-----------------------------------------------------------------------------
  82. // ChooseLowestPtr:
  83. // Checks two pointers @ptr_a and @ptr_b and prefers the lowest in absolute addresses,
  84. // The function prefers non-NULL pointers, and returns NULL only if both @ptr_a and
  85. // @ptr_b are NULL.
  86. static inline void * ChooseLowestPtr( void * ptr_a, void * ptr_b )
  87. {
  88. // First, check the @ptr_a for NULL
  89. // and prefer the other pointer, even if it's NULL too,
  90. // because there no choice is.
  91. if( NULL == ptr_a )
  92. return ptr_b;
  93. else
  94. // Then, check the @ptr_b for NULL
  95. // and prefer the other pointer, even if it's NULL too,
  96. // because there no choice is.
  97. if( NULL == ptr_b )
  98. return ptr_a;
  99. // Since @ptr_a and @ptr_b aren't NULL for sure, determine which of the
  100. // pointers is greater than the other in absolute values.
  101. ptrdiff_t diff = (ptrdiff_t)ptr_b - (ptrdiff_t)ptr_a;
  102. // @ptr_a is less
  103. if( diff > 0 )
  104. // prefer @ptr_a
  105. return ptr_a;
  106. // Otherwise, prefer @ptr_b
  107. return ptr_b;
  108. /* #define GetMin(A,B) ((TOUINT(A)>TOUINT(B))?(B):(A)) */
  109. /* #define GetMax(A,B) ((TOUINT(A)<TOUINT(B))?(B):(A)) */
  110. /* #define GetNearPointer(P1,P2) ((P1!=NULL && P2!=NULL)?GetMin(P1,P2):((P1!=NULL)?P1:P2)) */
  111. }
  112. // ChooseLowestPtrConst:
  113. // Checks two pointers @ptr_a and @ptr_b and prefers the lowest in absolute addresses,
  114. // The function prefers non-NULL pointers, and returns NULL only if both @ptr_a and
  115. // @ptr_b are NULL.
  116. static inline const void * ChooseLowestPtrConst( const void * ptr_a, const void * ptr_b )
  117. {
  118. // First, check the @ptr_a for NULL
  119. // and prefer the other pointer, even if it's NULL too,
  120. // because there no choice is.
  121. if( NULL == ptr_a )
  122. return ptr_b;
  123. else
  124. // Then, check the @ptr_b for NULL
  125. // and prefer the other pointer, even if it's NULL too,
  126. // because there no choice is.
  127. if( NULL == ptr_b )
  128. return ptr_a;
  129. // Since @ptr_a and @ptr_b aren't NULL for sure, determine which of the
  130. // pointers is greater than the other in absolute values.
  131. ptrdiff_t diff = (ptrdiff_t)ptr_b - (ptrdiff_t)ptr_a;
  132. // @ptr_a is less
  133. if( diff > 0 )
  134. // prefer @ptr_a
  135. return ptr_a;
  136. // Otherwise, prefer @ptr_b
  137. return ptr_b;
  138. /* #define GetMin(A,B) ((TOUINT(A)>TOUINT(B))?(B):(A)) */
  139. /* #define GetMax(A,B) ((TOUINT(A)<TOUINT(B))?(B):(A)) */
  140. /* #define GetNearPointer(P1,P2) ((P1!=NULL && P2!=NULL)?GetMin(P1,P2):((P1!=NULL)?P1:P2)) */
  141. }
  142. // ----------------------------------------------------------------------------
  143. // SubPointers:
  144. // Substracts the @ptr_sub from the @ptr_src pointer and returns the difference.
  145. static inline ptrdiff_t SubPointers( const void * ptr_src, const void * ptr_sub )
  146. {
  147. ptrdiff_t diff = (ptrdiff_t)ptr_src - (ptrdiff_t)ptr_sub;
  148. return diff;
  149. /* #define SubPointers(P1,P2) TOUINT((TOUINT(TOPCHAR(P1))-TOUINT(TOPCHAR(P2)))) */
  150. }
  151. // ----------------------------------------------------------------------------
  152. // DecCharToNum:
  153. // Converts a demical charater into the number
  154. static inline int DecCharToNum( const char ch )
  155. {
  156. // In case the given @ch isn't numeric character return zero
  157. return ( IsDemicalChar(ch) ? (int)ch - '0' : 0 );
  158. /* #define CharToDec(character) ((IsDEC(character))?(int)character-'0':0);*/
  159. }
  160. #define BinCharToNum(ch) (DecCharToNum(ch)) // binary system: convert the character into the demical number
  161. #define OctCharToNum(ch) (DecCharToNum(ch)) // octal system: convert the character into the demical number
  162. // ----------------------------------------------------------------------------
  163. // HexCharToNum:
  164. // Converts a hexademical charater into the number
  165. static inline int HexCharToNum( const char ch )
  166. {
  167. // In case the given @ch isn't numeric character return zero
  168. return ( IsHexademicalChar(ch) ? (int)(tolower(ch) - 'a') + 10 : 0 );
  169. /* #define CharHexToDec( character ) ( ( IsDemicalChar (character) )? ((character)-'0'): ( ( IsHexademicalChar(character))? ((character)-'A'+0x0A): 0 ) ) */
  170. }
  171. // ----------------------------------------------------------------------------
  172. // HexCharToNumber:
  173. // Converts a hex-literal character into the number
  174. static inline int HexCharToNumber( const char ch )
  175. {
  176. return ( IsDemicalChar(ch) ? DecCharToNum(ch) : HexCharToNum(ch) );
  177. /* #define CharHexToDec( character ) ( ( IsDemicalChar (character) )? ((character)-'0'): ( ( IsHexademicalChar(character))? ((character)-'A'+0x0A): 0 ) ) */
  178. }
  179. // ----------------------------------------------------------------------------
  180. // IsBinarySystem:
  181. // Parses the number's string prefix and detects if it relates to a binary numeric system
  182. // Prefix is "#B", e.g. "#B1000"
  183. static inline BOOL IsBinarySystem( const char * prefix )
  184. {
  185. return MAKE_BOOL(
  186. GPIB_CHAR_NMBSYSTEM_SIGN == prefix[0] // First character: is a numeric system prefix character
  187. && 'b' == tolower(prefix[1]) // Second character: 'b' or 'B'
  188. );
  189. /* #define IsBinSystem( string ) ( (*(string)=='#' && ( (*(string+1) & 0xDF)=='B' ))?TRUE:FALSE ) */
  190. }
  191. // ----------------------------------------------------------------------------
  192. // IsHexademicalSystem:
  193. // Parses the number's string prefix and detects if it relates to a hexademical numeric system
  194. // Prefix is "#H", e.g. "#HA41C"
  195. static inline BOOL IsHexademicalSystem( const char * prefix )
  196. {
  197. return MAKE_BOOL(
  198. GPIB_CHAR_NMBSYSTEM_SIGN == prefix[0] // First character: is a numeric system prefix character
  199. && 'h' == tolower(prefix[1]) // Second character: 'h' or 'H'
  200. );
  201. /* #define IsHexSystem( string ) ( (*(string)=='#' && ( (*(string+1) & 0xDF)=='H' ))?TRUE:FALSE ) */
  202. }
  203. // ----------------------------------------------------------------------------
  204. // IsOctalSystem:
  205. // Parses the number's string prefix and detects if it relates to an octal numeric system
  206. // Prefix is "#O" or "#Q", e.g. "#O606", "#Q606"
  207. static inline BOOL IsOctalSystem( const char * prefix )
  208. {
  209. return MAKE_BOOL(
  210. GPIB_CHAR_NMBSYSTEM_SIGN == prefix[0] // First character: is a numeric system prefix character
  211. && ( 'o' == tolower(prefix[1]) // Second character: 'o' or 'O'
  212. || 'q' == tolower(prefix[1]) // Second character: 'q' or 'Q'
  213. )
  214. );
  215. /* #define IsOctSystem( string ) ( (*(string)=='#' && ( (*(string+1) & 0xDF)=='O' ))?TRUE:FALSE ) */
  216. }
  217. // ----------------------------------------------------------------------------
  218. // IsNumericSystem:
  219. // Checks if the given @prefix relates to a numeric system: hexademical, octal or binary.
  220. static inline BOOL IsNumericSystem( const char * prefix )
  221. {
  222. return MAKE_BOOL( IsHexademicalSystem(prefix) // Check first for hexademical
  223. || IsBinarySystem(prefix) // Next check for binary
  224. || IsOctalSystem(prefix) ); // At last check for octal
  225. /* #define IsNumericSystem( string ) ( ( IsOctalSystem( string ) || IsHexademicalSystem( string ) || IsBinarySystem( string ))?TRUE:FALSE ) */
  226. }
  227. // ----------------------------------------------------------------------------
  228. // GetNumericSystemBase:
  229. // Returns a number system base if any system detected based on @prefix
  230. static inline int GetNumericSystemBase( const char * prefix )
  231. {
  232. if( IsHexademicalSystem( prefix ) )
  233. return 16;
  234. if( IsOctalSystem( prefix ) )
  235. return 8;
  236. if( IsBinarySystem( prefix ) )
  237. return 2;
  238. return 0;
  239. /*#define GetNumericSystem( string ) ( (IsNumericSystem(string))?( (IsBinarySystem( string ))?2:( (IsOctalSystem( string ))?8:( (IsHexademicalSystem( string ))?16:(0) ) ) ):0)*/
  240. }
  241. /* protos */
  242. BOOL ConvertNumerationSystem( const char * str, int nsys, uint32_t * pResult, const char * * ppEnd ); // "gpib_parser_numutils.c"
  243. int GPIB_ParseNumbers( const char * str, eGPIB_ParseNumbers_type_t type, size_t count, int * , ... ); // "gpib_parser_numutils.c"
  244. #endif