Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot 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 0 : fnv1a_hash( core::string_view data ) noexcept
21 : {
22 0 : constexpr std::uint64_t basis = 14695981039346656037ULL;
23 0 : constexpr std::uint64_t prime = 1099511628211ULL;
24 :
25 0 : std::uint64_t hash = basis;
26 0 : for( unsigned char c : data )
27 : {
28 0 : hash ^= c;
29 0 : hash *= prime;
30 : }
31 0 : return hash;
32 : }
33 :
34 : // Convert to null-terminated hex string
35 : void
36 0 : to_hex( std::uint64_t value, char* out ) noexcept
37 : {
38 0 : constexpr char hex[] = "0123456789abcdef";
39 0 : for( int i = 15; i >= 0; --i )
40 : {
41 0 : out[i] = hex[value & 0xF];
42 0 : value >>= 4;
43 : }
44 0 : out[16] = '\0';
45 0 : }
46 :
47 : } // (anon)
48 :
49 : std::string
50 0 : etag( core::string_view body, etag_options opts )
51 : {
52 0 : auto const hash = fnv1a_hash( body );
53 :
54 : char hex[17];
55 0 : to_hex( hash, hex );
56 :
57 : char buf[64];
58 : int n;
59 0 : if( opts.weak )
60 0 : n = std::snprintf( buf, sizeof(buf),
61 : "W/\"%zx-%s\"", body.size(), hex );
62 : else
63 0 : n = std::snprintf( buf, sizeof(buf),
64 : "\"%zx-%s\"", body.size(), hex );
65 :
66 0 : return std::string( buf, static_cast<std::size_t>(n) );
67 : }
68 :
69 : std::string
70 0 : etag(
71 : std::uint64_t size,
72 : std::uint64_t mtime,
73 : etag_options opts )
74 : {
75 : char buf[64];
76 : int n;
77 0 : if( opts.weak )
78 0 : 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 0 : 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 0 : return std::string( buf, static_cast<std::size_t>(n) );
89 : }
90 :
91 : } // http
92 : } // boost
|