&& (*p != ''#'') &&
(*p != ''&'')) s += *p++;
Params = s;
}
//寻找查询
//接受以''&''打头的查询
if (*p == ''?'' || *p == ''&'')
{
s = *p; //保存前导查询字符
p++;
while (*p && (*p != ''#'')) s += *p++;
Query = s;
}
//寻找片断(fragment)
if (*p == ''#'')
{
p++;
s.resize(0);
while (*p) s += *p++;
Fragment = s;
}
}
如果使用流程的话,代码就会像下面这个样子:
class Url
{
string scheme, host, port, user, pass, uri, param, ankor;
string* head_token;
int last_pos, cur_pos;
char* url;
parse_url(char* param)
{
START_FLOW analyze_url();
url = param;
int len = strlen(url);
last_pos = 0;
cur_pos = 0;
head_token = NULL;
while (cur_pos < len) {
cur_pos++;
}
if (head_token)
*head_token = url + last_pos;
}
void analyze_url()
{
START_FLOW
{
read_to_tail(&scheme, "://");
START_FLOW
read_from_head(&host, "/");
START_FLOW
read_from_head(&port, ":");
START_FLOW
{
string tmp;
read_from_head(&tmp, "@");
user = host;
pass = port;
host.erase();
port.erase();
read_from_head(&port, ":");
host = tmp;
}
}
START_FLOW
{
read_from_head(&uri, "/"));
START_FLOW
read_from_head(¶m, "?");
START_FLOW
read_from_head(&anchor, "#");
}
}
void read_to_tail(string* token, char* end_str)
{
head_token = token;
while (TRUE)
{
WAIT (cur_pos=);
if (memcmp(url + cur_pos, end_str, strlen(end_str)) == 0)
break;
}
head_token->assign(url + last_pos, cur_pos - last_pos);
last_pos = cur_pos = cur_pos + strlen(end_str);
head_token = NULL;
}
void read_from_head(string* token, char* start_str)
{
while (TRUE)
{
WAIT (cur_pos=);
if (memcmp(url + cur_pos, end_str, strlen(end_str)) == 0)
break;
}
if (head_token)
head_token->assign(url + last_pos, cur_pos - last_pos);
head_token = token;
last_pos = cur_pos + 1;
}
};
代码短多了,也易于修改,面对更复杂的格式也更具可伸缩性。
使用线程来实现
不幸的是,没有任何编译器可以支持这两个原语,如果想使用它们,只能通过一个线程来实现,虽然会带来一些系统开销, 但是值得。为取代这两个原语,可以使用以下七个宏:
·VFLOW_EVENT_DECLARE(evt):声明一个事件变量。虚拟流程可使用事件来等待或发信号。
·VFLOW_EVENT_INITIALIZE(evt):初始化一个事件变量。这个宏可在C++中并入上一个宏。
·VFLOW_WAIT(evt):一个虚拟流程能调用它来等待一个事件。
·VFLOW_SIGNAL(evt):给一个事件发信号。所有等待事件的虚拟流程将会一个接一个地被激活。当被激活后,将继续之前的流程直至再碰到一个VFLOW_WAIT,此时它又被挂起,而在队列中等待的下一个虚拟流程将会被激活。调用VFLOW_SIGNAL的流程在所有等待的流程全部执行完毕后,才会继续执行。
·VFLOW_TERMINATE(evt):当它被调用时,所有等待事件的虚拟流程会立即退出。
·VFLOW_START(routine, param):要启动一个虚拟流程,需要调用routine(param)。当它遇到第一个VFLOW_WAIT时,它会将执行控制交回它的父流程。
·VFLOW_EXIT:用于虚拟流程的中途退出。
下面是修改后的代码,且在Windows与Linux下都能运行:
//analyze [scheme://[user:pass@]host[:port]]/]uri[?param[#ankor]]
#include "vflow.h"
#include
|