77.78% Lines (21/27) 75.00% Functions (3/4)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #include <boost/http/server/etag.hpp> 10   #include <boost/http/server/etag.hpp>
11   #include <cstdio> 11   #include <cstdio>
12   12  
13   namespace boost { 13   namespace boost {
14   namespace http { 14   namespace http {
15   15  
16   namespace { 16   namespace {
17   17  
18   // Simple FNV-1a hash for content 18   // Simple FNV-1a hash for content
19   std::uint64_t 19   std::uint64_t
HITCBC 20   1 fnv1a_hash( core::string_view data ) noexcept 20   1 fnv1a_hash( core::string_view data ) noexcept
21   { 21   {
HITCBC 22   1 constexpr std::uint64_t basis = 14695981039346656037ULL; 22   1 constexpr std::uint64_t basis = 14695981039346656037ULL;
HITCBC 23   1 constexpr std::uint64_t prime = 1099511628211ULL; 23   1 constexpr std::uint64_t prime = 1099511628211ULL;
24   24  
HITCBC 25   1 std::uint64_t hash = basis; 25   1 std::uint64_t hash = basis;
HITCBC 26   3 for( unsigned char c : data ) 26   3 for( unsigned char c : data )
27   { 27   {
HITCBC 28   2 hash ^= c; 28   2 hash ^= c;
HITCBC 29   2 hash *= prime; 29   2 hash *= prime;
30   } 30   }
HITCBC 31   1 return hash; 31   1 return hash;
32   } 32   }
33   33  
34   // Convert to null-terminated hex string 34   // Convert to null-terminated hex string
35   void 35   void
HITCBC 36   1 to_hex( std::uint64_t value, char* out ) noexcept 36   1 to_hex( std::uint64_t value, char* out ) noexcept
37   { 37   {
HITCBC 38   1 constexpr char hex[] = "0123456789abcdef"; 38   1 constexpr char hex[] = "0123456789abcdef";
HITCBC 39   17 for( int i = 15; i >= 0; --i ) 39   17 for( int i = 15; i >= 0; --i )
40   { 40   {
HITCBC 41   16 out[i] = hex[value & 0xF]; 41   16 out[i] = hex[value & 0xF];
HITCBC 42   16 value >>= 4; 42   16 value >>= 4;
43   } 43   }
HITCBC 44   1 out[16] = '\0'; 44   1 out[16] = '\0';
HITCBC 45   1 } 45   1 }
46   46  
47   } // (anon) 47   } // (anon)
48   48  
49   std::string 49   std::string
HITCBC 50   1 etag( core::string_view body, etag_options opts ) 50   1 etag( core::string_view body, etag_options opts )
51   { 51   {
HITCBC 52   1 auto const hash = fnv1a_hash( body ); 52   1 auto const hash = fnv1a_hash( body );
53   53  
54   char hex[17]; 54   char hex[17];
HITCBC 55   1 to_hex( hash, hex ); 55   1 to_hex( hash, hex );
56   56  
57   char buf[64]; 57   char buf[64];
58   int n; 58   int n;
HITCBC 59   1 if( opts.weak ) 59   1 if( opts.weak )
MISUBC 60   n = std::snprintf( buf, sizeof(buf), 60   n = std::snprintf( buf, sizeof(buf),
61   "W/\"%zx-%s\"", body.size(), hex ); 61   "W/\"%zx-%s\"", body.size(), hex );
62   else 62   else
HITCBC 63   1 n = std::snprintf( buf, sizeof(buf), 63   1 n = std::snprintf( buf, sizeof(buf),
64   "\"%zx-%s\"", body.size(), hex ); 64   "\"%zx-%s\"", body.size(), hex );
65   65  
HITCBC 66   2 return std::string( buf, static_cast<std::size_t>(n) ); 66   2 return std::string( buf, static_cast<std::size_t>(n) );
67   } 67   }
68   68  
69   std::string 69   std::string
MISUBC 70   etag( 70   etag(
71   std::uint64_t size, 71   std::uint64_t size,
72   std::uint64_t mtime, 72   std::uint64_t mtime,
73   etag_options opts ) 73   etag_options opts )
74   { 74   {
75   char buf[64]; 75   char buf[64];
76   int n; 76   int n;
MISUBC 77   if( opts.weak ) 77   if( opts.weak )
MISUBC 78   n = std::snprintf( buf, sizeof(buf), 78   n = std::snprintf( buf, sizeof(buf),
79   "W/\"%llx-%llx\"", 79   "W/\"%llx-%llx\"",
80   static_cast<unsigned long long>( size ), 80   static_cast<unsigned long long>( size ),
81   static_cast<unsigned long long>( mtime ) ); 81   static_cast<unsigned long long>( mtime ) );
82   else 82   else
MISUBC 83   n = std::snprintf( buf, sizeof(buf), 83   n = std::snprintf( buf, sizeof(buf),
84   "\"%llx-%llx\"", 84   "\"%llx-%llx\"",
85   static_cast<unsigned long long>( size ), 85   static_cast<unsigned long long>( size ),
86   static_cast<unsigned long long>( mtime ) ); 86   static_cast<unsigned long long>( mtime ) );
87   87  
MISUBC 88   return std::string( buf, static_cast<std::size_t>(n) ); 88   return std::string( buf, static_cast<std::size_t>(n) );
89   } 89   }
90   90  
91   } // http 91   } // http
92   } // boost 92   } // boost