summaryrefslogtreecommitdiff
path: root/src/stat_cache.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-04-14 04:03:59 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2017-04-15 03:42:28 -0400
commit0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c (patch)
tree9f10434103121230441d24121925b3dcd987878b /src/stat_cache.c
parent8e97c84c0f491247ea200d93367aa1d81e6105c1 (diff)
downloadlighttpd1.4-0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c.tar.gz
lighttpd1.4-0cc7556aec6ae6da4270e82a72d0bfce52ff1d8c.zip
[core] perf: stat_cache_mimetype_by_ext()
shared code to get mimetype string via longest extension match (attempts to match file basename, then longest ext, then "") Note: this is a behavior change from simple suffix match if there are 16 or more entries in mimetypes.assign
Diffstat (limited to 'src/stat_cache.c')
-rw-r--r--src/stat_cache.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/src/stat_cache.c b/src/stat_cache.c
index c08d2dd7..7215fdf9 100644
--- a/src/stat_cache.c
+++ b/src/stat_cache.c
@@ -268,6 +268,42 @@ static int stat_cache_attr_get(buffer *buf, char *name, char *xattrname) {
}
#endif
+const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *name, size_t nlen)
+{
+ const char *end = name + nlen; /*(end of string)*/
+ const size_t used = con->conf.mimetypes->used;
+ if (used < 16) {
+ for (size_t i = 0; i < used; ++i) {
+ /* suffix match */
+ const data_string *ds = (data_string *)con->conf.mimetypes->data[i];
+ const size_t klen = buffer_string_length(ds->key);
+ if (klen <= nlen && 0 == strncasecmp(end-klen, ds->key->ptr, klen))
+ return ds->value;
+ }
+ }
+ else {
+ const char *s;
+ const data_string *ds;
+ if (nlen) {
+ for (s = end-1; s != name && *s != '/'; --s) ; /*(like memrchr())*/
+ if (*s == '/') ++s;
+ }
+ else {
+ s = name;
+ }
+ /* search for basename, then longest .ext2.ext1, then .ext1, then "" */
+ ds = (data_string *)array_get_element(con->conf.mimetypes, s);
+ if (NULL != ds) return ds->value;
+ while (++s < end) {
+ while (*s != '.' && ++s != end) ;
+ ds = (data_string *)array_get_element(con->conf.mimetypes, s);
+ if (NULL != ds) return ds->value;
+ }
+ }
+
+ return NULL;
+}
+
/* the famous DJB hash function for strings */
static uint32_t hashme(buffer *str) {
uint32_t hash = 5381;
@@ -400,7 +436,6 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
stat_cache_entry *sce = NULL;
stat_cache *sc;
struct stat st;
- size_t k;
int fd;
struct stat lst;
#ifdef DEBUG_STAT_CACHE
@@ -635,22 +670,9 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
#endif
/* xattr did not set a content-type. ask the config */
if (buffer_string_is_empty(sce->content_type)) {
- size_t namelen = buffer_string_length(name);
-
- for (k = 0; k < con->conf.mimetypes->used; k++) {
- data_string *ds = (data_string *)con->conf.mimetypes->data[k];
- buffer *type = ds->key;
- size_t typelen = buffer_string_length(type);
-
- if (buffer_is_empty(type)) continue;
-
- /* check if the right side is the same */
- if (typelen > namelen) continue;
-
- if (0 == strncasecmp(name->ptr + namelen - typelen, type->ptr, typelen)) {
- buffer_copy_buffer(sce->content_type, ds->value);
- break;
- }
+ const buffer *type = stat_cache_mimetype_by_ext(con, CONST_BUF_LEN(name));
+ if (NULL != type) {
+ buffer_copy_buffer(sce->content_type, type);
}
}
etag_create(sce->etag, &(sce->st), con->etag_flags);