#include <assert.h>
#include <string.h>
#include <string>
#include <stdio.h>
using namespace std;
map<std::string, URLInfo> urllib;
/**
* 初始化:使用初始化指令让系统重新完成初始化,内部URL记录清空,时间初始化等。
* @return 初始化结果
* E000:方法未实现
* E001:初始化成功
*/
E_RESULT initSys()
{
initTimeSeconds();
urllib.clear();
if (urllib.empty() && getCurrentTimeSeconds()==0)
return E001;
else
return E000;
}
/**
* 生成短URL:根据请求中的长URL生成一个短URL。
* 要求:
* 1、需要考虑参数不合法的异常场景
* 2、生成的短URL在系统中最大有效期为2天,过期后会被清理掉。
* 3、生成的短URL不能重复(例外:相同的长URL生成的短URL要相同(过期后短URL要重新生成))
* 4、短URL的格式为:短URL服务域名(固定)/内部ID(不重复) 如:s.vmall.com/UAyJ
*
* @param longURL
* 长URL,最大长度256个字符
* @param expireTime
* 生成的短URL在系统中保留时间,超过该时间会被清理掉
* @return 处理结果
* E000:方法未实现
* E002:处理成功
* E003:参数非法
*/
char tochar(int x)
{
if (x < 26 && x >= 0)
return 'a' + x;
else if (x < 52)
return 'A' + x - 26;
else if (x < 62)
return '0' + x - 52;
else
return '_';
}
void toshort(const char* longURL, char* shortURL)
{
int len = strlen(longURL);
int i = 1,tem= longURL[0],j=0;
while (i<len)
{
if (i % 7 != 0)
tem += longURL[i];
else
{
shortURL[j] = tochar(tem%62);
j++;
tem = longURL[i];
}
i++;
}
shortURL[j++]= tochar(tem % 62);
shortURL[j] = '/0';
}
E_RESULT saveURL(const char* longURL, int expireTime, char* shortURL)
{
static int conflict = 0;
pair<map<string, URLInfo>::iterator, bool> Insert_Pair;
toshort(longURL, shortURL);
string surl = shortURL;
strcpy(shortURL, SUS_DOMAIN);
map<string, URLInfo>::iterator iter;
iter = urllib.find(surl);
if (iter != urllib.end() && strcmp(longURL, iter->second.URL) == 0)
{
iter->second.expireTime = expireTime + getCurrentTimeSeconds();
strcat(shortURL, surl.data());
return E002;
}
else if (iter != urllib.end())
surl += tochar(conflict++);
URLInfo tem;
tem.expireTime = expireTime + getCurrentTimeSeconds();
strcpy(tem.URL, longURL);
strcat(shortURL, surl.data());
Insert_Pair=urllib.insert(pair<string, URLInfo>(surl, tem));
if (Insert_Pair.second == true)
return E002;
else
return E000;
}
/**
* 重定向到长URL:根据短URL返回原始的长URL
* 要求:支持URL过期时间的判断,已经过期的长URL信息当做不存在进行处理
*
* @param shortURL
* 短URL,进行合法性检查
* @param longURL
* 查询到的原始长URL
* @return 处理结果
* E000:方法未实现
* E002:处理成功
* E003:参数非法
* E004:短URL不存在
*/
E_RESULT queryURL(const char* shortURL, char *longURL)
{
string tem;
int i = strlen(SUS_DOMAIN);
map<string, URLInfo>::iterator iter;
while (shortURL[i] != '\0')
{
if (shortURL[i] <= 'Z'&&shortURL[i] >= 'A')
;
else if (shortURL[i] <= 'z'&&shortURL[i] >= 'a')
;
else if (shortURL[i] <= '9'&&shortURL[i] >= '0')
;
else
{
longURL[0] = 0;
return E003;
}
i++;
}
tem = (shortURL+strlen(SUS_DOMAIN));
iter = urllib.find(tem);
if (iter != urllib.end())
{
if (iter->second.expireTime >= getCurrentTimeSeconds())
{
strcpy(longURL, iter->second.URL);
return E002;
}
else
{
urllib.erase(iter);
longURL[0] = 0;
return E004;
}
}
else
{
longURL[0] = 0;
return E004;
}
}
/**
* 提供给考生的测试用例样例
* 重要说明:此用例只用于验证基本功能,并未包含所有场景,考生可以在本接口中调整或者增加测试用例。
**/
void shortURLService_TestCase()
{
//1、系统初始化
E_RESULT ret = initSys();
assert(ret == E001);
//2、生成短URL
char shortURL[MAX_SHORT_URL_LEN + 1] = { 0 };
const char *longURL = "https://www.vmall.com/product/10086705348665.html";
ret = saveURL(longURL, 2 * 24 * 3600, shortURL);
assert(ret == E002); //检查返回值
assert(0 == strncmp(SUS_DOMAIN, shortURL, strlen(SUS_DOMAIN))); //检查短URL
//3、相同的长URL生成的短URL要相同
char shortURL1[MAX_SHORT_URL_LEN + 1] = { 0 };
const char *longURL1 = "https://www.vmall.com/product/10086705348665.html";
ret = saveURL(longURL1, 2 * 24 * 3600, shortURL1);
assert(ret == E002); //检查返回值
assert(0 == strcmp(shortURL1, shortURL)); //URL相等
//4、不同的长URL生成的短URL要不同
char shortURL2[MAX_SHORT_URL_LEN + 1] = { 0 };
const char *longURL2 = "https://www.vmall.com/product/10086501288078.html";
ret = saveURL(longURL2, 2 * 24 * 3600, shortURL2);
assert(ret == E002); //检查返回值
assert(0 != strcmp(shortURL1, shortURL2)); //URL不等
//5、短URL重定向
char longURL3[MAX_LONG_URL_LEN + 1] = { 0 };
ret = queryURL(shortURL, longURL3);
assert(ret == E002); //检查返回值
assert(0 == strcmp(longURL, longURL3)); //URL相等
//6、短URL过期
int elapseTime = 2 * 24 * 3600 + 1;
elapseTimeSeconds(elapseTime);
ret = queryURL(shortURL, longURL3);
assert(ret == E004); //检查返回值
assert(0 == longURL3[0]); //URL为空
}