Base10.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "util/Base10.h"
  16. #include "wire/Message.h"
  17. #include "exception/Except.h"
  18. #include "util/CString.h"
  19. #include <stdbool.h>
  20. Er_DEFUN(void Base10_write(struct Message* msg, int64_t num))
  21. {
  22. bool negative = num < 0;
  23. if (negative) {
  24. num = -num;
  25. } else if (num == 0) {
  26. Er(Message_epush8(msg, '0'));
  27. Er_ret();
  28. }
  29. while (num > 0) {
  30. Er(Message_epush8(msg, '0' + (num % 10)));
  31. num /= 10;
  32. }
  33. if (negative) {
  34. Er(Message_epush8(msg, '-'));
  35. }
  36. Er_ret();
  37. }
  38. Er_DEFUN(int64_t Base10_read(struct Message* msg))
  39. {
  40. int64_t out = 0;
  41. bool negative = false;
  42. uint8_t chr = Er(Message_epop8(msg));
  43. if (chr == '-') {
  44. negative = true;
  45. chr = Er(Message_epop8(msg));
  46. }
  47. if (chr >= '0' && chr <= '9') {
  48. while (chr >= '0' && chr <= '9') {
  49. out *= 10;
  50. out += chr - '0';
  51. if (Message_getLength(msg) == 0) {
  52. if (negative) { out = -out; }
  53. Er_ret(out);
  54. }
  55. chr = Er(Message_epop8(msg));
  56. }
  57. Er(Message_epush8(msg, chr));
  58. if (negative) { out = -out; }
  59. Er_ret(out);
  60. } else {
  61. Er(Message_epush8(msg, chr));
  62. Er_raise(Message_getAlloc(msg), "No base10 characters found");
  63. }
  64. }
  65. int Base10_fromString(uint8_t* str, int64_t* numOut)
  66. {
  67. int len = CString_strlen(str);
  68. if (len < 1) {
  69. return -1;
  70. } else if (str[0] == '-') {
  71. if (len < 2 || str[1] < '0' || str[1] > '9') {
  72. return -1;
  73. }
  74. } else if (str[0] < '0' || str[0] > '9') {
  75. return -1;
  76. }
  77. struct Message msg = Message_foreign(len, str);
  78. *numOut = Er_assert(Base10_read(&msg));
  79. return 0;
  80. }