argcheck.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*****************************************************************************
  2. *
  3. * argcheck - macros for argument value checking
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. *
  23. ****************************************************************************/
  24. #ifndef CCAN_ARGCHECK_H
  25. #define CCAN_ARGCHECK_H
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdarg.h>
  29. #include <ccan/likely/likely.h>
  30. #include <ccan/compiler/compiler.h>
  31. /**
  32. * ARGCHECK_DISABLE_LOGGING - define to disable any logging done by
  33. * argcheck. This does not disable the actual checks, merely the invocation
  34. * of the argcheck_log function, be it custom or the default logging
  35. * function.
  36. */
  37. #ifdef ARGCHECK_DISABLE_LOGGING
  38. #undef argcheck_log
  39. #define argcheck_log(...) /* __VA_ARGS__ */
  40. #else
  41. #ifndef argcheck_log
  42. /**
  43. * argcheck_log - logging function for failed argcheck tests
  44. *
  45. * Override this function to hook up your own logging function. The function
  46. * will be called once for each failed test.
  47. */
  48. #define argcheck_log argcheck_log_
  49. #endif /* argcheck_log */
  50. static inline void COLD PRINTF_FMT(4, 5)
  51. argcheck_log_(const char *file, int line, const char *func,
  52. const char *msg, ...)
  53. {
  54. va_list args;
  55. va_start(args, msg);
  56. fprintf(stderr, "argcheck: %s:%d %s\nargcheck: ", file, line, func);
  57. vfprintf(stderr, msg, args);
  58. va_end(args);
  59. }
  60. #endif
  61. /**
  62. * argcheck_int_eq - check the argument is equal to the value.
  63. */
  64. #define argcheck_int_eq(arg, val) \
  65. argcheck_int_eq_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  66. /**
  67. * argcheck_int_ne - check the argument is not equal to the value
  68. */
  69. #define argcheck_int_ne(arg, val) \
  70. argcheck_int_ne_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  71. /**
  72. * argcheck_int_ge - check the argument is equal or greater than the value
  73. */
  74. #define argcheck_int_ge(arg, val) \
  75. argcheck_int_ge_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  76. /**
  77. * argcheck_int_gt - check the argument is greater than the value
  78. */
  79. #define argcheck_int_gt(arg, val) \
  80. argcheck_int_gt_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  81. /**
  82. * argcheck_int_le - check the argument is equal or less than the value
  83. */
  84. #define argcheck_int_le(arg, val) \
  85. argcheck_int_le_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  86. /**
  87. * argcheck_int_lt - check the argument is less than the value
  88. */
  89. #define argcheck_int_lt(arg, val) \
  90. argcheck_int_lt_(arg, val, #arg, #val, __FILE__, __LINE__, __func__)
  91. /**
  92. * argcheck_int_range - check the argument is within a range (inclusive)
  93. */
  94. #define argcheck_int_range(arg, min, max) \
  95. argcheck_int_range_(arg, min, max, #arg, #min, #max, __FILE__, __LINE__, __func__)
  96. /**
  97. * argcheck_flag_set - check if a flag is set
  98. */
  99. #define argcheck_flag_set(arg, flag) \
  100. argcheck_flag_set_(arg, flag, #arg, #flag, __FILE__, __LINE__, __func__)
  101. /**
  102. * argcheck_flag_unset - check if a flag is not set
  103. */
  104. #define argcheck_flag_unset(arg, flag) \
  105. argcheck_flag_unset_(arg, flag, #arg, #flag, __FILE__, __LINE__, __func__)
  106. /**
  107. * argcheck_ptr_not_null - check that a pointer is not NULL
  108. */
  109. #define argcheck_ptr_not_null(arg) \
  110. argcheck_ptr_not_null_(arg, #arg, __FILE__, __LINE__, __func__)
  111. /**
  112. * argcheck_ptr_null - check that a pointer is NULL
  113. */
  114. #define argcheck_ptr_null(arg) \
  115. argcheck_ptr_null_(arg, #arg, __FILE__, __LINE__, __func__)
  116. /**
  117. * argcheck_str_null - see argcheck_ptr_null
  118. */
  119. #define argcheck_str_null(arg) \
  120. argcheck_str_null_(arg, #arg, __FILE__, __LINE__, __func__)
  121. /**
  122. * argcheck_str_not_null - see argcheck_ptr_not_null
  123. */
  124. #define argcheck_str_not_null(arg) \
  125. argcheck_str_not_null_(arg, #arg, __FILE__, __LINE__, __func__)
  126. /**
  127. * argcheck_str_zero - check that a string is not NULL and of zero length
  128. */
  129. #define argcheck_str_zero_len(arg) \
  130. argcheck_str_zero_len_(arg, #arg, __FILE__, __LINE__, __func__)
  131. /**
  132. * argcheck_str_null_or_zero - check that a string is either NULL or of zero length
  133. */
  134. #define argcheck_str_null_or_zero_len(arg) \
  135. argcheck_str_null_or_zero_len_(arg, #arg, __FILE__, __LINE__, __func__)
  136. /**
  137. * argcheck_str_not_zero - check that a string is not NULL and has a length greater than 0
  138. */
  139. #define argcheck_str_not_zero_len(arg) \
  140. argcheck_str_not_zero_len_(arg, #arg, __FILE__, __LINE__, __func__)
  141. /**
  142. * argcheck_str_null_or_not_zero - check that a string is either NULL or has a length greater than 0
  143. */
  144. #define argcheck_str_null_or_not_zero_len(arg) \
  145. argcheck_str_null_or_not_zero_len_(arg, #arg, __FILE__, __LINE__, __func__)
  146. /**
  147. * argcheck_str_min_len - check that a string is not NULL and has a length greater than or equal to a minimum
  148. */
  149. #define argcheck_str_min_len(arg, min) \
  150. argcheck_str_min_len_(arg, #arg, min, #min, __FILE__, __LINE__, __func__)
  151. /**
  152. * argcheck_str_max_len - check that a string is not NULL and has a length less than or equal to a maximum
  153. */
  154. #define argcheck_str_max_len(arg, max) \
  155. argcheck_str_max_len_(arg, #arg, max, #max, __FILE__, __LINE__, __func__)
  156. /**
  157. * argcheck_str_null_or_min_len - check that a string is NULL or has a length greater than or equal to a minimum
  158. */
  159. #define argcheck_str_null_or_min_len(arg, min) \
  160. argcheck_str_null_or_min_len_(arg, #arg, min, #min, __FILE__, __LINE__, __func__)
  161. /**
  162. * argcheck_str_null_or_max_len - check that a string is NULL or has a length less than or equal to a maximum
  163. */
  164. #define argcheck_str_null_or_max_len(arg, max) \
  165. argcheck_str_null_or_max_len_(arg, #arg, max, #max, __FILE__, __LINE__, __func__)
  166. /*
  167. below is the actual implemenation. do not use it directly, use the macros
  168. above instead
  169. */
  170. static inline int argcheck_int_eq_(int a, int b, const char *astr, const char *bstr,
  171. const char *file, int line, const char *func)
  172. {
  173. if (likely(a == b))
  174. return 1;
  175. argcheck_log(file, line, func,
  176. "condition \"(%s == %s)\" (%d == %d) failed\n", astr, bstr, a, b);
  177. return 0;
  178. }
  179. static inline int argcheck_int_ne_(int a, int b, const char *astr, const char *bstr,
  180. const char *file, int line, const char *func)
  181. {
  182. if (likely(a != b))
  183. return 1;
  184. argcheck_log(file, line, func,
  185. "condition \"(%s != %s)\" (%d != %d) failed\n", astr, bstr, a, b);
  186. return 0;
  187. }
  188. static inline int argcheck_int_ge_(int a, int b, const char *astr, const char *bstr,
  189. const char *file, int line, const char *func)
  190. {
  191. if (likely(a >= b))
  192. return 1;
  193. argcheck_log(file, line, func,
  194. "condition \"(%s >= %s)\" (%d >= %d) failed\n", astr, bstr, a, b);
  195. return 0;
  196. }
  197. static inline int argcheck_int_gt_(int a, int b, const char *astr, const char *bstr,
  198. const char *file, int line, const char *func)
  199. {
  200. if (likely(a > b))
  201. return 1;
  202. argcheck_log(file, line, func,
  203. "condition \"(%s > %s)\" (%d > %d) failed\n", astr, bstr, a, b);
  204. return 0;
  205. }
  206. static inline int argcheck_int_le_(int a, int b, const char *astr, const char *bstr,
  207. const char *file, int line, const char *func)
  208. {
  209. if (likely(a <= b))
  210. return 1;
  211. argcheck_log(file, line, func,
  212. "condition \"(%s <= %s)\" (%d <= %d) failed\n", astr, bstr, a, b);
  213. return 0;
  214. }
  215. static inline int argcheck_int_lt_(int a, int b, const char *astr, const char *bstr,
  216. const char *file, int line, const char *func)
  217. {
  218. if (likely(a < b))
  219. return 1;
  220. argcheck_log(file, line, func,
  221. "condition \"(%s < %s)\" (%d < %d) failed\n", astr, bstr, a, b);
  222. return 0;
  223. }
  224. static inline int argcheck_int_range_(int v, int min, int max,
  225. const char *vstr,
  226. const char *minstr, const char *maxstr,
  227. const char *file, int line, const char *func)
  228. {
  229. if (!argcheck_int_le_(min, max, minstr, maxstr, file, line, func))
  230. return 0;
  231. if (likely(v >= min && v <= max))
  232. return 1;
  233. argcheck_log(file, line, func,
  234. "condition \"(%s <= %s <= %s)\" (%d <= %d <= %d) failed\n",
  235. minstr, vstr, maxstr, min, v, max);
  236. return 0;
  237. }
  238. static inline int argcheck_flag_set_(int arg, int flag,
  239. const char *argstr, const char *flagstr,
  240. const char *file, int line, const char *func)
  241. {
  242. if (!argcheck_int_ne_(flag, 0, flagstr, "0", file, line, func))
  243. return 0;
  244. if (likely(arg & flag))
  245. return 1;
  246. argcheck_log(file, line, func,
  247. "flag \"%s\" (%d) is not set on \"%s\" (%d)\"\n",
  248. flagstr, flag, argstr, arg);
  249. return 0;
  250. }
  251. static inline int argcheck_flag_unset_(int arg, int flag,
  252. const char *argstr, const char *flagstr,
  253. const char *file, int line, const char *func)
  254. {
  255. if (!argcheck_int_ne_(flag, 0, flagstr, "0", file, line, func))
  256. return 0;
  257. if (likely((arg & flag) == 0))
  258. return 1;
  259. argcheck_log(file, line, func,
  260. "flag \"%s\" (%d) must not be set on \"%s\" (%d)\"\n",
  261. flagstr, flag, argstr, arg);
  262. return 0;
  263. }
  264. static inline int argcheck_ptr_not_null_(const void *arg, const char *argstr,
  265. const char *file, int line, const char *func)
  266. {
  267. if (likely(arg != NULL))
  268. return 1;
  269. argcheck_log(file, line, func,
  270. "\"%s\" must not be NULL\n", argstr);
  271. return 0;
  272. }
  273. static inline int argcheck_ptr_null_(const void *arg, const char *argstr,
  274. const char *file, int line, const char *func)
  275. {
  276. if (likely(arg == NULL))
  277. return 1;
  278. argcheck_log(file, line, func,
  279. "\"%s\" must be NULL\n", argstr);
  280. return 0;
  281. }
  282. static inline int argcheck_str_null_(const char *arg, const char *argstr,
  283. const char *file, int line, const char *func)
  284. {
  285. return argcheck_ptr_null_(arg, argstr, file, line, func);
  286. }
  287. static inline int argcheck_str_not_null_(const char *arg, const char *argstr,
  288. const char *file, int line, const char *func)
  289. {
  290. return argcheck_ptr_not_null_(arg, argstr, file, line, func);
  291. }
  292. static inline int argcheck_str_zero_len_(const char *arg, const char *argstr,
  293. const char *file, int line, const char *func)
  294. {
  295. if (!argcheck_str_not_null_(arg, argstr, file, line, func))
  296. return 0;
  297. if (likely(*arg == '\0'))
  298. return 1;
  299. argcheck_log(file, line, func,
  300. "\"%s\" must be a zero-length string\n", argstr);
  301. return 0;
  302. }
  303. static inline int argcheck_str_null_or_zero_len_(const char *arg, const char *argstr,
  304. const char *file, int line, const char *func)
  305. {
  306. if (likely(arg == NULL || *arg == '\0'))
  307. return 1;
  308. argcheck_log(file, line, func,
  309. "\"%s\" must be NULL or a zero-length string\n", argstr);
  310. return 0;
  311. }
  312. static inline int argcheck_str_not_zero_len_(const char *arg, const char *argstr,
  313. const char *file, int line, const char *func)
  314. {
  315. if (!argcheck_str_not_null_(arg, argstr, file, line, func))
  316. return 0;
  317. if (likely(*arg != '\0'))
  318. return 1;
  319. argcheck_log(file, line, func,
  320. "\"%s\" must not be a zero-length string\n", argstr);
  321. return 0;
  322. }
  323. static inline int argcheck_str_null_or_not_zero_len_(const char *arg, const char *argstr,
  324. const char *file, int line, const char *func)
  325. {
  326. if (likely(arg == NULL || *arg != '\0'))
  327. return 1;
  328. argcheck_log(file, line, func,
  329. "\"%s\" must be NULL or not a zero-length string\n", argstr);
  330. return 0;
  331. }
  332. static inline int argcheck_str_min_len_(const char *arg, const char *argstr,
  333. int min, const char *minstr,
  334. const char *file, int line, const char *func)
  335. {
  336. int len;
  337. if (!argcheck_str_not_null_(arg, argstr, file, line, func))
  338. return 0;
  339. len = strlen(arg);
  340. if (likely(len >= min))
  341. return 1;
  342. argcheck_log(file, line, func,
  343. "\"%s\" must be at least \"%s\" (%d) long, is '%s' (length %d)\n", argstr,
  344. minstr, min, arg, len);
  345. return 0;
  346. }
  347. static inline int argcheck_str_max_len_(const char *arg, const char *argstr,
  348. int max, const char *maxstr,
  349. const char *file, int line, const char *func)
  350. {
  351. int len;
  352. if (!argcheck_str_not_null_(arg, argstr, file, line, func))
  353. return 0;
  354. len = strlen(arg);
  355. if (likely(len <= max))
  356. return 1;
  357. argcheck_log(file, line, func,
  358. "\"%s\" must be at most \"%s\" (%d) long, is '%s' (length %d)\n", argstr,
  359. maxstr, max, arg, len);
  360. return 0;
  361. }
  362. static inline int argcheck_str_null_or_min_len_(const char *arg, const char *argstr,
  363. int min, const char *minstr,
  364. const char *file, int line, const char *func)
  365. {
  366. int len;
  367. if (likely(arg == NULL))
  368. return 1;
  369. len = strlen(arg);
  370. if (likely(len >= min))
  371. return 1;
  372. argcheck_log(file, line, func,
  373. "\"%s\" must be NULL or at least \"%s\" (%d) long, is '%s' (length %d)\n", argstr,
  374. minstr, min, arg, len);
  375. return 0;
  376. }
  377. static inline int argcheck_str_null_or_max_len_(const char *arg, const char *argstr,
  378. int max, const char *maxstr,
  379. const char *file, int line, const char *func)
  380. {
  381. int len;
  382. if (likely(arg == NULL))
  383. return 1;
  384. len = strlen(arg);
  385. if (likely(len <= max))
  386. return 1;
  387. argcheck_log(file, line, func,
  388. "\"%s\" must be NULL or at most \"%s\" (%d) long, is '%s' (length %d)\n", argstr,
  389. maxstr, max, arg, len);
  390. return 0;
  391. }
  392. #endif /* CCAN_ARGCHECK_H */