libs/http/src/server/etag.cpp

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