Commit 60ec94a7c35ff3f7153c99deff29afef91500622
1 parent
173b944e
Add QUtil::is_long_long
Showing
5 changed files
with
52 additions
and
0 deletions
ChangeLog
| 1 | +2022-05-15 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Add QUtil::is_long_long to test whether a string can be | ||
| 4 | + converted to a long long and back without loss of information. | ||
| 5 | + | ||
| 1 | 2022-05-04 Jay Berkenbilt <ejb@ql.org> | 6 | 2022-05-04 Jay Berkenbilt <ejb@ql.org> |
| 2 | 7 | ||
| 3 | * JSON: add a new "blob" type that takes a function to write data | 8 | * JSON: add a new "blob" type that takes a function to write data |
include/qpdf/QUtil.hh
| @@ -65,6 +65,13 @@ namespace QUtil | @@ -65,6 +65,13 @@ namespace QUtil | ||
| 65 | QPDF_DLL | 65 | QPDF_DLL |
| 66 | unsigned int string_to_uint(char const* str); | 66 | unsigned int string_to_uint(char const* str); |
| 67 | 67 | ||
| 68 | + // Returns true if this exactly represents a long long. The | ||
| 69 | + // determination is made by converting the string to a long long, | ||
| 70 | + // then converting the result back to a string, and then comparing | ||
| 71 | + // that result with the original string. | ||
| 72 | + QPDF_DLL | ||
| 73 | + bool is_long_long(char const* str); | ||
| 74 | + | ||
| 68 | // Pipeline's write method wants unsigned char*, but we often have | 75 | // Pipeline's write method wants unsigned char*, but we often have |
| 69 | // some other type of string. These methods do combinations of | 76 | // some other type of string. These methods do combinations of |
| 70 | // const_cast and reinterpret_cast to give us an unsigned char*. | 77 | // const_cast and reinterpret_cast to give us an unsigned char*. |
libqpdf/QUtil.cc
| @@ -467,6 +467,19 @@ QUtil::string_to_uint(char const* str) | @@ -467,6 +467,19 @@ QUtil::string_to_uint(char const* str) | ||
| 467 | return QIntC::to_uint(string_to_ull(str)); | 467 | return QIntC::to_uint(string_to_ull(str)); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | +bool | ||
| 471 | +QUtil::is_long_long(char const* str) | ||
| 472 | +{ | ||
| 473 | + try { | ||
| 474 | + auto i1 = string_to_ll(str); | ||
| 475 | + std::string s1 = int_to_string(i1); | ||
| 476 | + return str == s1; | ||
| 477 | + } catch (std::exception&) { | ||
| 478 | + // overflow or other error | ||
| 479 | + } | ||
| 480 | + return false; | ||
| 481 | +} | ||
| 482 | + | ||
| 470 | unsigned char* | 483 | unsigned char* |
| 471 | QUtil::unsigned_char_pointer(std::string const& str) | 484 | QUtil::unsigned_char_pointer(std::string const& str) |
| 472 | { | 485 | { |
libtests/qtest/qutil/qutil.out
libtests/qutil.cc
| @@ -676,6 +676,29 @@ timestamp_test() | @@ -676,6 +676,29 @@ timestamp_test() | ||
| 676 | QUtil::qpdf_time_to_pdf_time(QUtil::get_current_qpdf_time()))); | 676 | QUtil::qpdf_time_to_pdf_time(QUtil::get_current_qpdf_time()))); |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | +void | ||
| 680 | +is_long_long_test() | ||
| 681 | +{ | ||
| 682 | + auto check = [](char const* s, bool v) { | ||
| 683 | + if (QUtil::is_long_long(s) != v) { | ||
| 684 | + std::cout << "failed: " << s << std::endl; | ||
| 685 | + } | ||
| 686 | + }; | ||
| 687 | + check("12312312", true); | ||
| 688 | + check("12312312.34", false); | ||
| 689 | + check("-12312312", true); | ||
| 690 | + check("-12312312.34", false); | ||
| 691 | + check("1e2", false); | ||
| 692 | + check("9223372036854775807", true); | ||
| 693 | + check("9223372036854775808", false); | ||
| 694 | + check("-9223372036854775808", true); | ||
| 695 | + check("-9223372036854775809", false); | ||
| 696 | + check("123123123123123123123123123123123123", false); | ||
| 697 | + check("potato", false); | ||
| 698 | + check("0123", false); | ||
| 699 | + std::cout << "done" << std::endl; | ||
| 700 | +} | ||
| 701 | + | ||
| 679 | int | 702 | int |
| 680 | main(int argc, char* argv[]) | 703 | main(int argc, char* argv[]) |
| 681 | { | 704 | { |
| @@ -710,6 +733,8 @@ main(int argc, char* argv[]) | @@ -710,6 +733,8 @@ main(int argc, char* argv[]) | ||
| 710 | rename_delete_test(); | 733 | rename_delete_test(); |
| 711 | std::cout << "---- timestamp" << std::endl; | 734 | std::cout << "---- timestamp" << std::endl; |
| 712 | timestamp_test(); | 735 | timestamp_test(); |
| 736 | + std::cout << "---- is_long_long" << std::endl; | ||
| 737 | + is_long_long_test(); | ||
| 713 | } catch (std::exception& e) { | 738 | } catch (std::exception& e) { |
| 714 | std::cout << "unexpected exception: " << e.what() << std::endl; | 739 | std::cout << "unexpected exception: " << e.what() << std::endl; |
| 715 | } | 740 | } |