@@ -29,33 +29,33 @@ constexpr int kMaxUuidNumberOfHexDigits = 32;
2929// Helper function to parse a single hexadecimal block of a UUID.
3030// A hexadecimal block is a 16-digit hexadecimal number, which is represented
3131// as 8 bytes.
32- StatusOr<uint64_t > ParseHexBlock (absl::string_view& str,
33- absl::string_view original_str) {
32+ StatusOr<std:: uint64_t > ParseHexBlock (absl::string_view& str,
33+ absl::string_view original_str) {
3434 constexpr int kMaxUuidBlockLength = 16 ;
3535 static auto const * char_to_hex = new absl::flat_hash_map<char , std::uint8_t >(
3636 {{' 0' , 0x00 }, {' 1' , 0x01 }, {' 2' , 0x02 }, {' 3' , 0x03 }, {' 4' , 0x04 },
3737 {' 5' , 0x05 }, {' 6' , 0x06 }, {' 7' , 0x07 }, {' 8' , 0x08 }, {' 9' , 0x09 },
3838 {' a' , 0x0a }, {' b' , 0x0b }, {' c' , 0x0c }, {' d' , 0x0d }, {' e' , 0x0e },
3939 {' f' , 0x0f }, {' A' , 0x0a }, {' B' , 0x0b }, {' C' , 0x0c }, {' D' , 0x0d },
4040 {' E' , 0x0e }, {' F' , 0x0f }});
41- uint64_t block = 0 ;
41+ std:: uint64_t block = 0 ;
4242 for (int j = 0 ; j < kMaxUuidBlockLength ; ++j) {
4343 absl::ConsumePrefix (&str, " -" );
4444 if (str.empty ()) {
4545 return internal::InvalidArgumentError (
46- absl::StrFormat (" UUID must be at least %d characters long : %s" ,
46+ absl::StrFormat (" UUID must contain %d hexadecimal digits : %s" ,
4747 kMaxUuidNumberOfHexDigits , original_str),
4848 GCP_ERROR_INFO ());
4949 }
50- if (str[0 ] == ' -' ) {
51- return internal::InvalidArgumentError (
52- absl::StrFormat (" UUID cannot contain consecutive hyphens: %s" ,
53- original_str),
54- GCP_ERROR_INFO ());
55- }
56-
5750 auto it = char_to_hex->find (str[0 ]);
5851 if (it == char_to_hex->end ()) {
52+ if (str[0 ] == ' -' ) {
53+ return internal::InvalidArgumentError (
54+ absl::StrFormat (" UUID cannot contain consecutive hyphens: %s" ,
55+ original_str),
56+ GCP_ERROR_INFO ());
57+ }
58+
5959 return internal::InvalidArgumentError (
6060 absl::StrFormat (" UUID contains invalid character (%c): %s" , str[0 ],
6161 original_str),
@@ -83,55 +83,54 @@ bool operator<(Uuid const& lhs, Uuid const& rhs) {
8383
8484Uuid::operator std::string () const {
8585 constexpr int kUuidStringLen = 36 ;
86- constexpr int kHyphenPos [] = {8 , 13 , 18 , 23 };
86+ constexpr int kChunkLength [] = {8 , 4 , 4 , 4 , 12 };
8787 auto to_hex = [](std::uint64_t v, int start_index, int end_index, char * out) {
8888 static constexpr char kHexChar [] = {' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' ,
8989 ' 8' , ' 9' , ' a' , ' b' , ' c' , ' d' , ' e' , ' f' };
9090 for (int i = start_index; i >= end_index; --i) {
9191 *out++ = kHexChar [(v >> (i * 4 )) & 0xf ];
9292 }
93+ return start_index - end_index + 1 ;
9394 };
9495
9596 std::string output;
9697 output.resize (kUuidStringLen );
9798 char * target = &((output)[output.size () - kUuidStringLen ]);
98- auto high_bits = Uint128High64 (uuid_);
99- auto low_bits = Uint128Low64 (uuid_);
100- to_hex (high_bits, 15 , 8 , target);
101- *(target + kHyphenPos [0 ]) = ' -' ;
102- to_hex (high_bits, 7 , 4 , target + kHyphenPos [0 ] + 1 );
103- *(target + kHyphenPos [1 ]) = ' -' ;
104- to_hex (high_bits, 3 , 0 , target + kHyphenPos [1 ] + 1 );
105- *(target + kHyphenPos [2 ]) = ' -' ;
106- to_hex (low_bits, 15 , 12 , target + kHyphenPos [2 ] + 1 );
107- *(target + kHyphenPos [3 ]) = ' -' ;
108- to_hex (low_bits, 11 , 0 , target + kHyphenPos [3 ] + 1 );
109-
99+ char * const last = &((output)[output.size ()]);
100+ auto bits = Uint128High64 (uuid_);
101+ int start = 16 ;
102+ for (auto length : kChunkLength ) {
103+ int end = start - length;
104+ target += to_hex (bits, start - 1 , end, target);
105+ // Only hyphens write to valid addresses.
106+ if (target < last) *(target++) = ' -' ;
107+ if (end == 0 ) {
108+ start = 16 ;
109+ bits = Uint128Low64 (uuid_);
110+ } else {
111+ start = end;
112+ }
113+ }
110114 return output;
111115}
112116
113117StatusOr<Uuid> MakeUuid (absl::string_view str) {
114- // Early checks for invalid length or leading hyphen
115- if (str.size () < kMaxUuidNumberOfHexDigits ) {
118+ if (str.empty ()) {
116119 return internal::InvalidArgumentError (
117- absl::StrFormat (" UUID must be at least %d characters long: %s" ,
118- kMaxUuidNumberOfHexDigits , str),
119- GCP_ERROR_INFO ());
120+ absl::StrFormat (" UUID cannot be empty" ), GCP_ERROR_INFO ());
120121 }
122+
121123 std::string original_str = std::string (str);
122124 // Check and remove optional braces
123- bool has_braces = (str[0 ] == ' {' );
124- if (has_braces) {
125- if (str[str.size () - 1 ] != ' }' ) {
125+ if (absl::ConsumePrefix (&str, " {" )) {
126+ if (!absl::ConsumeSuffix (&str, " }" )) {
126127 return internal::InvalidArgumentError (
127128 absl::StrFormat (" UUID missing closing '}': %s" , original_str),
128129 GCP_ERROR_INFO ());
129130 }
130- str.remove_prefix (1 );
131- str.remove_suffix (1 );
132131 }
133132
134- // Check for leading hyphen after braces.
133+ // Check for leading hyphen after stripping any surrounding braces.
135134 if (str[0 ] == ' -' ) {
136135 return internal::InvalidArgumentError (
137136 absl::StrFormat (" UUID cannot begin with '-': %s" , original_str),
0 commit comments