Commit 60ec94a7c35ff3f7153c99deff29afef91500622

Authored by Jay Berkenbilt
1 parent 173b944e

Add QUtil::is_long_long

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 6 2022-05-04 Jay Berkenbilt <ejb@ql.org>
2 7  
3 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 65 QPDF_DLL
66 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 75 // Pipeline's write method wants unsigned char*, but we often have
69 76 // some other type of string. These methods do combinations of
70 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 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 483 unsigned char*
471 484 QUtil::unsigned_char_pointer(std::string const& str)
472 485 {
... ...
libtests/qtest/qutil/qutil.out
... ... @@ -129,3 +129,5 @@ delete file
129 129 D:20210209144925-05'00'
130 130 D:20210210011925+05'30'
131 131 D:20210209191925Z
  132 +---- is_long_long
  133 +done
... ...
libtests/qutil.cc
... ... @@ -676,6 +676,29 @@ timestamp_test()
676 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 702 int
680 703 main(int argc, char* argv[])
681 704 {
... ... @@ -710,6 +733,8 @@ main(int argc, char* argv[])
710 733 rename_delete_test();
711 734 std::cout << "---- timestamp" << std::endl;
712 735 timestamp_test();
  736 + std::cout << "---- is_long_long" << std::endl;
  737 + is_long_long_test();
713 738 } catch (std::exception& e) {
714 739 std::cout << "unexpected exception: " << e.what() << std::endl;
715 740 }
... ...