mirror of https://github.com/BOINC/boinc.git
- remote job submission: show 20 batches, with link to show all
- XML parser: make low-level functions inline, in an attempt (unsuccessful, as far as I can tell) to boost performance
This commit is contained in:
parent
444cc65722
commit
6391a8c401
|
@ -6640,3 +6640,18 @@ Rom 5 Nov 2012
|
|||
|
||||
samples\vboxwrapper\
|
||||
vboxwrapper.cpp
|
||||
|
||||
David 7 Nov 2012
|
||||
- remote job submission: show 20 batches, with link to show all
|
||||
- XML parser: make low-level functions inline, in an attempt
|
||||
(unsuccessful, as far as I can tell) to boost performance
|
||||
|
||||
html/user/
|
||||
submit.php
|
||||
lib/
|
||||
cc_config.h
|
||||
parse.cpp,h
|
||||
proxy_info.h
|
||||
sched/
|
||||
sched_main.cpp
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ function show_participant() {
|
|||
function show_totals() {
|
||||
$fn = "boinc_state.xml";
|
||||
if (!file_exists($fn) || filemtime($fn) < time()-86400) {
|
||||
$x = file_get_contents("http://boincstats.com/en/xml/boincState");
|
||||
$uid = time();
|
||||
$x = file_get_contents("http://boincstats.com/en/xml/boincState?uid=$uid");
|
||||
if ($x) {
|
||||
$f = fopen($fn, "w");
|
||||
fwrite($f, $x);
|
||||
|
|
|
@ -27,34 +27,43 @@ error_reporting(E_ALL);
|
|||
ini_set('display_errors', true);
|
||||
ini_set('display_startup_errors', true);
|
||||
|
||||
// show a set of batches
|
||||
//
|
||||
function show_batches($batches) {
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state < BATCH_STATE_COMPLETE || $batch->fraction_done < 1) {
|
||||
$wus = BoincWorkunit::enum("batch = $batch->id");
|
||||
$batch = get_batch_params($batch, $wus);
|
||||
}
|
||||
$app = BoincApp::lookup_id($batch->app_id);
|
||||
if ($app) {
|
||||
$batch->app_name = $app->name;
|
||||
} else {
|
||||
$batch->app_name = "unknown";
|
||||
}
|
||||
$user = BoincUser::lookup_id($batch->user_id);
|
||||
if ($user) {
|
||||
$batch->user_name = $user->name;
|
||||
} else {
|
||||
$batch->user_name = "missing user $batch->user_id";
|
||||
}
|
||||
}
|
||||
define("PAGE_SIZE", 20);
|
||||
|
||||
function state_count($batches, $state) {
|
||||
$n = 0;
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state == $state) $n++;
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
function show_all_link($batches, $state, $limit, $user, $app) {
|
||||
$n = state_count($batches, $state);
|
||||
if ($n > $limit) {
|
||||
if ($user) $userid = $user->id;
|
||||
else $userid = 0;
|
||||
if ($app) $appid = $app->id;
|
||||
else $appid = 0;
|
||||
|
||||
echo "Showing the most recent $limit of $n batches.
|
||||
<a href=submit.php?action=show_all&state=$state&userid=$userid&appid=$appid>Show all $n</a>
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
function show_in_progress($batches, $limit, $user, $app) {
|
||||
$first = true;
|
||||
$n = 0;
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state != BATCH_STATE_IN_PROGRESS) continue;
|
||||
if ($limit && $n == $limit) break;
|
||||
$n++;
|
||||
if ($first) {
|
||||
$first = false;
|
||||
echo "<h2>Batches in progress</h2>\n";
|
||||
if ($limit) {
|
||||
show_all_link($batches, BATCH_STATE_IN_PROGRESS, $limit, $user, $app);
|
||||
}
|
||||
start_table();
|
||||
table_header("name", "ID", "user", "app", "# jobs", "progress", "submitted");
|
||||
}
|
||||
|
@ -74,13 +83,21 @@ function show_batches($batches) {
|
|||
} else {
|
||||
end_table();
|
||||
}
|
||||
}
|
||||
|
||||
function show_complete($batches, $limit, $user, $app) {
|
||||
$first = true;
|
||||
$n = 0;
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state != BATCH_STATE_COMPLETE) continue;
|
||||
if ($limit && $n == $limit) break;
|
||||
$n++;
|
||||
if ($first) {
|
||||
$first = false;
|
||||
echo "<h2>Completed batches</h2>\n";
|
||||
if ($limit) {
|
||||
show_all_link($batches, BATCH_STATE_COMPLETE, $limit, $user, $app);
|
||||
}
|
||||
start_table();
|
||||
table_header("name", "ID", "user", "app", "# jobs", "fraction done", "submitted");
|
||||
}
|
||||
|
@ -100,13 +117,21 @@ function show_batches($batches) {
|
|||
} else {
|
||||
end_table();
|
||||
}
|
||||
}
|
||||
|
||||
function show_aborted($batches, $limit, $user, $app) {
|
||||
$first = true;
|
||||
$n = 0;
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state != BATCH_STATE_ABORTED) continue;
|
||||
if ($limit && $n == $limit) break;
|
||||
$n++;
|
||||
if ($first) {
|
||||
$first = false;
|
||||
echo "<h2>Aborted batches</h2>\n";
|
||||
if ($limit) {
|
||||
show_all_link($batches, BATCH_STATE_ABORTED, $limit, $user, $app);
|
||||
}
|
||||
start_table();
|
||||
table_header("name", "ID", "user", "app", "# jobs", "submitted");
|
||||
}
|
||||
|
@ -124,6 +149,38 @@ function show_batches($batches) {
|
|||
}
|
||||
}
|
||||
|
||||
// fill in the app and user names
|
||||
//
|
||||
function fill_in_app_and_user_names(&$batches) {
|
||||
foreach ($batches as $batch) {
|
||||
if ($batch->state < BATCH_STATE_COMPLETE || $batch->fraction_done < 1) {
|
||||
$wus = BoincWorkunit::enum("batch = $batch->id");
|
||||
$batch = get_batch_params($batch, $wus);
|
||||
}
|
||||
$app = BoincApp::lookup_id($batch->app_id);
|
||||
if ($app) {
|
||||
$batch->app_name = $app->name;
|
||||
} else {
|
||||
$batch->app_name = "unknown";
|
||||
}
|
||||
$user = BoincUser::lookup_id($batch->user_id);
|
||||
if ($user) {
|
||||
$batch->user_name = $user->name;
|
||||
} else {
|
||||
$batch->user_name = "missing user $batch->user_id";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show a set of batches
|
||||
//
|
||||
function show_batches($batches, $limit, $user, $app) {
|
||||
fill_in_app_and_user_names($batches);
|
||||
show_in_progress($batches, $limit, $user, $app);
|
||||
show_complete($batches, $limit, $user, $app);
|
||||
show_aborted($batches, $limit, $user, $app);
|
||||
}
|
||||
|
||||
// the job submission "home page":
|
||||
// show the user's in-progress and completed batches,
|
||||
// and a button for creating a new batch
|
||||
|
@ -165,13 +222,12 @@ function handle_main($user) {
|
|||
echo "</ul>";
|
||||
|
||||
$batches = BoincBatch::enum("user_id = $user->id order by id desc");
|
||||
show_batches($batches);
|
||||
show_batches($batches, PAGE_SIZE, $user, null);
|
||||
|
||||
page_tail();
|
||||
}
|
||||
|
||||
function handle_admin($user) {
|
||||
$app_id = get_int("app_id");
|
||||
function check_admin_access($user, $app_id) {
|
||||
$user_submit = BoincUserSubmit::lookup_userid($user->id);
|
||||
if (!$user_submit) error_page("no access");
|
||||
if ($app_id) {
|
||||
|
@ -179,16 +235,24 @@ function handle_admin($user) {
|
|||
$usa = BoincUserSubmitApp::lookup("user_id = $user->id and app_id=$app_id");
|
||||
if (!$usa) error_page("no access");
|
||||
}
|
||||
} else {
|
||||
if (!$user_submit->manage_all) error_page("no access");
|
||||
}
|
||||
}
|
||||
|
||||
function handle_admin($user) {
|
||||
$app_id = get_int("app_id");
|
||||
check_admin_access($user, $app_id);
|
||||
if ($app_id) {
|
||||
$app = BoincApp::lookup_id($app_id);
|
||||
if (!$app) error_page("no such app");
|
||||
page_head("Administer $app->user_friendly_name");
|
||||
$batches = BoincBatch::enum("app_id = $app_id order by id desc");
|
||||
show_batches($batches);
|
||||
show_batches($batches, PAGE_SIZE, null, $app);
|
||||
} else {
|
||||
if (!$user_submit->manage_all) error_page("no access");
|
||||
page_head("Administer all apps");
|
||||
$batches = BoincBatch::enum("true order by id desc");
|
||||
show_batches($batches);
|
||||
show_batches($batches, PAGE_SIZE, null, null);
|
||||
}
|
||||
page_tail();
|
||||
}
|
||||
|
@ -412,6 +476,51 @@ function handle_retire_batch($user) {
|
|||
page_tail();
|
||||
}
|
||||
|
||||
function show_batches_in_state($batches, $state) {
|
||||
switch ($state) {
|
||||
case BATCH_STATE_IN_PROGRESS:
|
||||
page_head("Batches in progress");
|
||||
show_in_progress($batches, 0, null, null);
|
||||
break;
|
||||
case BATCH_STATE_COMPLETE:
|
||||
page_head("Completed batches");
|
||||
show_complete($batches, 0, null, null);
|
||||
break;
|
||||
case BATCH_STATE_ABORTED:
|
||||
page_head("Aborted batches");
|
||||
show_aborted($batches, 0, null, null);
|
||||
break;
|
||||
}
|
||||
page_tail();
|
||||
}
|
||||
|
||||
function handle_show_all($user) {
|
||||
$userid = get_int("userid");
|
||||
$appid = get_int("appid");
|
||||
$state = get_int("state");
|
||||
if ($userid) {
|
||||
// user looking at their own batches
|
||||
//
|
||||
if ($userid != $user->id) error_page("wrong user");
|
||||
$batches = BoincBatch::enum("user_id = $user->id and state=$state order by id desc");
|
||||
fill_in_app_and_user_names($batches);
|
||||
show_batches_in_state($batches, $state);
|
||||
} else {
|
||||
// admin looking at batches
|
||||
//
|
||||
check_admin_access($user, $appid);
|
||||
if ($appid) {
|
||||
$app = BoincApp::lookup_id($app_id);
|
||||
if (!$app) error_page("no such app");
|
||||
$batches = BoincBatch::enum("app_id = $app_id and state=$state order by id desc");
|
||||
} else {
|
||||
$batches = BoincBatch::enum("state=$state order by id desc");
|
||||
}
|
||||
fill_in_app_and_user_names($batches);
|
||||
show_batches_in_state($batches, $state);
|
||||
}
|
||||
}
|
||||
|
||||
$user = get_logged_in_user();
|
||||
|
||||
$action = get_str('action', true);
|
||||
|
@ -425,6 +534,7 @@ case 'query_batch': handle_query_batch($user); break;
|
|||
case 'query_job': handle_query_job($user); break;
|
||||
case 'retire_batch': handle_retire_batch($user); break;
|
||||
case 'retire_batch_confirm': handle_retire_batch_confirm(); break;
|
||||
case 'show_all': handle_show_all($user); break;
|
||||
default:
|
||||
error_page('no such action');
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "proxy_info.h"
|
||||
#include "coproc.h"
|
||||
|
||||
class XML_PARSER;
|
||||
struct XML_PARSER;
|
||||
|
||||
#define MAX_FILE_XFERS_PER_PROJECT 2
|
||||
#define MAX_FILE_XFERS 8
|
||||
|
|
201
lib/parse.cpp
201
lib/parse.cpp
|
@ -483,28 +483,6 @@ XML_PARSER::XML_PARSER(MIOFILE* _f) {
|
|||
f = _f;
|
||||
}
|
||||
|
||||
// read until find non-whitespace char.
|
||||
// Return the char in the reference param
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
bool XML_PARSER::scan_nonws(int& first_char) {
|
||||
char c;
|
||||
while (1) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return true;
|
||||
unsigned char uc = c;
|
||||
if (isspace(uc)) continue;
|
||||
first_char = c;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define XML_PARSE_COMMENT 1
|
||||
#define XML_PARSE_EOF 2
|
||||
#define XML_PARSE_CDATA 3
|
||||
#define XML_PARSE_TAG 4
|
||||
#define XML_PARSE_DATA 5
|
||||
|
||||
int XML_PARSER::scan_comment() {
|
||||
char buf[256];
|
||||
char* p = buf;
|
||||
|
@ -544,132 +522,6 @@ int XML_PARSER::scan_cdata(char* buf, int len) {
|
|||
}
|
||||
}
|
||||
|
||||
// we just read a <; read until we find a >.
|
||||
// Given <tag [attr=val attr=val] [/]>:
|
||||
// - copy tag (or tag/) to buf
|
||||
// - copy "attr=val attr=val" to attr_buf
|
||||
//
|
||||
// Return either
|
||||
// XML_PARSE_TAG
|
||||
// XML_PARSE_COMMENT
|
||||
// XML_PARSE_EOF
|
||||
// XML_PARSE_CDATA
|
||||
//
|
||||
int XML_PARSER::scan_tag(
|
||||
char* buf, int _tag_len, char* attr_buf, int attr_len
|
||||
) {
|
||||
int c;
|
||||
char* buf_start = buf;
|
||||
bool found_space = false;
|
||||
int tag_len = _tag_len;
|
||||
|
||||
for (int i=0; ; i++) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return XML_PARSE_EOF;
|
||||
if (c == '>') {
|
||||
*buf = 0;
|
||||
if (attr_buf) *attr_buf = 0;
|
||||
return XML_PARSE_TAG;
|
||||
}
|
||||
if (isspace(c)) {
|
||||
if (found_space && attr_buf) {
|
||||
if (--attr_len > 0) {
|
||||
*attr_buf++ = c;
|
||||
}
|
||||
}
|
||||
found_space = true;
|
||||
} else if (c == '/') {
|
||||
if (--tag_len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
} else {
|
||||
if (found_space) {
|
||||
if (attr_buf) {
|
||||
if (--attr_len > 0) {
|
||||
*attr_buf++ = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (--tag_len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for comment start
|
||||
//
|
||||
if (i==2 && !strncmp(buf_start, "!--", 3)) {
|
||||
return scan_comment();
|
||||
}
|
||||
if (i==7 && !strncmp(buf_start, "![CDATA[", 8)) {
|
||||
return scan_cdata(buf_start, tag_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read and copy text to buf; stop when find a <;
|
||||
// ungetc() that so we read it again
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
bool XML_PARSER::copy_until_tag(char* buf, int len) {
|
||||
int c;
|
||||
while (1) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return true;
|
||||
if (c == '<') {
|
||||
f->_ungetc(c);
|
||||
*buf = 0;
|
||||
return false;
|
||||
}
|
||||
if (--len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan something, either tag or text.
|
||||
// Strip whitespace at start and end.
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
int XML_PARSER::get_aux(char* buf, int len, char* attr_buf, int attr_len) {
|
||||
bool eof;
|
||||
int c, retval;
|
||||
|
||||
while (1) {
|
||||
eof = scan_nonws(c);
|
||||
if (eof) return XML_PARSE_EOF;
|
||||
if (c == '<') {
|
||||
retval = scan_tag(buf, len, attr_buf, attr_len);
|
||||
if (retval == XML_PARSE_EOF) return retval;
|
||||
if (retval == XML_PARSE_COMMENT) continue;
|
||||
} else {
|
||||
buf[0] = c;
|
||||
eof = copy_until_tag(buf+1, len-1);
|
||||
if (eof) return XML_PARSE_EOF;
|
||||
retval = XML_PARSE_DATA;
|
||||
}
|
||||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
bool XML_PARSER::get(
|
||||
char* buf, int len, bool& _is_tag, char* attr_buf, int attr_len
|
||||
) {
|
||||
switch (get_aux(buf, len, attr_buf, attr_len)) {
|
||||
case XML_PARSE_EOF: return true;
|
||||
case XML_PARSE_TAG:
|
||||
_is_tag = true;
|
||||
break;
|
||||
case XML_PARSE_DATA:
|
||||
case XML_PARSE_CDATA:
|
||||
default:
|
||||
_is_tag = false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define MAX_XML_STRING 262144
|
||||
|
||||
// We just parsed "parsed_tag".
|
||||
|
@ -932,59 +784,6 @@ bool XML_PARSER::parse_start(const char* start_tag) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// copy everything up to (but not including) the given end tag.
|
||||
// The copied text may include XML tags.
|
||||
// strips whitespace.
|
||||
//
|
||||
int XML_PARSER::element_contents(const char* end_tag, char* buf, int buflen) {
|
||||
int n=0;
|
||||
int retval=0;
|
||||
while (1) {
|
||||
if (n == buflen-1) {
|
||||
retval = ERR_XML_PARSE;
|
||||
break;
|
||||
}
|
||||
int c = f->_getc();
|
||||
if (c == EOF) {
|
||||
retval = ERR_XML_PARSE;
|
||||
break;
|
||||
}
|
||||
buf[n++] = c;
|
||||
buf[n] = 0;
|
||||
char* p = strstr(buf, end_tag);
|
||||
if (p) {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[n] = 0;
|
||||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int XML_PARSER::element_contents(const char* end_tag, string& buf) {
|
||||
int retval=0;
|
||||
while (1) {
|
||||
int c = f->_getc();
|
||||
if (c == EOF) {
|
||||
retval = ERR_XML_PARSE;
|
||||
break;
|
||||
}
|
||||
buf += c;
|
||||
char* p = strstr(buf.c_str(), end_tag);
|
||||
if (p) {
|
||||
int k = strlen(end_tag);
|
||||
int n = buf.length();
|
||||
buf.erase(n-k, k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
// We got an unexpected tag.
|
||||
// If it's an end tag, do nothing.
|
||||
// Otherwise skip until the end tag, if any
|
||||
|
|
192
lib/parse.h
192
lib/parse.h
|
@ -24,17 +24,20 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "miofile.h"
|
||||
#include "error_numbers.h"
|
||||
#include "str_util.h"
|
||||
|
||||
// see parse_test.cpp for example usage of XML_PARSER
|
||||
|
||||
class XML_PARSER {
|
||||
bool scan_nonws(int&);
|
||||
#define XML_PARSE_COMMENT 1
|
||||
#define XML_PARSE_EOF 2
|
||||
#define XML_PARSE_CDATA 3
|
||||
#define XML_PARSE_TAG 4
|
||||
#define XML_PARSE_DATA 5
|
||||
|
||||
struct XML_PARSER {
|
||||
int scan_comment();
|
||||
int scan_tag(char*, int, char* ab=0, int al=0);
|
||||
int scan_cdata(char*, int);
|
||||
bool copy_until_tag(char*, int);
|
||||
public:
|
||||
char parsed_tag[4096];
|
||||
bool is_tag;
|
||||
MIOFILE* f;
|
||||
|
@ -42,14 +45,187 @@ public:
|
|||
void init(MIOFILE* mf) {
|
||||
f = mf;
|
||||
}
|
||||
bool get(char*, int, bool&, char* ab=0, int al=0);
|
||||
// read and copy text to buf; stop when find a <;
|
||||
// ungetc() that so we read it again
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
inline bool copy_until_tag(char* buf, int len) {
|
||||
int c;
|
||||
while (1) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return true;
|
||||
if (c == '<') {
|
||||
f->_ungetc(c);
|
||||
*buf = 0;
|
||||
return false;
|
||||
}
|
||||
if (--len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool get(
|
||||
char* buf, int len, bool& _is_tag, char* attr_buf=0, int attr_len=0
|
||||
) {
|
||||
switch (get_aux(buf, len, attr_buf, attr_len)) {
|
||||
case XML_PARSE_EOF: return true;
|
||||
case XML_PARSE_TAG:
|
||||
_is_tag = true;
|
||||
break;
|
||||
case XML_PARSE_DATA:
|
||||
case XML_PARSE_CDATA:
|
||||
default:
|
||||
_is_tag = false;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool get_tag(char* ab=0, int al=0) {
|
||||
return get(parsed_tag, sizeof(parsed_tag), is_tag, ab, al);
|
||||
}
|
||||
inline bool match_tag(const char* tag) {
|
||||
return !strcmp(parsed_tag, tag);
|
||||
}
|
||||
int get_aux(char* buf, int len, char* attr_buf, int attr_len);
|
||||
|
||||
// read until find non-whitespace char.
|
||||
// Return the char in the reference param
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
inline bool scan_nonws(int& first_char) {
|
||||
char c;
|
||||
while (1) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return true;
|
||||
unsigned char uc = c;
|
||||
if (isspace(uc)) continue;
|
||||
first_char = c;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan something, either tag or text.
|
||||
// Strip whitespace at start and end.
|
||||
// Return true iff reached EOF
|
||||
//
|
||||
inline int get_aux(
|
||||
char* buf, int len, char* attr_buf, int attr_len
|
||||
) {
|
||||
bool eof;
|
||||
int c, retval;
|
||||
|
||||
while (1) {
|
||||
eof = scan_nonws(c);
|
||||
if (eof) return XML_PARSE_EOF;
|
||||
if (c == '<') {
|
||||
retval = scan_tag(buf, len, attr_buf, attr_len);
|
||||
if (retval == XML_PARSE_EOF) return retval;
|
||||
if (retval == XML_PARSE_COMMENT) continue;
|
||||
} else {
|
||||
buf[0] = c;
|
||||
eof = copy_until_tag(buf+1, len-1);
|
||||
if (eof) return XML_PARSE_EOF;
|
||||
retval = XML_PARSE_DATA;
|
||||
}
|
||||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
// we just read a <; read until we find a >.
|
||||
// Given <tag [attr=val attr=val] [/]>:
|
||||
// - copy tag (or tag/) to buf
|
||||
// - copy "attr=val attr=val" to attr_buf
|
||||
//
|
||||
// Return either
|
||||
// XML_PARSE_TAG
|
||||
// XML_PARSE_COMMENT
|
||||
// XML_PARSE_EOF
|
||||
// XML_PARSE_CDATA
|
||||
//
|
||||
inline int scan_tag(
|
||||
char* buf, int _tag_len, char* attr_buf=0, int attr_len=0
|
||||
) {
|
||||
int c;
|
||||
char* buf_start = buf;
|
||||
bool found_space = false;
|
||||
int tag_len = _tag_len;
|
||||
|
||||
for (int i=0; ; i++) {
|
||||
c = f->_getc();
|
||||
if (c == EOF) return XML_PARSE_EOF;
|
||||
if (c == '>') {
|
||||
*buf = 0;
|
||||
if (attr_buf) *attr_buf = 0;
|
||||
return XML_PARSE_TAG;
|
||||
}
|
||||
if (isspace(c)) {
|
||||
if (found_space && attr_buf) {
|
||||
if (--attr_len > 0) {
|
||||
*attr_buf++ = c;
|
||||
}
|
||||
}
|
||||
found_space = true;
|
||||
} else if (c == '/') {
|
||||
if (--tag_len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
} else {
|
||||
if (found_space) {
|
||||
if (attr_buf) {
|
||||
if (--attr_len > 0) {
|
||||
*attr_buf++ = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (--tag_len > 0) {
|
||||
*buf++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for comment start
|
||||
//
|
||||
if (i==2 && !strncmp(buf_start, "!--", 3)) {
|
||||
return scan_comment();
|
||||
}
|
||||
if (i==7 && !strncmp(buf_start, "![CDATA[", 8)) {
|
||||
return scan_cdata(buf_start, tag_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy everything up to (but not including) the given end tag.
|
||||
// The copied text may include XML tags.
|
||||
// strips whitespace.
|
||||
//
|
||||
inline int element_contents(const char* end_tag, char* buf, int buflen) {
|
||||
int n=0;
|
||||
int retval=0;
|
||||
while (1) {
|
||||
if (n == buflen-1) {
|
||||
retval = ERR_XML_PARSE;
|
||||
break;
|
||||
}
|
||||
int c = f->_getc();
|
||||
if (c == EOF) {
|
||||
retval = ERR_XML_PARSE;
|
||||
break;
|
||||
}
|
||||
buf[n++] = c;
|
||||
buf[n] = 0;
|
||||
char* p = strstr(buf, end_tag);
|
||||
if (p) {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[n] = 0;
|
||||
strip_whitespace(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool parse_start(const char*);
|
||||
bool parse_str(const char*, char*, int);
|
||||
bool parse_string(const char*, std::string&);
|
||||
|
@ -58,8 +234,6 @@ public:
|
|||
bool parse_ulong(const char*, unsigned long&);
|
||||
bool parse_ulonglong(const char*, unsigned long long&);
|
||||
bool parse_bool(const char*, bool&);
|
||||
int element_contents(const char*, char*, int);
|
||||
int element_contents(const char*, std::string&);
|
||||
int copy_element(std::string&);
|
||||
void skip_unexpected(const char*, bool verbose, const char*);
|
||||
void skip_unexpected(bool verbose=false, const char* msg="") {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef _PROXY_INFO_
|
||||
#define _PROXY_INFO_
|
||||
|
||||
class XML_PARSER;
|
||||
struct XML_PARSER;
|
||||
class MIOFILE;
|
||||
|
||||
// info on whether HTTP requests need to go through a proxy
|
||||
|
|
|
@ -349,6 +349,20 @@ inline static const char* get_remote_addr() {
|
|||
return r ? r : "?.?.?.?";
|
||||
}
|
||||
|
||||
#if 0 // performance test for XML parsing (use a large request)
|
||||
int main(int, char**) {
|
||||
SCHEDULER_REQUEST sreq;
|
||||
FILE* f = fopen("req", "r");
|
||||
MIOFILE mf;
|
||||
XML_PARSER xp(&mf);
|
||||
mf.init_file(f);
|
||||
for (int i=0; i<10; i++) {
|
||||
sreq.parse(xp);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#if !defined(PLAN_CLASS_TEST)
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
@ -651,6 +665,7 @@ done:
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// the following stuff is here because if you put it in sched_limit.cpp
|
||||
// you get "ssp undefined" in programs other than cgi
|
||||
|
|
Loading…
Reference in New Issue