Commit fa58a6cc8143e592dd489716e3770775fd8b058c
1 parent
ab21de50
make http request and response childs of a common parent http message
Showing
24 changed files
with
696 additions
and
155 deletions
1 | +2012-02-12 12:43:56 +0100 Georg Hopp | ||
2 | + | ||
3 | + * make http request and response childs of a common parent http message (HEAD, master) | ||
4 | + | ||
1 | 2012-02-12 04:13:54 +0100 Georg Hopp | 5 | 2012-02-12 04:13:54 +0100 Georg Hopp |
2 | 6 | ||
3 | - * remove now obsoleted header_sort (HEAD, master) | 7 | + * remove now obsoleted header_sort |
4 | 8 | ||
5 | 2012-02-12 04:05:38 +0100 Georg Hopp | 9 | 2012-02-12 04:05:38 +0100 Georg Hopp |
6 | 10 |
@@ -42,28 +42,44 @@ | @@ -42,28 +42,44 @@ | ||
42 | * @TODO: actually i use gcc feature ## for variadoc... think about | 42 | * @TODO: actually i use gcc feature ## for variadoc... think about |
43 | * a way to make this standard. | 43 | * a way to make this standard. |
44 | */ | 44 | */ |
45 | -#define _CALL(object,_iface,method,...) \ | ||
46 | - class_ptr class = class_getClass((object)); \ | ||
47 | - struct i_##_iface * iface; \ | ||
48 | - if (class->init) class->init(); \ | ||
49 | - iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \ | ||
50 | - while ((NULL == iface || NULL == iface->method) && HAS_PARENT(class)) { \ | ||
51 | - class = class->parent; \ | ||
52 | - if (class->init) class->init(); \ | ||
53 | - iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \ | ||
54 | - }; \ | ||
55 | - assert(NULL != iface->method); | 45 | +#define _CALL(object,_iface,method,...) \ |
46 | + do { \ | ||
47 | + class_ptr class = class_getClass((object)); \ | ||
48 | + if (class->init) class->init(); \ | ||
49 | + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \ | ||
50 | + while ((NULL == iface || NULL == iface->method) && HAS_PARENT(class)) { \ | ||
51 | + class = class->parent; \ | ||
52 | + if (class->init) class->init(); \ | ||
53 | + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \ | ||
54 | + }; \ | ||
55 | + assert(NULL != iface->method); \ | ||
56 | + } while(0) | ||
56 | 57 | ||
57 | -#define CALL(object,_iface,method,...) \ | ||
58 | - do { \ | 58 | +#define CALL(object,_iface,method,...) \ |
59 | + do { \ | ||
60 | + struct i_##_iface * iface; \ | ||
59 | _CALL(object, _iface, method, ##__VA_ARGS__); \ | 61 | _CALL(object, _iface, method, ##__VA_ARGS__); \ |
60 | - iface->method(object, ##__VA_ARGS__); \ | 62 | + iface->method(object, ##__VA_ARGS__); \ |
61 | } while(0) | 63 | } while(0) |
62 | 64 | ||
63 | -#define RETCALL(object,_iface,method,ret,...) \ | ||
64 | - do { \ | 65 | +#define RETCALL(object,_iface,method,ret,...) \ |
66 | + do { \ | ||
67 | + struct i_##_iface * iface; \ | ||
65 | _CALL(object, _iface, method, ##__VA_ARGS__); \ | 68 | _CALL(object, _iface, method, ##__VA_ARGS__); \ |
66 | - ret = iface->method(object, ##__VA_ARGS__); \ | 69 | + ret = iface->method(object, ##__VA_ARGS__); \ |
70 | + } while(0) | ||
71 | + | ||
72 | +#define PARENTCALL(object,_iface,method,...) \ | ||
73 | + do { \ | ||
74 | + struct i_##_iface * iface; \ | ||
75 | + class_ptr class = class_getClass((object)); \ | ||
76 | + if (class->init) class->init(); \ | ||
77 | + assert(HAS_PARENT(class)); \ | ||
78 | + class = class->parent; \ | ||
79 | + if (class->init) class->init(); \ | ||
80 | + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \ | ||
81 | + assert(NULL != iface->method); \ | ||
82 | + iface->method(object, ##__VA_ARGS__); \ | ||
67 | } while(0) | 83 | } while(0) |
68 | 84 | ||
69 | 85 |
include/http/message.h
0 → 100644
1 | +#ifndef __HTTP_MESSAGE__ | ||
2 | +#define __HTTP_MESSAGE__ | ||
3 | + | ||
4 | +#include "class.h" | ||
5 | +#include "http/header.h" | ||
6 | + | ||
7 | +typedef enum e_HttpMessageType { | ||
8 | + HTTP_MESSAGE_BUFFERED=0, | ||
9 | + HTTP_MESSAGE_PIPED | ||
10 | +} HttpMessageType; | ||
11 | + | ||
12 | + | ||
13 | +CLASS(HttpMessage) { | ||
14 | + char * version; | ||
15 | + | ||
16 | + HttpHeader header; | ||
17 | + | ||
18 | + HttpMessageType type; | ||
19 | + union { | ||
20 | + char * buffer; | ||
21 | + int handle; | ||
22 | + } body; | ||
23 | + int nbody; | ||
24 | +}; | ||
25 | + | ||
26 | +#endif // __HTTP_MESSAGE__ | ||
27 | + | ||
28 | +// vim: set ts=4 sw=4: |
@@ -2,17 +2,13 @@ | @@ -2,17 +2,13 @@ | ||
2 | #define __HTTP_REQUEST_H__ | 2 | #define __HTTP_REQUEST_H__ |
3 | 3 | ||
4 | #include "class.h" | 4 | #include "class.h" |
5 | -#include "http/header.h" | 5 | +#include "http/message.h" |
6 | 6 | ||
7 | CLASS(HttpRequest) { | 7 | CLASS(HttpRequest) { |
8 | + EXTENDS(HttpMessage); | ||
9 | + | ||
8 | char * method; | 10 | char * method; |
9 | char * uri; | 11 | char * uri; |
10 | - char * version; | ||
11 | - | ||
12 | - HttpHeader header; | ||
13 | - | ||
14 | - char * body; | ||
15 | - int nbody; | ||
16 | }; | 12 | }; |
17 | 13 | ||
18 | char httpRequestHasKeepAlive(HttpRequest); | 14 | char httpRequestHasKeepAlive(HttpRequest); |
@@ -7,6 +7,9 @@ | @@ -7,6 +7,9 @@ | ||
7 | 7 | ||
8 | #define HTTP_REQUEST_PARSER_READ_CHUNK 1024 | 8 | #define HTTP_REQUEST_PARSER_READ_CHUNK 1024 |
9 | 9 | ||
10 | +#define REMAINS(pars) \ | ||
11 | + ((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer)) | ||
12 | + | ||
10 | 13 | ||
11 | typedef enum e_HttpRequestState { | 14 | typedef enum e_HttpRequestState { |
12 | HTTP_REQUEST_GARBAGE=0, | 15 | HTTP_REQUEST_GARBAGE=0, |
@@ -32,6 +35,8 @@ CLASS(HttpRequestParser) { | @@ -32,6 +35,8 @@ CLASS(HttpRequestParser) { | ||
32 | 35 | ||
33 | size_t httpRequestParserRead(HttpRequestParser, int); | 36 | size_t httpRequestParserRead(HttpRequestParser, int); |
34 | void httpRequestParserParse(HttpRequestParser); | 37 | void httpRequestParserParse(HttpRequestParser); |
38 | +void httpRequestParserGetBody(HttpRequestParser); | ||
39 | + | ||
35 | void httpRequestParserGetRequestLine(HttpRequest, char *); | 40 | void httpRequestParserGetRequestLine(HttpRequest, char *); |
36 | void httpRequestParserGetHeader(HttpRequest, char *); | 41 | void httpRequestParserGetHeader(HttpRequest, char *); |
37 | 42 |
@@ -4,18 +4,14 @@ | @@ -4,18 +4,14 @@ | ||
4 | #include <sys/types.h> | 4 | #include <sys/types.h> |
5 | 5 | ||
6 | #include "class.h" | 6 | #include "class.h" |
7 | -#include "http/header.h" | 7 | +#include "http/message.h" |
8 | 8 | ||
9 | 9 | ||
10 | CLASS(HttpResponse) { | 10 | CLASS(HttpResponse) { |
11 | - char * version; | 11 | + EXTENDS(HttpMessage); |
12 | + | ||
12 | unsigned int status; | 13 | unsigned int status; |
13 | char * reason; | 14 | char * reason; |
14 | - | ||
15 | - HttpHeader header; | ||
16 | - | ||
17 | - char * body; | ||
18 | - int nbody; | ||
19 | }; | 15 | }; |
20 | 16 | ||
21 | HttpResponse httpResponse404(); | 17 | HttpResponse httpResponse404(); |
include/http/worker.h
0 → 100644
@@ -6,6 +6,7 @@ CLASS = class.c interface.c | @@ -6,6 +6,7 @@ CLASS = class.c interface.c | ||
6 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c | 6 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
7 | SERVER = server.c server/run.c server/close_conn.c | 7 | SERVER = server.c server/run.c server/close_conn.c |
8 | LOGGER = logger.c logger/stderr.c logger/syslog.c | 8 | LOGGER = logger.c logger/stderr.c logger/syslog.c |
9 | +MSG = http/message.c | ||
9 | REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c | 10 | REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c |
10 | RESP = http/response.c http/response/404.c http/response/size_get.c \ | 11 | RESP = http/response.c http/response/404.c http/response/size_get.c \ |
11 | http/response/to_string.c | 12 | http/response/to_string.c |
@@ -13,7 +14,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \ | @@ -13,7 +14,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \ | ||
13 | http/header/size_get.c http/header/to_string.c | 14 | http/header/size_get.c http/header/to_string.c |
14 | PARSER = http/request/parser.c http/request/parser/get_header.c \ | 15 | PARSER = http/request/parser.c http/request/parser/get_header.c \ |
15 | http/request/parser/parse.c http/request/parser/get_request_line.c \ | 16 | http/request/parser/parse.c http/request/parser/get_request_line.c \ |
16 | - http/request/parser/read.c | 17 | + http/request/parser/read.c http/request/parser/get_body.c |
17 | 18 | ||
18 | 19 | ||
19 | AM_CFLAGS = -Wall -I ../include/ | 20 | AM_CFLAGS = -Wall -I ../include/ |
@@ -21,6 +22,6 @@ AM_CFLAGS = -Wall -I ../include/ | @@ -21,6 +22,6 @@ AM_CFLAGS = -Wall -I ../include/ | ||
21 | bin_PROGRAMS = testserver | 22 | bin_PROGRAMS = testserver |
22 | 23 | ||
23 | testserver_SOURCES = testserver.c \ | 24 | testserver_SOURCES = testserver.c \ |
24 | - $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(REQ) \ | 25 | + $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ |
25 | $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c | 26 | $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c |
26 | testserver_CFLAGS = -Wall -I ../include/ | 27 | testserver_CFLAGS = -Wall -I ../include/ |
src/http/header/add.c
0 → 100644
1 | +#include <search.h> | ||
2 | +#include <stdlib.h> | ||
3 | +#include <ctype.h> | ||
4 | +#include <stdio.h> | ||
5 | + | ||
6 | +#include "class.h" | ||
7 | +#include "interface/class.h" | ||
8 | +#include "http/header.h" | ||
9 | + | ||
10 | +static | ||
11 | +inline | ||
12 | +unsigned long | ||
13 | +sdbm(const unsigned char * str) | ||
14 | +{ | ||
15 | + unsigned long hash = 0; | ||
16 | + int c; | ||
17 | + | ||
18 | + while ((c = tolower(*str++))) | ||
19 | + hash = c + (hash << 6) + (hash << 16) - hash; | ||
20 | + | ||
21 | + return hash; | ||
22 | +} | ||
23 | + | ||
24 | +static | ||
25 | +inline | ||
26 | +int | ||
27 | +comp(const void * _a, const void * _b) | ||
28 | +{ | ||
29 | + HttpHeader a = (HttpHeader)_a; | ||
30 | + HttpHeader b = (HttpHeader)_b; | ||
31 | + return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; | ||
32 | +} | ||
33 | + | ||
34 | +void | ||
35 | +httpHeaderAdd(const HttpHeader * root, HttpHeader header) | ||
36 | +{ | ||
37 | + HttpHeader * found = tsearch(header, (void **)root, comp); | ||
38 | + | ||
39 | + if (*found != header) { | ||
40 | + puts("uhh, duplicate header set. " | ||
41 | + "This is not implemented right now. " | ||
42 | + "Keep the first one found."); | ||
43 | + delete(&header); | ||
44 | + } | ||
45 | +} | ||
46 | + | ||
47 | +// vim: set ts=4 sw=4: |
src/http/message.c
0 → 100644
1 | +#ifndef _GNU_SOURCE | ||
2 | +#define _GNU_SOURCE | ||
3 | +#endif | ||
4 | + | ||
5 | +#include <search.h> | ||
6 | +#include <stdlib.h> | ||
7 | +#include <string.h> | ||
8 | +#include <stdarg.h> | ||
9 | +#include <unistd.h> | ||
10 | + | ||
11 | +#include "class.h" | ||
12 | +#include "interface/class.h" | ||
13 | + | ||
14 | +#include "http/message.h" | ||
15 | +#include "message/helper.c" | ||
16 | + | ||
17 | + | ||
18 | +static | ||
19 | +void | ||
20 | +ctor(void * _this, va_list * params) | ||
21 | +{ | ||
22 | + HttpMessage this = _this; | ||
23 | + char * version = va_arg(* params, char *); | ||
24 | + | ||
25 | + this->version = calloc(1, strlen(version)+1); | ||
26 | + strcpy(this->version, version); | ||
27 | +} | ||
28 | + | ||
29 | +static | ||
30 | +void | ||
31 | +dtor(void * _this) | ||
32 | +{ | ||
33 | + HttpMessage this = _this; | ||
34 | + | ||
35 | + _free((void **)&(this->version)); | ||
36 | + | ||
37 | + /** | ||
38 | + * this is a GNU extension...anyway on most non | ||
39 | + * GNUish systems i would not use tsearch anyway | ||
40 | + * as the trees will be unbalanced. | ||
41 | + */ | ||
42 | + tdestroy(this->header, tDelete); | ||
43 | + | ||
44 | + switch (this->type) { | ||
45 | + case HTTP_MESSAGE_BUFFERED: | ||
46 | + _free((void **)&((this->body).buffer)); | ||
47 | + break; | ||
48 | + | ||
49 | + case HTTP_MESSAGE_PIPED: | ||
50 | + close((this->body).handle); | ||
51 | + break; | ||
52 | + | ||
53 | + default: | ||
54 | + break; | ||
55 | + } | ||
56 | +} | ||
57 | + | ||
58 | +INIT_IFACE(Class, ctor, dtor, NULL); | ||
59 | +CREATE_CLASS(HttpMessage, NULL, IFACE(Class)); | ||
60 | + | ||
61 | +// vim: set ts=4 sw=4: |
src/http/message/helper.c
0 → 100644
1 | +#ifndef __HTTP_MESSAGE_HELPER_C__ | ||
2 | +#define __HTTP_MESSAGE_HELPER_C__ | ||
3 | + | ||
4 | +#include <stdlib.h> | ||
5 | + | ||
6 | +#include "class.h" | ||
7 | +#include "interface/class.h" | ||
8 | + | ||
9 | + | ||
10 | +static | ||
11 | +inline | ||
12 | +void | ||
13 | +_free(void ** data) | ||
14 | +{ | ||
15 | + if (NULL != *data) { | ||
16 | + free(*data); | ||
17 | + } | ||
18 | +} | ||
19 | + | ||
20 | +static | ||
21 | +inline | ||
22 | +void | ||
23 | +tDelete(void * node) | ||
24 | +{ | ||
25 | + delete(&node); | ||
26 | +} | ||
27 | + | ||
28 | +#endif // __HTTP_MESSAGE_HELPER_C__ | ||
29 | + | ||
30 | +// vim: set ts=4 sw=4: |
1 | -#ifndef _GNU_SOURCE | ||
2 | -#define _GNU_SOURCE | ||
3 | -#endif | ||
4 | - | ||
5 | #include <stdlib.h> | 1 | #include <stdlib.h> |
6 | #include <stdarg.h> | 2 | #include <stdarg.h> |
7 | -#include <search.h> | ||
8 | 3 | ||
9 | #include "class.h" | 4 | #include "class.h" |
10 | #include "interface/class.h" | 5 | #include "interface/class.h" |
11 | 6 | ||
12 | #include "http/request.h" | 7 | #include "http/request.h" |
8 | +#include "message/helper.c" | ||
13 | 9 | ||
14 | 10 | ||
15 | static | 11 | static |
16 | -inline | ||
17 | -void | ||
18 | -_free(void ** data) | ||
19 | -{ | ||
20 | - if (NULL != *data) { | ||
21 | - free(*data); | ||
22 | - } | ||
23 | -} | ||
24 | - | ||
25 | -static | ||
26 | -inline | ||
27 | -void | ||
28 | -tDelete(void * node) | ||
29 | -{ | ||
30 | - delete(&node); | ||
31 | -} | ||
32 | - | ||
33 | -static | ||
34 | void | 12 | void |
35 | ctor(void * _this, va_list * params) {} | 13 | ctor(void * _this, va_list * params) {} |
36 | 14 | ||
@@ -40,21 +18,13 @@ dtor(void * _this) | @@ -40,21 +18,13 @@ dtor(void * _this) | ||
40 | { | 18 | { |
41 | HttpRequest this = _this; | 19 | HttpRequest this = _this; |
42 | 20 | ||
43 | - _free((void **)&(this->version)); | ||
44 | _free((void **)&(this->uri)); | 21 | _free((void **)&(this->uri)); |
45 | _free((void **)&(this->method)); | 22 | _free((void **)&(this->method)); |
46 | 23 | ||
47 | - /** | ||
48 | - * this is a GNU extension...anyway on most non | ||
49 | - * GNUish systems i would not use tsearch anyway | ||
50 | - * as the trees will be unbalanced. | ||
51 | - */ | ||
52 | - tdestroy(this->header, tDelete); | ||
53 | - | ||
54 | - _free((void **)&(this->body)); | 24 | + PARENTCALL(_this, Class, dtor); |
55 | } | 25 | } |
56 | 26 | ||
57 | INIT_IFACE(Class, ctor, dtor, NULL); | 27 | INIT_IFACE(Class, ctor, dtor, NULL); |
58 | -CREATE_CLASS(HttpRequest, NULL, IFACE(Class)); | 28 | +CREATE_CLASS(HttpRequest, HttpMessage, IFACE(Class)); |
59 | 29 | ||
60 | // vim: set ts=4 sw=4: | 30 | // vim: set ts=4 sw=4: |
1 | #include <string.h> | 1 | #include <string.h> |
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | 3 | ||
4 | +#include "http/message.h" | ||
4 | #include "http/request.h" | 5 | #include "http/request.h" |
5 | #include "http/header.h" | 6 | #include "http/header.h" |
6 | 7 | ||
@@ -8,10 +9,11 @@ | @@ -8,10 +9,11 @@ | ||
8 | char | 9 | char |
9 | httpRequestHasKeepAlive(HttpRequest request) | 10 | httpRequestHasKeepAlive(HttpRequest request) |
10 | { | 11 | { |
11 | - char * header; | ||
12 | - char * header_ptr; | 12 | + HttpMessage message = (HttpMessage)request; |
13 | + char * header; | ||
14 | + char * header_ptr; | ||
13 | 15 | ||
14 | - header = httpHeaderGet(&(request->header), "connection"); | 16 | + header = httpHeaderGet(&(message->header), "connection"); |
15 | 17 | ||
16 | if (NULL == header) { | 18 | if (NULL == header) { |
17 | return 0; | 19 | return 0; |
src/http/request/parser/get_body.c
0 → 100644
1 | +#include <stdlib.h> | ||
2 | + | ||
3 | +#include "http/header.h" | ||
4 | +#include "http/message.h" | ||
5 | +#include "http/request/parser.h" | ||
6 | + | ||
7 | +void | ||
8 | +httpRequestParserGetBody(HttpRequestParser this) | ||
9 | +{ | ||
10 | + HttpMessage message = (HttpMessage)(this->cur_request); | ||
11 | + char * nbody; | ||
12 | + | ||
13 | + if (0 == message->nbody) { | ||
14 | + nbody = httpHeaderGet( | ||
15 | + &(message->header), | ||
16 | + "Content-Length"); | ||
17 | + | ||
18 | + if (NULL == nbody) { | ||
19 | + this->state = HTTP_REQUEST_DONE; | ||
20 | + return; | ||
21 | + } | ||
22 | + else { | ||
23 | + message->type = HTTP_MESSAGE_BUFFERED; | ||
24 | + message->nbody = atoi(nbody); | ||
25 | + } | ||
26 | + } | ||
27 | + | ||
28 | + if (REMAINS(this) >= message->nbody) { | ||
29 | + (message->body).buffer = calloc(1, message->nbody + 1); | ||
30 | + memcpy((message->body).buffer, | ||
31 | + this->cur_data, | ||
32 | + message->nbody); | ||
33 | + this->cur_data += message->nbody; | ||
34 | + this->state = HTTP_REQUEST_DONE; | ||
35 | + } | ||
36 | +} | ||
37 | + | ||
38 | +// vim: set ts=4 sw=4: |
@@ -5,10 +5,10 @@ | @@ -5,10 +5,10 @@ | ||
5 | #include "class.h" | 5 | #include "class.h" |
6 | #include "interface/class.h" | 6 | #include "interface/class.h" |
7 | #include "http/header.h" | 7 | #include "http/header.h" |
8 | -#include "http/request.h" | 8 | +#include "http/message.h" |
9 | 9 | ||
10 | void | 10 | void |
11 | -httpRequestParserGetHeader(HttpRequest request, char * line) | 11 | +httpRequestParserGetHeader(HttpMessage request, char * line) |
12 | { | 12 | { |
13 | char * name = line; | 13 | char * name = line; |
14 | char * value = strchr(line, ':'); | 14 | char * value = strchr(line, ':'); |
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | void | 7 | void |
8 | httpRequestParserGetRequestLine(HttpRequest request, char * line) | 8 | httpRequestParserGetRequestLine(HttpRequest request, char * line) |
9 | { | 9 | { |
10 | + HttpMessage message = (HttpMessage)request; | ||
10 | char * method, * uri, * version; | 11 | char * method, * uri, * version; |
11 | 12 | ||
12 | method = line; | 13 | method = line; |
@@ -23,8 +24,8 @@ httpRequestParserGetRequestLine(HttpRequest request, char * line) | @@ -23,8 +24,8 @@ httpRequestParserGetRequestLine(HttpRequest request, char * line) | ||
23 | strcpy(request->method, method); | 24 | strcpy(request->method, method); |
24 | request->uri = malloc(strlen(uri) + 1); | 25 | request->uri = malloc(strlen(uri) + 1); |
25 | strcpy(request->uri, uri); | 26 | strcpy(request->uri, uri); |
26 | - request->version = malloc(strlen(version) + 1); | ||
27 | - strcpy(request->version, method); | 27 | + message->version = malloc(strlen(version) + 1); |
28 | + strcpy(message->version, method); | ||
28 | } | 29 | } |
29 | 30 | ||
30 | // vim: set ts=4 sw=4: | 31 | // vim: set ts=4 sw=4: |
@@ -7,10 +7,6 @@ | @@ -7,10 +7,6 @@ | ||
7 | #include "interface/class.h" | 7 | #include "interface/class.h" |
8 | 8 | ||
9 | 9 | ||
10 | -#define REMAINS(pars) \ | ||
11 | - ((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer)) | ||
12 | - | ||
13 | - | ||
14 | static | 10 | static |
15 | inline | 11 | inline |
16 | char * | 12 | char * |
@@ -79,33 +75,7 @@ httpRequestParserParse(HttpRequestParser this) | @@ -79,33 +75,7 @@ httpRequestParserParse(HttpRequestParser this) | ||
79 | break; | 75 | break; |
80 | 76 | ||
81 | case HTTP_REQUEST_HEADERS_DONE: | 77 | case HTTP_REQUEST_HEADERS_DONE: |
82 | - { | ||
83 | - char * nbody; | ||
84 | - | ||
85 | - if (0 == this->cur_request->nbody) { | ||
86 | - nbody = httpHeaderGet( | ||
87 | - &(this->cur_request->header), | ||
88 | - "Content-Length"); | ||
89 | - | ||
90 | - if (NULL == nbody) { | ||
91 | - this->state = HTTP_REQUEST_DONE; | ||
92 | - break; | ||
93 | - } | ||
94 | - else { | ||
95 | - this->cur_request->nbody = atoi(nbody); | ||
96 | - } | ||
97 | - } | ||
98 | - | ||
99 | - if (REMAINS(this) >= this->cur_request->nbody) { | ||
100 | - this->cur_request->body = calloc(1, this->cur_request->nbody + 1); | ||
101 | - memcpy(this->cur_request->body, | ||
102 | - this->cur_data, | ||
103 | - this->cur_request->nbody); | ||
104 | - this->cur_data += this->cur_request->nbody; | ||
105 | - this->state = HTTP_REQUEST_DONE; | ||
106 | - } | ||
107 | - } | ||
108 | - | 78 | + httpRequestParserGetBody(this); |
109 | break; | 79 | break; |
110 | 80 | ||
111 | case HTTP_REQUEST_DONE: | 81 | case HTTP_REQUEST_DONE: |
src/http/request/parser/read.c
0 → 100644
1 | +#include <stdlib.h> | ||
2 | +#include <unistd.h> | ||
3 | + | ||
4 | +#include "http/request/parser.h" | ||
5 | + | ||
6 | + | ||
7 | +size_t | ||
8 | +httpRequestParserRead(HttpRequestParser this, int fd) | ||
9 | +{ | ||
10 | + size_t remaining, chunks; | ||
11 | + char buffer[1024]; | ||
12 | + | ||
13 | + ssize_t size = read(fd, buffer, 1024); | ||
14 | + | ||
15 | + if (0 < size) { | ||
16 | + remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK; | ||
17 | + chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK; | ||
18 | + | ||
19 | + /** | ||
20 | + * because a division always rounds down | ||
21 | + * chunks holds exactly the currently allocated chunks if | ||
22 | + * remaining equals 0 but there is no space left. | ||
23 | + * Else chunks holds the actually allocated amount of chunks | ||
24 | + * minus 1. | ||
25 | + * For this reason chunks always has to be increased by 1. | ||
26 | + */ | ||
27 | + chunks++; | ||
28 | + | ||
29 | + if (size >= remaining) { | ||
30 | + this->buffer = | ||
31 | + realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK); | ||
32 | + } | ||
33 | + | ||
34 | + memcpy(this->buffer + this->buffer_used, buffer, size); | ||
35 | + this->buffer_used += size; | ||
36 | + this->buffer[this->buffer_used] = 0; | ||
37 | + | ||
38 | + httpRequestParserParse(this); | ||
39 | + } | ||
40 | + | ||
41 | + return size; | ||
42 | +} | ||
43 | + | ||
44 | +// vim: set ts=4 sw=4: |
1 | -#ifndef _GNU_SOURCE | ||
2 | -#define _GNU_SOURCE | ||
3 | -#endif | ||
4 | - | ||
5 | -#include <search.h> | ||
6 | #include <stdlib.h> | 1 | #include <stdlib.h> |
7 | #include <stdarg.h> | 2 | #include <stdarg.h> |
8 | 3 | ||
@@ -10,60 +5,38 @@ | @@ -10,60 +5,38 @@ | ||
10 | #include "interface/class.h" | 5 | #include "interface/class.h" |
11 | 6 | ||
12 | #include "http/response.h" | 7 | #include "http/response.h" |
8 | +#include "message/helper.c" | ||
13 | 9 | ||
14 | 10 | ||
15 | static | 11 | static |
16 | void | 12 | void |
17 | -_free(void ** data) | ||
18 | -{ | ||
19 | - if (NULL != *data) { | ||
20 | - free(*data); | ||
21 | - } | ||
22 | -} | ||
23 | - | ||
24 | -static | ||
25 | -void | ||
26 | ctor(void * _this, va_list * params) | 13 | ctor(void * _this, va_list * params) |
27 | { | 14 | { |
28 | - char * version; | 15 | + HttpResponse this = _this; |
16 | + char * status; | ||
29 | char * reason; | 17 | char * reason; |
30 | 18 | ||
31 | - HttpResponse this = _this; | 19 | + PARENTCALL(_this, Class, ctor, params); |
32 | 20 | ||
33 | - version = va_arg(* params, char *); | ||
34 | this->status = va_arg(* params, unsigned int); | 21 | this->status = va_arg(* params, unsigned int); |
35 | reason = va_arg(* params, char *); | 22 | reason = va_arg(* params, char *); |
36 | 23 | ||
37 | - this->version = calloc(1, strlen(version)+1); | ||
38 | - strcpy(this->version, version); | ||
39 | - | ||
40 | this->reason = calloc(1, strlen(reason)+1); | 24 | this->reason = calloc(1, strlen(reason)+1); |
41 | strcpy(this->reason, reason); | 25 | strcpy(this->reason, reason); |
42 | } | 26 | } |
43 | 27 | ||
44 | static | 28 | static |
45 | -inline | ||
46 | -void | ||
47 | -tDelete(void * node) | ||
48 | -{ | ||
49 | - delete(&node); | ||
50 | -} | ||
51 | - | ||
52 | -static | ||
53 | void | 29 | void |
54 | dtor(void * _this) | 30 | dtor(void * _this) |
55 | { | 31 | { |
56 | HttpResponse this = _this; | 32 | HttpResponse this = _this; |
57 | 33 | ||
58 | - _free((void **)&(this->version)); | ||
59 | _free((void **)&(this->reason)); | 34 | _free((void **)&(this->reason)); |
60 | 35 | ||
61 | - tdestroy(this->header, tDelete); | ||
62 | - | ||
63 | - _free((void **)&(this->body)); | 36 | + PARENTCALL(_this, Class, dtor); |
64 | } | 37 | } |
65 | 38 | ||
66 | INIT_IFACE(Class, ctor, dtor, NULL); | 39 | INIT_IFACE(Class, ctor, dtor, NULL); |
67 | -CREATE_CLASS(HttpResponse, NULL, IFACE(Class)); | 40 | +CREATE_CLASS(HttpResponse, HttpMessage, IFACE(Class)); |
68 | 41 | ||
69 | // vim: set ts=4 sw=4: | 42 | // vim: set ts=4 sw=4: |
@@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
7 | #include "interface/class.h" | 7 | #include "interface/class.h" |
8 | 8 | ||
9 | #include "http/response.h" | 9 | #include "http/response.h" |
10 | +#include "http/message.h" | ||
10 | #include "http/header.h" | 11 | #include "http/header.h" |
11 | 12 | ||
12 | 13 | ||
@@ -26,26 +27,29 @@ httpResponse404() | @@ -26,26 +27,29 @@ httpResponse404() | ||
26 | struct tm * tmp; | 27 | struct tm * tmp; |
27 | char buffer[200]; | 28 | char buffer[200]; |
28 | HttpResponse response; | 29 | HttpResponse response; |
30 | + HttpMessage message; | ||
29 | 31 | ||
30 | response = new(HttpResponse, "HTTP/1.1", 404, "Not Found"); | 32 | response = new(HttpResponse, "HTTP/1.1", 404, "Not Found"); |
33 | + message = (HttpMessage)response; | ||
31 | 34 | ||
32 | - httpHeaderAdd(&(response->header), | 35 | + httpHeaderAdd(&(message->header), |
33 | new(HttpHeader, "Content-Type", "text/html")); | 36 | new(HttpHeader, "Content-Type", "text/html")); |
34 | - httpHeaderAdd(&(response->header), | 37 | + httpHeaderAdd(&(message->header), |
35 | new(HttpHeader, "Server", "testserver")); | 38 | new(HttpHeader, "Server", "testserver")); |
36 | 39 | ||
37 | - response->nbody = sizeof(RESP_DATA) - 1; | ||
38 | - response->body = calloc(1, sizeof(RESP_DATA)); | ||
39 | - strcpy(response->body, RESP_DATA); | 40 | + message->type = HTTP_MESSAGE_BUFFERED; |
41 | + message->nbody = sizeof(RESP_DATA) - 1; | ||
42 | + (message->body).buffer = calloc(1, sizeof(RESP_DATA)); | ||
43 | + strcpy((message->body).buffer, RESP_DATA); | ||
40 | 44 | ||
41 | - sprintf(buffer, "%d", response->nbody); | ||
42 | - httpHeaderAdd(&(response->header), | 45 | + sprintf(buffer, "%d", message->nbody); |
46 | + httpHeaderAdd(&(message->header), | ||
43 | new(HttpHeader, "Content-Length", buffer)); | 47 | new(HttpHeader, "Content-Length", buffer)); |
44 | 48 | ||
45 | t = time(NULL); | 49 | t = time(NULL); |
46 | tmp = localtime(&t); | 50 | tmp = localtime(&t); |
47 | strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp); | 51 | strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp); |
48 | - httpHeaderAdd(&(response->header), | 52 | + httpHeaderAdd(&(message->header), |
49 | new(HttpHeader, "Date", buffer)); | 53 | new(HttpHeader, "Date", buffer)); |
50 | 54 | ||
51 | return response; | 55 | return response; |
@@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
2 | #include <string.h> | 2 | #include <string.h> |
3 | #include <sys/types.h> | 3 | #include <sys/types.h> |
4 | 4 | ||
5 | +#include "http/message.h" | ||
5 | #include "http/response.h" | 6 | #include "http/response.h" |
6 | #include "http/header.h" | 7 | #include "http/header.h" |
7 | 8 | ||
@@ -20,16 +21,21 @@ addHeaderSize(const void * node, const VISIT which, const int depth) | @@ -20,16 +21,21 @@ addHeaderSize(const void * node, const VISIT which, const int depth) | ||
20 | size_t | 21 | size_t |
21 | httpResponseSizeGet(HttpResponse response) | 22 | httpResponseSizeGet(HttpResponse response) |
22 | { | 23 | { |
24 | + HttpMessage message = (HttpMessage)response; | ||
25 | + | ||
23 | size = 0; | 26 | size = 0; |
24 | 27 | ||
25 | - size += strlen(response->version) + 1; | 28 | + size += strlen(message->version) + 1; |
26 | size += 4; // for status | 29 | size += 4; // for status |
27 | size += strlen(response->reason) + 2; | 30 | size += strlen(response->reason) + 2; |
28 | 31 | ||
29 | - twalk(response->header, addHeaderSize); | 32 | + twalk(message->header, addHeaderSize); |
30 | 33 | ||
31 | size += 2; | 34 | size += 2; |
32 | - size += response->nbody; | 35 | + |
36 | + if (HTTP_MESSAGE_BUFFERED == message->type) { | ||
37 | + size += message->nbody; | ||
38 | + } | ||
33 | 39 | ||
34 | return size; | 40 | return size; |
35 | } | 41 | } |
@@ -20,13 +20,14 @@ addHeaderString(const void * node, const VISIT which, const int depth) | @@ -20,13 +20,14 @@ addHeaderString(const void * node, const VISIT which, const int depth) | ||
20 | char * | 20 | char * |
21 | httpResponseToString(HttpResponse response, char * _string) | 21 | httpResponseToString(HttpResponse response, char * _string) |
22 | { | 22 | { |
23 | - char status[4]; | 23 | + HttpMessage message = (HttpMessage)response; |
24 | + char status[4]; | ||
24 | 25 | ||
25 | string = _string; | 26 | string = _string; |
26 | 27 | ||
27 | snprintf(status, 4, "%d", response->status); | 28 | snprintf(status, 4, "%d", response->status); |
28 | 29 | ||
29 | - strcpy(string, response->version); | 30 | + strcpy(string, message->version); |
30 | string += strlen(string); | 31 | string += strlen(string); |
31 | 32 | ||
32 | *string++ = ' '; | 33 | *string++ = ' '; |
@@ -42,12 +43,14 @@ httpResponseToString(HttpResponse response, char * _string) | @@ -42,12 +43,14 @@ httpResponseToString(HttpResponse response, char * _string) | ||
42 | *string++ = '\r'; | 43 | *string++ = '\r'; |
43 | *string++ = '\n'; | 44 | *string++ = '\n'; |
44 | 45 | ||
45 | - twalk(response->header, addHeaderString); | 46 | + twalk(message->header, addHeaderString); |
46 | 47 | ||
47 | *string++ = '\r'; | 48 | *string++ = '\r'; |
48 | *string++ = '\n'; | 49 | *string++ = '\n'; |
49 | 50 | ||
50 | - memcpy(string, response->body, response->nbody); | 51 | + if (HTTP_MESSAGE_BUFFERED == message->type) { |
52 | + memcpy(string, (message->body).buffer, message->nbody); | ||
53 | + } | ||
51 | 54 | ||
52 | return string; | 55 | return string; |
53 | } | 56 | } |
@@ -117,13 +117,13 @@ serverRun(Server this) | @@ -117,13 +117,13 @@ serverRun(Server this) | ||
117 | if (httpRequestHasKeepAlive(queue->requests[j])) { | 117 | if (httpRequestHasKeepAlive(queue->requests[j])) { |
118 | (this->conns)[fd].keep_alive = 1; | 118 | (this->conns)[fd].keep_alive = 1; |
119 | httpHeaderAdd( | 119 | httpHeaderAdd( |
120 | - &(response->header), | 120 | + &(((HttpMessage)response)->header), |
121 | new(HttpHeader, "Connection", "Keep-Alive")); | 121 | new(HttpHeader, "Connection", "Keep-Alive")); |
122 | } | 122 | } |
123 | else { | 123 | else { |
124 | (this->conns)[fd].keep_alive = 0; | 124 | (this->conns)[fd].keep_alive = 0; |
125 | httpHeaderAdd( | 125 | httpHeaderAdd( |
126 | - &(response->header), | 126 | + &(((HttpMessage)response)->header), |
127 | new(HttpHeader, "Connection", "Close")); | 127 | new(HttpHeader, "Connection", "Close")); |
128 | } | 128 | } |
129 | 129 |
tests/tst-tsearch.c
0 → 100644
1 | +/* Test program for tsearch et al. | ||
2 | + Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc. | ||
3 | + This file is part of the GNU C Library. | ||
4 | + | ||
5 | + The GNU C Library is free software; you can redistribute it and/or | ||
6 | + modify it under the terms of the GNU Lesser General Public | ||
7 | + License as published by the Free Software Foundation; either | ||
8 | + version 2.1 of the License, or (at your option) any later version. | ||
9 | + | ||
10 | + The GNU C Library is distributed in the hope that it will be useful, | ||
11 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | + Lesser General Public License for more details. | ||
14 | + | ||
15 | + You should have received a copy of the GNU Lesser General Public | ||
16 | + License along with the GNU C Library; if not, write to the Free | ||
17 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
18 | + 02111-1307 USA. */ | ||
19 | + | ||
20 | +#ifndef _GNU_SOURCE | ||
21 | +# define _GNU_SOURCE 1 | ||
22 | +#endif | ||
23 | + | ||
24 | +#include <stdio.h> | ||
25 | +#include <stdlib.h> | ||
26 | +#include <string.h> | ||
27 | +#include <search.h> | ||
28 | + | ||
29 | +#define SEED 0 | ||
30 | +#define BALANCED 1 | ||
31 | +#define PASSES 100 | ||
32 | + | ||
33 | +#if BALANCED | ||
34 | +#include <math.h> | ||
35 | +#define SIZE 1000 | ||
36 | +#else | ||
37 | +#define SIZE 100 | ||
38 | +#endif | ||
39 | + | ||
40 | +enum order | ||
41 | +{ | ||
42 | + ascending, | ||
43 | + descending, | ||
44 | + randomorder | ||
45 | +}; | ||
46 | + | ||
47 | +enum action | ||
48 | +{ | ||
49 | + build, | ||
50 | + build_and_del, | ||
51 | + delete, | ||
52 | + find | ||
53 | +}; | ||
54 | + | ||
55 | +/* Set to 1 if a test is flunked. */ | ||
56 | +static int error = 0; | ||
57 | + | ||
58 | +/* The keys we add to the tree. */ | ||
59 | +static int x[SIZE]; | ||
60 | + | ||
61 | +/* Pointers into the key array, possibly permutated, to define an order | ||
62 | + for insertion/removal. */ | ||
63 | +static int y[SIZE]; | ||
64 | + | ||
65 | +/* Flags set for each element visited during a tree walk. */ | ||
66 | +static int z[SIZE]; | ||
67 | + | ||
68 | +/* Depths for all the elements, to check that the depth is constant for | ||
69 | + all three visits. */ | ||
70 | +static int depths[SIZE]; | ||
71 | + | ||
72 | +/* Maximum depth during a tree walk. */ | ||
73 | +static int max_depth; | ||
74 | + | ||
75 | +/* Compare two keys. */ | ||
76 | +static int | ||
77 | +cmp_fn (const void *a, const void *b) | ||
78 | +{ | ||
79 | + return *(const int *) a - *(const int *) b; | ||
80 | +} | ||
81 | + | ||
82 | +/* Permute an array of integers. */ | ||
83 | +static void | ||
84 | +memfry (int *string) | ||
85 | +{ | ||
86 | + int i; | ||
87 | + | ||
88 | + for (i = 0; i < SIZE; ++i) | ||
89 | + { | ||
90 | + int32_t j; | ||
91 | + int c; | ||
92 | + | ||
93 | + j = random () % SIZE; | ||
94 | + | ||
95 | + c = string[i]; | ||
96 | + string[i] = string[j]; | ||
97 | + string[j] = c; | ||
98 | + } | ||
99 | +} | ||
100 | + | ||
101 | +static void | ||
102 | +walk_action (const void *nodep, const VISIT which, const int depth) | ||
103 | +{ | ||
104 | + int key = **(int **) nodep; | ||
105 | + | ||
106 | + if (depth > max_depth) | ||
107 | + max_depth = depth; | ||
108 | + if (which == leaf || which == preorder) | ||
109 | + { | ||
110 | + ++z[key]; | ||
111 | + depths[key] = depth; | ||
112 | + } | ||
113 | + else | ||
114 | + { | ||
115 | + if (depths[key] != depth) | ||
116 | + { | ||
117 | + fputs ("Depth for one element is not constant during tree walk.\n", | ||
118 | + stdout); | ||
119 | + } | ||
120 | + } | ||
121 | +} | ||
122 | + | ||
123 | +static void | ||
124 | +walk_tree (void *root, int expected_count) | ||
125 | +{ | ||
126 | + int i; | ||
127 | + | ||
128 | + memset (z, 0, sizeof z); | ||
129 | + max_depth = 0; | ||
130 | + | ||
131 | + twalk (root, walk_action); | ||
132 | + for (i = 0; i < expected_count; ++i) | ||
133 | + if (z[i] != 1) | ||
134 | + { | ||
135 | + fputs ("Node was not visited.\n", stdout); | ||
136 | + error = 1; | ||
137 | + } | ||
138 | + | ||
139 | +#if BALANCED | ||
140 | + if (max_depth > log (expected_count) * 2 + 2) | ||
141 | +#else | ||
142 | + if (max_depth > expected_count) | ||
143 | +#endif | ||
144 | + { | ||
145 | + fputs ("Depth too large during tree walk.\n", stdout); | ||
146 | + error = 1; | ||
147 | + } | ||
148 | +} | ||
149 | + | ||
150 | +/* Perform an operation on a tree. */ | ||
151 | +static void | ||
152 | +mangle_tree (enum order how, enum action what, void **root, int lag) | ||
153 | +{ | ||
154 | + int i; | ||
155 | + | ||
156 | + if (how == randomorder) | ||
157 | + { | ||
158 | + for (i = 0; i < SIZE; ++i) | ||
159 | + y[i] = i; | ||
160 | + memfry (y); | ||
161 | + } | ||
162 | + | ||
163 | + for (i = 0; i < SIZE + lag; ++i) | ||
164 | + { | ||
165 | + void *elem; | ||
166 | + int j, k; | ||
167 | + | ||
168 | + switch (how) | ||
169 | + { | ||
170 | + case randomorder: | ||
171 | + if (i >= lag) | ||
172 | + k = y[i - lag]; | ||
173 | + else | ||
174 | + /* Ensure that the array index is within bounds. */ | ||
175 | + k = y[(SIZE - i - 1 + lag) % SIZE]; | ||
176 | + j = y[i % SIZE]; | ||
177 | + break; | ||
178 | + | ||
179 | + case ascending: | ||
180 | + k = i - lag; | ||
181 | + j = i; | ||
182 | + break; | ||
183 | + | ||
184 | + case descending: | ||
185 | + k = SIZE - i - 1 + lag; | ||
186 | + j = SIZE - i - 1; | ||
187 | + break; | ||
188 | + | ||
189 | + default: | ||
190 | + /* This never should happen, but gcc isn't smart enough to | ||
191 | + recognize it. */ | ||
192 | + abort (); | ||
193 | + } | ||
194 | + | ||
195 | + switch (what) | ||
196 | + { | ||
197 | + case build_and_del: | ||
198 | + case build: | ||
199 | + if (i < SIZE) | ||
200 | + { | ||
201 | + if (tfind (x + j, (void *const *) root, cmp_fn) != NULL) | ||
202 | + { | ||
203 | + fputs ("Found element which is not in tree yet.\n", stdout); | ||
204 | + error = 1; | ||
205 | + } | ||
206 | + elem = tsearch (x + j, root, cmp_fn); | ||
207 | + if (elem == 0 | ||
208 | + || tfind (x + j, (void *const *) root, cmp_fn) == NULL) | ||
209 | + { | ||
210 | + fputs ("Couldn't find element after it was added.\n", | ||
211 | + stdout); | ||
212 | + error = 1; | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
216 | + if (what == build || i < lag) | ||
217 | + break; | ||
218 | + | ||
219 | + j = k; | ||
220 | + /* fall through */ | ||
221 | + | ||
222 | + case delete: | ||
223 | + elem = tfind (x + j, (void *const *) root, cmp_fn); | ||
224 | + if (elem == NULL || tdelete (x + j, root, cmp_fn) == NULL) | ||
225 | + { | ||
226 | + fputs ("Error deleting element.\n", stdout); | ||
227 | + error = 1; | ||
228 | + } | ||
229 | + break; | ||
230 | + | ||
231 | + case find: | ||
232 | + if (tfind (x + j, (void *const *) root, cmp_fn) == NULL) | ||
233 | + { | ||
234 | + fputs ("Couldn't find element after it was added.\n", stdout); | ||
235 | + error = 1; | ||
236 | + } | ||
237 | + break; | ||
238 | + | ||
239 | + } | ||
240 | + } | ||
241 | +} | ||
242 | + | ||
243 | + | ||
244 | +int | ||
245 | +main (int argc, char **argv) | ||
246 | +{ | ||
247 | + int total_error = 0; | ||
248 | + static char state[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||
249 | + void *root = NULL; | ||
250 | + int i, j; | ||
251 | + | ||
252 | + initstate (SEED, state, 8); | ||
253 | + | ||
254 | + for (i = 0; i < SIZE; ++i) | ||
255 | + x[i] = i; | ||
256 | + | ||
257 | + /* Do this loop several times to get different permutations for the | ||
258 | + random case. */ | ||
259 | + fputs ("Series I\n", stdout); | ||
260 | + for (i = 0; i < PASSES; ++i) | ||
261 | + { | ||
262 | + fprintf (stdout, "Pass %d... ", i + 1); | ||
263 | + fflush (stdout); | ||
264 | + error = 0; | ||
265 | + | ||
266 | + mangle_tree (ascending, build, &root, 0); | ||
267 | + mangle_tree (ascending, find, &root, 0); | ||
268 | + mangle_tree (descending, find, &root, 0); | ||
269 | + mangle_tree (randomorder, find, &root, 0); | ||
270 | + walk_tree (root, SIZE); | ||
271 | + mangle_tree (ascending, delete, &root, 0); | ||
272 | + | ||
273 | + mangle_tree (ascending, build, &root, 0); | ||
274 | + walk_tree (root, SIZE); | ||
275 | + mangle_tree (descending, delete, &root, 0); | ||
276 | + | ||
277 | + mangle_tree (ascending, build, &root, 0); | ||
278 | + walk_tree (root, SIZE); | ||
279 | + mangle_tree (randomorder, delete, &root, 0); | ||
280 | + | ||
281 | + mangle_tree (descending, build, &root, 0); | ||
282 | + mangle_tree (ascending, find, &root, 0); | ||
283 | + mangle_tree (descending, find, &root, 0); | ||
284 | + mangle_tree (randomorder, find, &root, 0); | ||
285 | + walk_tree (root, SIZE); | ||
286 | + mangle_tree (descending, delete, &root, 0); | ||
287 | + | ||
288 | + mangle_tree (descending, build, &root, 0); | ||
289 | + walk_tree (root, SIZE); | ||
290 | + mangle_tree (descending, delete, &root, 0); | ||
291 | + | ||
292 | + mangle_tree (descending, build, &root, 0); | ||
293 | + walk_tree (root, SIZE); | ||
294 | + mangle_tree (randomorder, delete, &root, 0); | ||
295 | + | ||
296 | + mangle_tree (randomorder, build, &root, 0); | ||
297 | + mangle_tree (ascending, find, &root, 0); | ||
298 | + mangle_tree (descending, find, &root, 0); | ||
299 | + mangle_tree (randomorder, find, &root, 0); | ||
300 | + walk_tree (root, SIZE); | ||
301 | + mangle_tree (randomorder, delete, &root, 0); | ||
302 | + | ||
303 | + for (j = 1; j < SIZE; j *= 2) | ||
304 | + { | ||
305 | + mangle_tree (randomorder, build_and_del, &root, j); | ||
306 | + } | ||
307 | + | ||
308 | + fputs (error ? " failed!\n" : " ok.\n", stdout); | ||
309 | + total_error |= error; | ||
310 | + } | ||
311 | + | ||
312 | + fputs ("Series II\n", stdout); | ||
313 | + for (i = 1; i < SIZE; i *= 2) | ||
314 | + { | ||
315 | + fprintf (stdout, "For size %d... ", i); | ||
316 | + fflush (stdout); | ||
317 | + error = 0; | ||
318 | + | ||
319 | + mangle_tree (ascending, build_and_del, &root, i); | ||
320 | + mangle_tree (descending, build_and_del, &root, i); | ||
321 | + mangle_tree (ascending, build_and_del, &root, i); | ||
322 | + mangle_tree (descending, build_and_del, &root, i); | ||
323 | + mangle_tree (ascending, build_and_del, &root, i); | ||
324 | + mangle_tree (descending, build_and_del, &root, i); | ||
325 | + mangle_tree (ascending, build_and_del, &root, i); | ||
326 | + mangle_tree (descending, build_and_del, &root, i); | ||
327 | + | ||
328 | + fputs (error ? " failed!\n" : " ok.\n", stdout); | ||
329 | + total_error |= error; | ||
330 | + } | ||
331 | + | ||
332 | + return total_error; | ||
333 | +} |
Please
register
or
login
to post a comment