0.00% Lines (0/26) 0.00% Functions (0/2)
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/mime_db.hpp> 10   #include <boost/http/server/mime_db.hpp>
11   #include <algorithm> 11   #include <algorithm>
12   #include <cctype> 12   #include <cctype>
13   13  
14   namespace boost { 14   namespace boost {
15   namespace http { 15   namespace http {
16   namespace mime_db { 16   namespace mime_db {
17   17  
18   namespace { 18   namespace {
19   19  
20   // Static database of common MIME types 20   // Static database of common MIME types
21   // Sorted by type for binary search 21   // Sorted by type for binary search
22   constexpr mime_type_entry db[] = { 22   constexpr mime_type_entry db[] = {
23   { "application/gzip", "", false }, 23   { "application/gzip", "", false },
24   { "application/javascript", "UTF-8", true }, 24   { "application/javascript", "UTF-8", true },
25   { "application/json", "UTF-8", true }, 25   { "application/json", "UTF-8", true },
26   { "application/octet-stream", "", false }, 26   { "application/octet-stream", "", false },
27   { "application/pdf", "", false }, 27   { "application/pdf", "", false },
28   { "application/rtf", "UTF-8", true }, 28   { "application/rtf", "UTF-8", true },
29   { "application/wasm", "", false }, 29   { "application/wasm", "", false },
30   { "application/x-7z-compressed", "", false }, 30   { "application/x-7z-compressed", "", false },
31   { "application/x-bzip", "", false }, 31   { "application/x-bzip", "", false },
32   { "application/x-bzip2", "", false }, 32   { "application/x-bzip2", "", false },
33   { "application/x-tar", "", false }, 33   { "application/x-tar", "", false },
34   { "application/xhtml+xml", "UTF-8", true }, 34   { "application/xhtml+xml", "UTF-8", true },
35   { "application/xml", "UTF-8", true }, 35   { "application/xml", "UTF-8", true },
36   { "application/zip", "", false }, 36   { "application/zip", "", false },
37   { "audio/aac", "", false }, 37   { "audio/aac", "", false },
38   { "audio/flac", "", false }, 38   { "audio/flac", "", false },
39   { "audio/mp4", "", false }, 39   { "audio/mp4", "", false },
40   { "audio/mpeg", "", false }, 40   { "audio/mpeg", "", false },
41   { "audio/ogg", "", false }, 41   { "audio/ogg", "", false },
42   { "audio/wav", "", false }, 42   { "audio/wav", "", false },
43   { "audio/webm", "", false }, 43   { "audio/webm", "", false },
44   { "font/otf", "", false }, 44   { "font/otf", "", false },
45   { "font/ttf", "", false }, 45   { "font/ttf", "", false },
46   { "font/woff", "", false }, 46   { "font/woff", "", false },
47   { "font/woff2", "", false }, 47   { "font/woff2", "", false },
48   { "image/avif", "", false }, 48   { "image/avif", "", false },
49   { "image/bmp", "", false }, 49   { "image/bmp", "", false },
50   { "image/gif", "", false }, 50   { "image/gif", "", false },
51   { "image/jpeg", "", false }, 51   { "image/jpeg", "", false },
52   { "image/png", "", false }, 52   { "image/png", "", false },
53   { "image/svg+xml", "UTF-8", true }, 53   { "image/svg+xml", "UTF-8", true },
54   { "image/tiff", "", false }, 54   { "image/tiff", "", false },
55   { "image/webp", "", false }, 55   { "image/webp", "", false },
56   { "image/x-icon", "", false }, 56   { "image/x-icon", "", false },
57   { "text/cache-manifest", "UTF-8", true }, 57   { "text/cache-manifest", "UTF-8", true },
58   { "text/calendar", "UTF-8", true }, 58   { "text/calendar", "UTF-8", true },
59   { "text/css", "UTF-8", true }, 59   { "text/css", "UTF-8", true },
60   { "text/csv", "UTF-8", true }, 60   { "text/csv", "UTF-8", true },
61   { "text/html", "UTF-8", true }, 61   { "text/html", "UTF-8", true },
62   { "text/javascript", "UTF-8", true }, 62   { "text/javascript", "UTF-8", true },
63   { "text/markdown", "UTF-8", true }, 63   { "text/markdown", "UTF-8", true },
64   { "text/plain", "UTF-8", true }, 64   { "text/plain", "UTF-8", true },
65   { "text/xml", "UTF-8", true }, 65   { "text/xml", "UTF-8", true },
66   { "video/mp4", "", false }, 66   { "video/mp4", "", false },
67   { "video/mpeg", "", false }, 67   { "video/mpeg", "", false },
68   { "video/ogg", "", false }, 68   { "video/ogg", "", false },
69   { "video/webm", "", false }, 69   { "video/webm", "", false },
70   }; 70   };
71   71  
72   constexpr std::size_t db_size = sizeof( db ) / sizeof( db[0] ); 72   constexpr std::size_t db_size = sizeof( db ) / sizeof( db[0] );
73   73  
74   // Case-insensitive comparison 74   // Case-insensitive comparison
75   int 75   int
MISUBC 76   compare_icase( core::string_view a, core::string_view b ) noexcept 76   compare_icase( core::string_view a, core::string_view b ) noexcept
77   { 77   {
MISUBC 78   auto const n = ( std::min )( a.size(), b.size() ); 78   auto const n = ( std::min )( a.size(), b.size() );
MISUBC 79   for( std::size_t i = 0; i < n; ++i ) 79   for( std::size_t i = 0; i < n; ++i )
80   { 80   {
81   auto const ca = static_cast<unsigned char>( 81   auto const ca = static_cast<unsigned char>(
MISUBC 82   std::tolower( static_cast<unsigned char>( a[i] ) ) ); 82   std::tolower( static_cast<unsigned char>( a[i] ) ) );
83   auto const cb = static_cast<unsigned char>( 83   auto const cb = static_cast<unsigned char>(
MISUBC 84   std::tolower( static_cast<unsigned char>( b[i] ) ) ); 84   std::tolower( static_cast<unsigned char>( b[i] ) ) );
MISUBC 85   if( ca < cb ) 85   if( ca < cb )
MISUBC 86   return -1; 86   return -1;
MISUBC 87   if( ca > cb ) 87   if( ca > cb )
MISUBC 88   return 1; 88   return 1;
89   } 89   }
MISUBC 90   if( a.size() < b.size() ) 90   if( a.size() < b.size() )
MISUBC 91   return -1; 91   return -1;
MISUBC 92   if( a.size() > b.size() ) 92   if( a.size() > b.size() )
MISUBC 93   return 1; 93   return 1;
MISUBC 94   return 0; 94   return 0;
95   } 95   }
96   96  
97   } // (anon) 97   } // (anon)
98   98  
99   mime_type_entry const* 99   mime_type_entry const*
MISUBC 100   lookup( core::string_view type ) noexcept 100   lookup( core::string_view type ) noexcept
101   { 101   {
102   // Binary search 102   // Binary search
MISUBC 103   std::size_t lo = 0; 103   std::size_t lo = 0;
MISUBC 104   std::size_t hi = db_size; 104   std::size_t hi = db_size;
MISUBC 105   while( lo < hi ) 105   while( lo < hi )
106   { 106   {
MISUBC 107   auto const mid = lo + ( hi - lo ) / 2; 107   auto const mid = lo + ( hi - lo ) / 2;
MISUBC 108   auto const cmp = compare_icase( db[mid].type, type ); 108   auto const cmp = compare_icase( db[mid].type, type );
MISUBC 109   if( cmp < 0 ) 109   if( cmp < 0 )
MISUBC 110   lo = mid + 1; 110   lo = mid + 1;
MISUBC 111   else if( cmp > 0 ) 111   else if( cmp > 0 )
MISUBC 112   hi = mid; 112   hi = mid;
113   else 113   else
MISUBC 114   return &db[mid]; 114   return &db[mid];
115   } 115   }
MISUBC 116   return nullptr; 116   return nullptr;
117   } 117   }
118   118  
119   } // mime_db 119   } // mime_db
120   } // http 120   } // http
121   } // boost 121   } // boost