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 | 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 | 9 | 2012-02-12 04:05:38 +0100 Georg Hopp |
| 6 | 10 | ... | ... |
| ... | ... | @@ -42,28 +42,44 @@ |
| 42 | 42 | * @TODO: actually i use gcc feature ## for variadoc... think about |
| 43 | 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 | 61 | _CALL(object, _iface, method, ##__VA_ARGS__); \ |
| 60 | - iface->method(object, ##__VA_ARGS__); \ | |
| 62 | + iface->method(object, ##__VA_ARGS__); \ | |
| 61 | 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 | 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 | 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 | 2 | #define __HTTP_REQUEST_H__ |
| 3 | 3 | |
| 4 | 4 | #include "class.h" |
| 5 | -#include "http/header.h" | |
| 5 | +#include "http/message.h" | |
| 6 | 6 | |
| 7 | 7 | CLASS(HttpRequest) { |
| 8 | + EXTENDS(HttpMessage); | |
| 9 | + | |
| 8 | 10 | char * method; |
| 9 | 11 | char * uri; |
| 10 | - char * version; | |
| 11 | - | |
| 12 | - HttpHeader header; | |
| 13 | - | |
| 14 | - char * body; | |
| 15 | - int nbody; | |
| 16 | 12 | }; |
| 17 | 13 | |
| 18 | 14 | char httpRequestHasKeepAlive(HttpRequest); | ... | ... |
| ... | ... | @@ -7,6 +7,9 @@ |
| 7 | 7 | |
| 8 | 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 | 14 | typedef enum e_HttpRequestState { |
| 12 | 15 | HTTP_REQUEST_GARBAGE=0, |
| ... | ... | @@ -32,6 +35,8 @@ CLASS(HttpRequestParser) { |
| 32 | 35 | |
| 33 | 36 | size_t httpRequestParserRead(HttpRequestParser, int); |
| 34 | 37 | void httpRequestParserParse(HttpRequestParser); |
| 38 | +void httpRequestParserGetBody(HttpRequestParser); | |
| 39 | + | |
| 35 | 40 | void httpRequestParserGetRequestLine(HttpRequest, char *); |
| 36 | 41 | void httpRequestParserGetHeader(HttpRequest, char *); |
| 37 | 42 | ... | ... |
| ... | ... | @@ -4,18 +4,14 @@ |
| 4 | 4 | #include <sys/types.h> |
| 5 | 5 | |
| 6 | 6 | #include "class.h" |
| 7 | -#include "http/header.h" | |
| 7 | +#include "http/message.h" | |
| 8 | 8 | |
| 9 | 9 | |
| 10 | 10 | CLASS(HttpResponse) { |
| 11 | - char * version; | |
| 11 | + EXTENDS(HttpMessage); | |
| 12 | + | |
| 12 | 13 | unsigned int status; |
| 13 | 14 | char * reason; |
| 14 | - | |
| 15 | - HttpHeader header; | |
| 16 | - | |
| 17 | - char * body; | |
| 18 | - int nbody; | |
| 19 | 15 | }; |
| 20 | 16 | |
| 21 | 17 | HttpResponse httpResponse404(); | ... | ... |
include/http/worker.h
0 → 100644
| ... | ... | @@ -6,6 +6,7 @@ CLASS = class.c interface.c |
| 6 | 6 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
| 7 | 7 | SERVER = server.c server/run.c server/close_conn.c |
| 8 | 8 | LOGGER = logger.c logger/stderr.c logger/syslog.c |
| 9 | +MSG = http/message.c | |
| 9 | 10 | REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c |
| 10 | 11 | RESP = http/response.c http/response/404.c http/response/size_get.c \ |
| 11 | 12 | http/response/to_string.c |
| ... | ... | @@ -13,7 +14,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \ |
| 13 | 14 | http/header/size_get.c http/header/to_string.c |
| 14 | 15 | PARSER = http/request/parser.c http/request/parser/get_header.c \ |
| 15 | 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 | 20 | AM_CFLAGS = -Wall -I ../include/ |
| ... | ... | @@ -21,6 +22,6 @@ AM_CFLAGS = -Wall -I ../include/ |
| 21 | 22 | bin_PROGRAMS = testserver |
| 22 | 23 | |
| 23 | 24 | testserver_SOURCES = testserver.c \ |
| 24 | - $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(REQ) \ | |
| 25 | + $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ | |
| 25 | 26 | $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c |
| 26 | 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 | 1 | #include <stdlib.h> |
| 6 | 2 | #include <stdarg.h> |
| 7 | -#include <search.h> | |
| 8 | 3 | |
| 9 | 4 | #include "class.h" |
| 10 | 5 | #include "interface/class.h" |
| 11 | 6 | |
| 12 | 7 | #include "http/request.h" |
| 8 | +#include "message/helper.c" | |
| 13 | 9 | |
| 14 | 10 | |
| 15 | 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 | 12 | void |
| 35 | 13 | ctor(void * _this, va_list * params) {} |
| 36 | 14 | |
| ... | ... | @@ -40,21 +18,13 @@ dtor(void * _this) |
| 40 | 18 | { |
| 41 | 19 | HttpRequest this = _this; |
| 42 | 20 | |
| 43 | - _free((void **)&(this->version)); | |
| 44 | 21 | _free((void **)&(this->uri)); |
| 45 | 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 | 27 | INIT_IFACE(Class, ctor, dtor, NULL); |
| 58 | -CREATE_CLASS(HttpRequest, NULL, IFACE(Class)); | |
| 28 | +CREATE_CLASS(HttpRequest, HttpMessage, IFACE(Class)); | |
| 59 | 29 | |
| 60 | 30 | // vim: set ts=4 sw=4: | ... | ... |
| 1 | 1 | #include <string.h> |
| 2 | 2 | #include <ctype.h> |
| 3 | 3 | |
| 4 | +#include "http/message.h" | |
| 4 | 5 | #include "http/request.h" |
| 5 | 6 | #include "http/header.h" |
| 6 | 7 | |
| ... | ... | @@ -8,10 +9,11 @@ |
| 8 | 9 | char |
| 9 | 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 | 18 | if (NULL == header) { |
| 17 | 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 | 5 | #include "class.h" |
| 6 | 6 | #include "interface/class.h" |
| 7 | 7 | #include "http/header.h" |
| 8 | -#include "http/request.h" | |
| 8 | +#include "http/message.h" | |
| 9 | 9 | |
| 10 | 10 | void |
| 11 | -httpRequestParserGetHeader(HttpRequest request, char * line) | |
| 11 | +httpRequestParserGetHeader(HttpMessage request, char * line) | |
| 12 | 12 | { |
| 13 | 13 | char * name = line; |
| 14 | 14 | char * value = strchr(line, ':'); | ... | ... |
| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | void |
| 8 | 8 | httpRequestParserGetRequestLine(HttpRequest request, char * line) |
| 9 | 9 | { |
| 10 | + HttpMessage message = (HttpMessage)request; | |
| 10 | 11 | char * method, * uri, * version; |
| 11 | 12 | |
| 12 | 13 | method = line; |
| ... | ... | @@ -23,8 +24,8 @@ httpRequestParserGetRequestLine(HttpRequest request, char * line) |
| 23 | 24 | strcpy(request->method, method); |
| 24 | 25 | request->uri = malloc(strlen(uri) + 1); |
| 25 | 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 | 31 | // vim: set ts=4 sw=4: | ... | ... |
| ... | ... | @@ -7,10 +7,6 @@ |
| 7 | 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 | 10 | static |
| 15 | 11 | inline |
| 16 | 12 | char * |
| ... | ... | @@ -79,33 +75,7 @@ httpRequestParserParse(HttpRequestParser this) |
| 79 | 75 | break; |
| 80 | 76 | |
| 81 | 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 | 79 | break; |
| 110 | 80 | |
| 111 | 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 | 1 | #include <stdlib.h> |
| 7 | 2 | #include <stdarg.h> |
| 8 | 3 | |
| ... | ... | @@ -10,60 +5,38 @@ |
| 10 | 5 | #include "interface/class.h" |
| 11 | 6 | |
| 12 | 7 | #include "http/response.h" |
| 8 | +#include "message/helper.c" | |
| 13 | 9 | |
| 14 | 10 | |
| 15 | 11 | static |
| 16 | 12 | void |
| 17 | -_free(void ** data) | |
| 18 | -{ | |
| 19 | - if (NULL != *data) { | |
| 20 | - free(*data); | |
| 21 | - } | |
| 22 | -} | |
| 23 | - | |
| 24 | -static | |
| 25 | -void | |
| 26 | 13 | ctor(void * _this, va_list * params) |
| 27 | 14 | { |
| 28 | - char * version; | |
| 15 | + HttpResponse this = _this; | |
| 16 | + char * status; | |
| 29 | 17 | char * reason; |
| 30 | 18 | |
| 31 | - HttpResponse this = _this; | |
| 19 | + PARENTCALL(_this, Class, ctor, params); | |
| 32 | 20 | |
| 33 | - version = va_arg(* params, char *); | |
| 34 | 21 | this->status = va_arg(* params, unsigned int); |
| 35 | 22 | reason = va_arg(* params, char *); |
| 36 | 23 | |
| 37 | - this->version = calloc(1, strlen(version)+1); | |
| 38 | - strcpy(this->version, version); | |
| 39 | - | |
| 40 | 24 | this->reason = calloc(1, strlen(reason)+1); |
| 41 | 25 | strcpy(this->reason, reason); |
| 42 | 26 | } |
| 43 | 27 | |
| 44 | 28 | static |
| 45 | -inline | |
| 46 | -void | |
| 47 | -tDelete(void * node) | |
| 48 | -{ | |
| 49 | - delete(&node); | |
| 50 | -} | |
| 51 | - | |
| 52 | -static | |
| 53 | 29 | void |
| 54 | 30 | dtor(void * _this) |
| 55 | 31 | { |
| 56 | 32 | HttpResponse this = _this; |
| 57 | 33 | |
| 58 | - _free((void **)&(this->version)); | |
| 59 | 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 | 39 | INIT_IFACE(Class, ctor, dtor, NULL); |
| 67 | -CREATE_CLASS(HttpResponse, NULL, IFACE(Class)); | |
| 40 | +CREATE_CLASS(HttpResponse, HttpMessage, IFACE(Class)); | |
| 68 | 41 | |
| 69 | 42 | // vim: set ts=4 sw=4: | ... | ... |
| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | #include "interface/class.h" |
| 8 | 8 | |
| 9 | 9 | #include "http/response.h" |
| 10 | +#include "http/message.h" | |
| 10 | 11 | #include "http/header.h" |
| 11 | 12 | |
| 12 | 13 | |
| ... | ... | @@ -26,26 +27,29 @@ httpResponse404() |
| 26 | 27 | struct tm * tmp; |
| 27 | 28 | char buffer[200]; |
| 28 | 29 | HttpResponse response; |
| 30 | + HttpMessage message; | |
| 29 | 31 | |
| 30 | 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 | 36 | new(HttpHeader, "Content-Type", "text/html")); |
| 34 | - httpHeaderAdd(&(response->header), | |
| 37 | + httpHeaderAdd(&(message->header), | |
| 35 | 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 | 47 | new(HttpHeader, "Content-Length", buffer)); |
| 44 | 48 | |
| 45 | 49 | t = time(NULL); |
| 46 | 50 | tmp = localtime(&t); |
| 47 | 51 | strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp); |
| 48 | - httpHeaderAdd(&(response->header), | |
| 52 | + httpHeaderAdd(&(message->header), | |
| 49 | 53 | new(HttpHeader, "Date", buffer)); |
| 50 | 54 | |
| 51 | 55 | return response; | ... | ... |
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | #include <string.h> |
| 3 | 3 | #include <sys/types.h> |
| 4 | 4 | |
| 5 | +#include "http/message.h" | |
| 5 | 6 | #include "http/response.h" |
| 6 | 7 | #include "http/header.h" |
| 7 | 8 | |
| ... | ... | @@ -20,16 +21,21 @@ addHeaderSize(const void * node, const VISIT which, const int depth) |
| 20 | 21 | size_t |
| 21 | 22 | httpResponseSizeGet(HttpResponse response) |
| 22 | 23 | { |
| 24 | + HttpMessage message = (HttpMessage)response; | |
| 25 | + | |
| 23 | 26 | size = 0; |
| 24 | 27 | |
| 25 | - size += strlen(response->version) + 1; | |
| 28 | + size += strlen(message->version) + 1; | |
| 26 | 29 | size += 4; // for status |
| 27 | 30 | size += strlen(response->reason) + 2; |
| 28 | 31 | |
| 29 | - twalk(response->header, addHeaderSize); | |
| 32 | + twalk(message->header, addHeaderSize); | |
| 30 | 33 | |
| 31 | 34 | size += 2; |
| 32 | - size += response->nbody; | |
| 35 | + | |
| 36 | + if (HTTP_MESSAGE_BUFFERED == message->type) { | |
| 37 | + size += message->nbody; | |
| 38 | + } | |
| 33 | 39 | |
| 34 | 40 | return size; |
| 35 | 41 | } | ... | ... |
| ... | ... | @@ -20,13 +20,14 @@ addHeaderString(const void * node, const VISIT which, const int depth) |
| 20 | 20 | char * |
| 21 | 21 | httpResponseToString(HttpResponse response, char * _string) |
| 22 | 22 | { |
| 23 | - char status[4]; | |
| 23 | + HttpMessage message = (HttpMessage)response; | |
| 24 | + char status[4]; | |
| 24 | 25 | |
| 25 | 26 | string = _string; |
| 26 | 27 | |
| 27 | 28 | snprintf(status, 4, "%d", response->status); |
| 28 | 29 | |
| 29 | - strcpy(string, response->version); | |
| 30 | + strcpy(string, message->version); | |
| 30 | 31 | string += strlen(string); |
| 31 | 32 | |
| 32 | 33 | *string++ = ' '; |
| ... | ... | @@ -42,12 +43,14 @@ httpResponseToString(HttpResponse response, char * _string) |
| 42 | 43 | *string++ = '\r'; |
| 43 | 44 | *string++ = '\n'; |
| 44 | 45 | |
| 45 | - twalk(response->header, addHeaderString); | |
| 46 | + twalk(message->header, addHeaderString); | |
| 46 | 47 | |
| 47 | 48 | *string++ = '\r'; |
| 48 | 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 | 55 | return string; |
| 53 | 56 | } | ... | ... |
| ... | ... | @@ -117,13 +117,13 @@ serverRun(Server this) |
| 117 | 117 | if (httpRequestHasKeepAlive(queue->requests[j])) { |
| 118 | 118 | (this->conns)[fd].keep_alive = 1; |
| 119 | 119 | httpHeaderAdd( |
| 120 | - &(response->header), | |
| 120 | + &(((HttpMessage)response)->header), | |
| 121 | 121 | new(HttpHeader, "Connection", "Keep-Alive")); |
| 122 | 122 | } |
| 123 | 123 | else { |
| 124 | 124 | (this->conns)[fd].keep_alive = 0; |
| 125 | 125 | httpHeaderAdd( |
| 126 | - &(response->header), | |
| 126 | + &(((HttpMessage)response)->header), | |
| 127 | 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