Permalink
Browse files

Add MultipartReader.

This is a wrapper around MultipartParser but has more developer-friendly
events by buffering header data and presenting it as a multimap.
  • Loading branch information...
1 parent 02d2600 commit 91a7d86662984ff97e19496c4523701e1666b70d @FooBarWidget committed Jul 6, 2010
Showing with 214 additions and 33 deletions.
  1. +1 −1 Makefile
  2. +145 −0 MultipartReader.h
  3. +68 −32 multipart.cpp
View
@@ -1,2 +1,2 @@
-multipart: multipart.cpp MultipartParser.h
+multipart: multipart.cpp MultipartParser.h MultipartReader.h
g++ -Wall multipart.cpp -o multipart
View
@@ -0,0 +1,145 @@
+#ifndef _MULTIPART_READER_H_
+#define _MULTIPART_READER_H_
+
+#include <map>
+#include <utility>
+#include "MultipartParser.h"
+
+class MultipartHeaders: public std::multimap<std::string, std::string> {
+public:
+ std::string operator[](const std::string &key) const {
+ const_iterator it = find(key);
+ if (it == end()) {
+ return std::string();
+ } else {
+ return it->second;
+ }
+ }
+};
+
+class MultipartReader {
+public:
+ typedef void (*PartBeginCallback)(const MultipartHeaders &headers, void *userData);
+ typedef void (*PartDataCallback)(const char *buffer, size_t size, void *userData);
+ typedef void (*Callback)(void *userData);
+
+private:
+ MultipartParser parser;
+ bool headersProcessed;
+ MultipartHeaders currentHeaders;
+ std::string currentHeaderName, currentHeaderValue;
+ void *userData;
+
+ void setCallbacks() {
+ parser.onPartBegin = cbPartBegin;
+ parser.onHeaderField = cbHeaderField;
+ parser.onHeaderValue = cbHeaderValue;
+ parser.onHeaderDone = cbHeaderDone;
+ parser.onHeadersDone = cbHeadersDone;
+ parser.onPartData = cbPartData;
+ parser.onPartEnd = cbPartEnd;
+ parser.onEnd = cbEnd;
+ parser.userData = this;
+ }
+
+ static void cbPartBegin(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ self->headersProcessed = false;
+ self->currentHeaders.clear();
+ self->currentHeaderName.clear();
+ self->currentHeaderValue.clear();
+ }
+
+ static void cbHeaderField(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ self->currentHeaderName.append(buffer + start, end - start);
+ }
+
+ static void cbHeaderValue(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ self->currentHeaderValue.append(buffer + start, end - start);
+ }
+
+ static void cbHeaderDone(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ self->currentHeaders.insert(std::make_pair(self->currentHeaderName,
+ self->currentHeaderValue));
+ self->currentHeaderName.clear();
+ self->currentHeaderValue.clear();
+ }
+
+ static void cbHeadersDone(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ if (self->onPartBegin != NULL) {
+ self->onPartBegin(self->currentHeaders, self->userData);
+ }
+ self->currentHeaders.clear();
+ self->currentHeaderName.clear();
+ self->currentHeaderValue.clear();
+ }
+
+ static void cbPartData(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ if (self->onPartData != NULL) {
+ self->onPartData(buffer + start, end - start, self->userData);
+ }
+ }
+
+ static void cbPartEnd(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ if (self->onPartEnd != NULL) {
+ self->onPartEnd(self->userData);
+ }
+ }
+
+ static void cbEnd(const char *buffer, size_t start, size_t end, void *userData) {
+ MultipartReader *self = (MultipartReader *) userData;
+ if (self->onEnd != NULL) {
+ self->onEnd(self->userData);
+ }
+ }
+
+public:
+ PartBeginCallback onPartBegin;
+ PartDataCallback onPartData;
+ Callback onPartEnd;
+ Callback onEnd;
+
+ MultipartReader() {
+ setCallbacks();
+ }
+
+ MultipartReader(const std::string &boundary): parser(boundary) {
+ setCallbacks();
+ }
+
+ void reset() {
+ parser.reset();
+ }
+
+ void setBoundary(const std::string &boundary) {
+ parser.setBoundary(boundary);
+ }
+
+ size_t feed(const char *buffer, size_t len) {
+ return parser.feed(buffer, len);
+ }
+
+ bool succeeded() const {
+ return parser.succeeded();
+ }
+
+ bool hasError() const {
+ return parser.hasError();
+ }
+
+ bool stopped() const {
+ return parser.stopped();
+ }
+
+ const char *getErrorMessage() const {
+ return parser.getErrorMessage();
+ }
+};
+
+#endif /* _MULTIPART_READER_H_ */
View
@@ -1,46 +1,82 @@
#include "MultipartParser.h"
+#include "MultipartReader.h"
#include <stdio.h>
+
+//#define TEST_PARSER
+
using namespace std;
-static void
-onPartBegin(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onPartBegin\n");
-}
+#ifdef TEST_PARSER
+ static void
+ onPartBegin(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onPartBegin\n");
+ }
-static void
-onHeaderField(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onHeaderField: (%s)\n", string(buffer + start, end - start).c_str());
-}
+ static void
+ onHeaderField(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onHeaderField: (%s)\n", string(buffer + start, end - start).c_str());
+ }
-static void
-onHeaderValue(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onHeaderValue: (%s)\n", string(buffer + start, end - start).c_str());
-}
+ static void
+ onHeaderValue(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onHeaderValue: (%s)\n", string(buffer + start, end - start).c_str());
+ }
-static void
-onPartData(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onPartData: (%s)\n", string(buffer + start, end - start).c_str());
-}
+ static void
+ onPartData(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onPartData: (%s)\n", string(buffer + start, end - start).c_str());
+ }
-static void
-onPartEnd(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onPartEnd\n");
-}
+ static void
+ onPartEnd(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onPartEnd\n");
+ }
-static void
-onEnd(const char *buffer, size_t start, size_t end, void *userData) {
- printf("onEnd\n");
-}
+ static void
+ onEnd(const char *buffer, size_t start, size_t end, void *userData) {
+ printf("onEnd\n");
+ }
+#else
+ void onPartBegin(const MultipartHeaders &headers, void *userData) {
+ printf("onPartBegin:\n");
+ MultipartHeaders::const_iterator it;
+ MultipartHeaders::const_iterator end = headers.end();
+ for (it = headers.begin(); it != headers.end(); it++) {
+ printf(" %s = %s\n", it->first.c_str(), it->second.c_str());
+ }
+ printf(" aaa: %s\n", headers["aaa"].c_str());
+ }
+
+ void onPartData(const char *buffer, size_t size, void *userData) {
+ printf("onPartData: (%s)\n", string(buffer, size).c_str());
+ }
+
+ void onPartEnd(void *userData) {
+ printf("onPartEnd\n");
+ }
+
+ void onEnd(void *userData) {
+ printf("onEnd\n");
+ }
+#endif
int
main() {
- MultipartParser parser("abcd");
- parser.onPartBegin = onPartBegin;
- parser.onHeaderField = onHeaderField;
- parser.onHeaderValue = onHeaderValue;
- parser.onPartData = onPartData;
- parser.onPartEnd = onPartEnd;
- parser.onEnd = onEnd;
+ #ifdef TEST_PARSER
+ MultipartParser parser("abcd");
+ parser.onPartBegin = onPartBegin;
+ parser.onHeaderField = onHeaderField;
+ parser.onHeaderValue = onHeaderValue;
+ parser.onPartData = onPartData;
+ parser.onPartEnd = onPartEnd;
+ parser.onEnd = onEnd;
+ #else
+ MultipartReader parser("abcd");
+ parser.onPartBegin = onPartBegin;
+ parser.onPartData = onPartData;
+ parser.onPartEnd = onPartEnd;
+ parser.onEnd = onEnd;
+ #endif
while (!parser.stopped() && !feof(stdin)) {
char buf[100];
@@ -49,7 +85,7 @@ main() {
do {
size_t ret = parser.feed(buf + fed, len - fed);
fed += ret;
- printf("accepted %d bytes\n", (int) ret);
+ //printf("accepted %d bytes\n", (int) ret);
} while (fed < len && !parser.stopped());
}
printf("%s\n", parser.getErrorMessage());

0 comments on commit 91a7d86

Please sign in to comment.