constexpr 关键字优化 字符串映射与查找

68 篇文章 3 订阅
47 篇文章 1 订阅

需求:

1)执行期间将文件名的扩展映射为具体的内容信息返回;

2)可以理解为键值对查找;

解决方法:

1)普通的解决方案:使用std::map<string, string>管理并查找;

2)constexpr解决方案:直接写为switch    case 方式;

先内联2个函数,作为字符串转int的哈希:


inline constexpr unsigned int str2tag_core(const char *s, size_t l, unsigned int h) 
{
	return (l == 0) ? h : str2tag_core(s + 1, l - 1, (h * 33) ^ static_cast<unsigned char>(*s));
}

inline unsigned int str2tag(const std::string &s) 
{
	return str2tag_core(s.data(), s.size(), 0);
}

方式一:

inline const char * find_content_type1(const string &ext) 
{
	auto it = tagStrMap.find(ext);
	if (it != tagStrMap.end())
	{
		return it->second.c_str();
	}
	return nullptr;

}

inline const char * find_content_type2(const string &ext)
{
	unsigned int code;
	static std::map<unsigned int, std::string> tagMap;
	if (tagMap.size() == 0)
	{
		for (auto & it : tagStrMap)
		{
			code = str2tag(it.first);
			//printf("set code %u : %s \n", code, it.second.c_str());
			/*auto it2 = tagMap.find(code);
			if (it2 != tagMap.end())
			{
				printf("same----\n");

			}*/
			tagMap.insert(std::make_pair(code, it.second));
		}

	}

	code = str2tag(ext);
	auto item = tagMap.find(code);
	if (item != tagMap.end())
	{
		return item->second.c_str();
	}

	return nullptr;

}

方法二:编译器常量表达式执行swich case

inline constexpr unsigned int CpmCode(const char *s, size_t l)
{
	return str2tag_core(s, l, 0);
}

const char * findConent1(const char* ext)
{
	unsigned int code = str2tag(ext);
	switch (code)
	{
	case CpmCode("css", 3): return "text/css";
	case CpmCode("csv", 3): return "text/csv";
	case CpmCode("txt", 3): return "text/plain";
	case CpmCode("vtt", 3): return "text/vtt";
	case CpmCode("htm", 3):
	case CpmCode("html", 4): return "text/html";

	case CpmCode("apng", 4): return "image/apng";
	case CpmCode("avif", 4): return "image/avif";
	case CpmCode("bmp", 3): return "image/bmp";
	case CpmCode("gif", 3): return "image/gif";
	case CpmCode("png", 3): return "image/png";
	case CpmCode("svg", 3): return "image/svg+xml";
	case CpmCode("webp", 4): return "image/webp";
	case CpmCode("ico", 3): return "image/x-icon";
	case CpmCode("tif", 3): return "image/tiff";
	case CpmCode("tiff", 4): return "image/tiff";
	case CpmCode("jpg", 3):
	case CpmCode("jpeg", 4): return "image/jpeg";

	case CpmCode("mp4", 3): return "video/mp4";
	case CpmCode("mpeg", 4): return "video/mpeg";
	case CpmCode("webm", 4): return "video/webm";

	case CpmCode("mp3", 3): return "audio/mp3";
	case CpmCode("mpga", 4): return "audio/mpeg";
	case CpmCode("weba", 4): return "audio/webm";
	case CpmCode("wav", 3): return "audio/wave";

	case CpmCode("otf", 3): return "font/otf";
	case CpmCode("ttf", 3): return "font/ttf";
	case CpmCode("woff", 4): return "font/woff";
	case CpmCode("woff2", 5): return "font/woff2";

	case CpmCode("7z", 2): return "application/x-7z-compressed";
	case CpmCode("atom", 3): return "application/atom+xml";
	case CpmCode("pdf", 3): return "application/pdf";
	case CpmCode("js", 2):
	case CpmCode("mjs", 3): return "application/javascript";
	case CpmCode("json", 4): return "application/json";
	case CpmCode("rss", 3): return "application/rss+xml";
	case CpmCode("tar", 3): return "application/x-tar";
	case CpmCode("xht", 3):
	case CpmCode("xhtml", 5): return "application/xhtml+xml";
	case CpmCode("xslt", 4): return "application/xslt+xml";
	case CpmCode("xml", 3): return "application/xml";
	case CpmCode("gz", 2): return "application/gzip";
	case CpmCode("zip", 3): return "application/zip";
	case CpmCode("wasm", 4): return "application/wasm";

	default: return nullptr;
	}
}

测试代码:

double test1(const string & ext)
{
	Timer timer;
	const	char * textCss = find_content_type1("css");
	timer.start();
	for (int i=0; i<20; i++)
	{
		const char *  textZip = find_content_type1(ext.c_str());	
	}

	double delta = timer.stop_delta_us();
	return delta;
	
}

double test2(const string & ext)
{
	Timer timer;

	const	char * textCss = find_content_type2("css");

	timer.start();
	for (int i = 0; i < 20; i++)
	{
		const char *  textZip = find_content_type2(ext.c_str());
	}
	double delta = timer.stop_delta_us();
	return delta;

}

double test3(const string & ext)
{
	Timer timer;
	timer.start();
	for (int i = 0; i < 20; i++)
	{	
		const char *  textZip = findConent1(ext.c_str());	
	}
	double delta = timer.stop_delta_us();
	return delta;
}
int main(void)
{
	static std::map<std::string, std::string> tagStrMap1
	{
		  {"css", "text/css"},
		  {"csv", "text/csv"},
		  {"txt", "text/plain"},
		  {"vtt", "text/vtt"},
		  {"htm", "text/html"},
		  {"html", "text/html"},

		  {"apng", "image/apng"},
		  {"avif", "image/avif"},
		  {"bmp", "image/bmp"},
		  {"gif", "image/gif"},
		  {"png", "image/png"},
		  {"svg", "image/svg+xml"},
		  {"webp", "image/webp"},
		  {"ico", "image/x-icon"},
		  {"tif", "image/tiff"},
		  {"tiff", "image/tiff"},
		  {"jpg", "image/jpeg"},
		  {"jpeg", "image/jpeg"},

		  {"mp4", "video/mp4"},
		  {"mpeg", "video/mpeg"},
		  {"webm", "video/webm"},

		  {"mp3", "audio/mp3"},
		  {"mpga", "audio/mpeg"},
		  {"weba", "audio/webm"},
		  {"wav", "audio/wave"},

		  {"otf", "font/otf"},
		  {"ttf", "font/ttf"},
		  {"woff", "font/woff"},
		  {"woff2", "font/woff2"},

		  {"7z", "application/x-7z-compressed"},
		  {"atom", "application/atom+xml"},
		  {"pdf", "application/pdf"},
		  {"js", "application/javascript"},
		  {"mjs", "application/javascript"},
		  {"json", "application/json"},
		  {"rss", "application/rss+xml"},
		  {"tar", "application/x-tar"},
		  {"xht", "application/xhtml+xml"},
		  {"xhtml", "application/xhtml+xml"},
		  {"xslt", "application/xslt+xml"},
		  {"xml", "application/xml"},
		  {"gz", "application/gzip"},
		  {"zip", "application/zip"},
		  {"wasm", "application/wasm"}

	};

	for (auto it : tagStrMap1)
	{
		string ext = it.first;

		double t1 = test1(ext);
		double t2 = test2(ext);
		double t3 = test3(ext);

		printf("%f, %f, %f\n", t1, t2, t3);
	}

结果是:使用字符串直接放到map里还是最快的!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值