X-Git-Url: https://git.ladys.computer/CGirls/blobdiff_plain/f5006884a1f4f37bc3c27ab1f3b882d2b36cd052..refs/heads/current:/request.c?ds=inline

diff --git a/request.c b/request.c
index 25f9625..f9fa453 100644
--- a/request.c
+++ b/request.c
@@ -4,23 +4,46 @@
 #include "aa.h"
 #include "request.h"
 
-void cgirls_freereq (cgirls_req req) {
-	free(req.cgirls_project);
-	free(req.cgirls_id);
-	if (req.cgirls_subpath) {
+static char const*const cgirls_mtypes[] = {
+	[cgirls_mtype_txt] = ".txt",
+	[cgirls_mtype_htm] = ".htm",
+	[cgirls_mtype_xml] = ".xml",
+	[cgirls_mtype_rdf] = ".rdf",
+};
+constexpr size_t cgirls_n·mtypes =
+	sizeof(cgirls_mtypes) / sizeof(char*);
+
+static char const*const cgirls_vbs[] = {
+	[cgirls_vb_unknown] = "unknown",
+	[cgirls_vb_index] = "index",
+	[cgirls_vb_show] = "show",
+};
+constexpr size_t cgirls_n·vbs =
+	sizeof(cgirls_vbs) / sizeof(char*);
+static cgirls_vb const cgirls_parsable·vbs[] = {
+	cgirls_vb_index,
+	cgirls_vb_show,
+};
+constexpr size_t cgirls_n·parsable·vbs =
+	sizeof(cgirls_parsable·vbs) / sizeof(cgirls_vb);
+
+void cgirls_req·free (cgirls_req req) {
+	free(req.project);
+	free(req.id_THIS_WILL_CHANGE);
+	if (req.subpath) {
 		size_t i = 0;
-		char* c = req.cgirls_subpath[i];
+		char* c = req.subpath[i];
 		while (c) {
 			free(c);
-			c = req.cgirls_subpath[++i];
+			c = req.subpath[++i];
 		}
-		free(req.cgirls_subpath);
+		free(req.subpath);
 	}
-	free(req.cgirls_baseid);
-	free(req.cgirls_status.cgirls_message);
+	free(req.baseid_THIS_WILL_CHANGE);
+	free(req.status.message);
 }
 
-char* cgirls_gobblepath(char const* ndx[1], char const*const end[1]) {
+static char* cgirls_gobble·path(char const* ndx[1], char const*const end[1]) {
 	char const* eor = strchr(ndx[0], '/');
 	char* result = nullptr;
 	if (!eor) {
@@ -37,20 +60,20 @@ char* cgirls_gobblepath(char const* ndx[1], char const*const end[1]) {
 	return result;
 }
 
-cgirls_req cgirls_path2req(char const*const pathinfo) {
+cgirls_req cgirls_path·to·req(char const*const pathinfo) {
 	assert(pathinfo != nullptr);
 
 	// Initialize the result.
 	cgirls_req req = {
-		.cgirls_action = cgirls_vb_unknown,
-		.cgirls_type = cgirls_mtype_any,
-		.cgirls_project = nullptr,
-		.cgirls_id = nullptr,
-		.cgirls_subpath = nullptr,
-		.cgirls_baseid = nullptr,
-		.cgirls_status = {
-			.cgirls_code = 200,
-			.cgirls_message = nullptr,
+		.verb = cgirls_vb_unknown,
+		.mtype = cgirls_mtype_any,
+		.project = nullptr,
+		.id_THIS_WILL_CHANGE = nullptr,
+		.subpath = nullptr,
+		.baseid_THIS_WILL_CHANGE = nullptr,
+		.status = {
+			.code = 200,
+			.message = nullptr,
 		},
 	};
 
@@ -64,7 +87,7 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 	// the project of the request. If there is no first slash, the
 	// project extends to the end of the string. An empty string is
 	// equivalent to having no project.
-	req.cgirls_project = cgirls_gobblepath(ndx, end);
+	req.project = cgirls_gobble·path(ndx, end);
 
 	// The portion of the pathinfo which follows the first slash but
 	// precedes the second gives the action of the request. If there is
@@ -80,7 +103,7 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 	// constants). If a verb is present, but unrecognized, it is assigned
 	// the special value `cgirls_vb_unknown´, which should generally be
 	// interpreted as an error.
-	char* soa = cgirls_gobblepath(ndx, end);
+	char* soa = cgirls_gobble·path(ndx, end);
 	if (soa) {
 		char*const eoa = strchr(soa, 0);
 		if (eoa - soa > 4) {
@@ -88,10 +111,10 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 			// present (it will be the last 4). Then set the first character
 			// of the extension to null, effectively trimming the verb.
 			char* ext = eoa - 4;
-			for (size_t i = 0; i < cgirls_n·mtypes; ++i) {
-				cgirls_mtype ixt = cgirls_mtypes[i];
-				if (strncmp(ext, ixt, 4) == 0) {
-					req.cgirls_type = ixt;
+			for (cgirls_mtype i = 0; i < cgirls_n·mtypes; ++i) {
+				char const*const ixt = cgirls_mtypes[i];
+				if (ixt && strncmp(ext, ixt, 4) == 0) {
+					req.mtype = i;
 					ext[0] = 0;
 					break;
 				}
@@ -99,14 +122,15 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 		}
 		for (size_t i = 0; i < cgirls_n·parsable·vbs; ++i) {
 			cgirls_vb ivb = cgirls_parsable·vbs[i];
-			if (strcmp(soa, ivb) == 0) {
-				req.cgirls_action = ivb;
+			char const*const svb = cgirls_vbs[ivb];
+			if (svb && strcmp(soa, svb) == 0) {
+				req.verb = ivb;
 				break;
 			}
 		}
 		free(soa);
 	} else if (ndx[0] == end[0]) {
-		req.cgirls_action = cgirls_vb_index;
+		req.verb = cgirls_vb_index;
 	}
 
 	// The portion of the pathinfo which follows the second slash but
@@ -115,7 +139,7 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 	// string. A single identifier may be given, or two identifiers may
 	// be given separated by two periods. An empty string is equivalent
 	// to no identifier.
-	char* idid = cgirls_gobblepath(ndx, end);
+	char* idid = cgirls_gobble·path(ndx, end);
 	if (idid) {
 		// If the identifier string contains two successive dots, the base
 		// and target identifiers must be extracted and the original
@@ -126,24 +150,27 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 			char const*const eods = dots + 2;
 			char const*const eoii = strchr(idid, 0);
 			if (dots > idid) {
-				req.cgirls_baseid = strndup(idid, dots - idid);
+				req.baseid_THIS_WILL_CHANGE = strndup(idid, dots - idid);
 			}
 			if (eods < eoii) {
-				req.cgirls_id = strndup(eods, eoii - eods);
+				req.id_THIS_WILL_CHANGE = strndup(eods, eoii - eods);
 			}
 			free(idid);
 		} else {
-			req.cgirls_id = idid;
+			req.id_THIS_WILL_CHANGE = idid;
 		}
 	}
 
 	// The portion of the pathinfo which follows the third slash is the
 	// subpath of the request. An empty sting is equivalent to having no
 	// subpath. Trailing and successive slashes are dropped.
-	char const* sos = ndx[0];
 	char const* sep = nullptr;
 	size_t n·s = 0;
-	while (end[0] > sos) {
+	for (
+		char const* sos = ndx[0];
+		sos < end[0];
+		sos = (end[0] > sep ? sep + 1 : end[0])
+	) {
 		// Count the number of segments in the pathinfo so that the correct
 		// amount of space can be allocated.
 		sep = strchr(sos, '/');
@@ -153,70 +180,74 @@ cgirls_req cgirls_path2req(char const*const pathinfo) {
 		if (sep > sos) {
 			++n·s;
 		}
-		if (end[0] > sep) {
-			sos = sep + 1;
-		} else {
-			sos = end[0];
-		}
-	}
-	req.cgirls_subpath = calloc(n·s + 1, sizeof(char*));
-	if (!req.cgirls_subpath) {
-		return req;
 	}
-	size_t i·s = 0;
-	while (end[0] > ndx[0]) {
-		// Add the segments to the newly allocated array.
-		sep = strchr(ndx[0], '/');
-		if (!sep) {
-			sep = end[0];
-		}
-		if (sep > ndx[0]) {
-			req.cgirls_subpath[i·s++] = strndup(ndx[0], sep - ndx[0]);
+	if (n·s > 0) {
+		req.subpath = calloc(n·s + 1, sizeof(char*));
+		if (!req.subpath) {
+			return req;
 		}
-		if (end[0] > sep) {
-			ndx[0] = sep + 1;
-		} else {
-			ndx[0] = end[0];
+		for (
+			size_t i·s = 0;
+			i·s < n·s;
+			ndx[0] = (end[0] > sep ? sep + 1 : end[0])
+		) {
+			// Add the segments to the newly allocated array.
+			sep = strchr(ndx[0], '/');
+			if (!sep) {
+				sep = end[0];
+			}
+			if (sep > ndx[0]) {
+				req.subpath[i·s++] = strndup(ndx[0], sep - ndx[0]);
+			}
 		}
+		req.subpath[n·s] = nullptr;
 	}
-	assert(i·s == n·s);
-	req.cgirls_subpath[i·s] = nullptr;
 
 	// Return the result.
 	return req;
 }
 
-char* cgirls_req2path(cgirls_req req) {
-	cgirls_vb vb = cgirls_vb_index;
-	bool has·ids = req.cgirls_baseid || req.cgirls_id;
-	bool has·type = req.cgirls_type;
-	bool has·subpath = req.cgirls_subpath && req.cgirls_subpath[0];
+char* cgirls_req·to·path(cgirls_req req) {
+	char const* vb = nullptr;
+	char const* mtype = nullptr;
+	bool has·ids = req.baseid_THIS_WILL_CHANGE || req.id_THIS_WILL_CHANGE;
+	bool has·subpath = req.subpath && req.subpath[0];
 	size_t length = 0;
 
+	// Get the string corresponding to the verb. Do not assume that the
+	// verb is welbehaved (actually corresponding to an enumeration
+	// constant).
+	if (req.verb < cgirls_n·vbs) {
+		vb = cgirls_vbs[req.verb];
+	}
+	if (!vb) {
+		vb = cgirls_vbs[cgirls_vb_unknown];
+	}
+
+	// Get the string corresponding to the mediatype, or `nullptr´. Do
+	// not assume that the verb is welbehaved (actually corresponding to
+	// an enumeration constant).
+	if (req.mtype < cgirls_n·mtypes) {
+		mtype = cgirls_mtypes[req.mtype];
+	}
+
 	// Get the length of the various parts. This length includes a
 	// trailing slash, but in practice this will be replaced by the final
 	// null byte.
-	if (req.cgirls_project) {
-		length += strlen(req.cgirls_project) + 1;
-		for (size_t i = 0; i < cgirls_n·vbs; ++i) {
-			cgirls_vb ivb = cgirls_vbs[i];
-			if (req.cgirls_action == ivb) {
-				vb = ivb;
-				break;
-			}
-		}
-		if (vb != cgirls_vb_index || has·type || has·ids || has·subpath) {
+	if (req.project) {
+		length += strlen(req.project) + 1;
+		if (req.verb != cgirls_vb_index || mtype || has·ids || has·subpath) {
 			length += strlen(vb) + 1;
 		}
-		if (has·type) {
-			length += strlen(req.cgirls_type);
+		if (mtype) {
+			length += strlen(mtype);
 		}
 		if (has·ids) {
-			if (req.cgirls_baseid) {
-				length += strlen(req.cgirls_baseid) + 2;
+			if (req.baseid_THIS_WILL_CHANGE) {
+				length += strlen(req.baseid_THIS_WILL_CHANGE) + 2;
 			}
-			if (req.cgirls_id) {
-				length += strlen(req.cgirls_id);
+			if (req.id_THIS_WILL_CHANGE) {
+				length += strlen(req.id_THIS_WILL_CHANGE);
 			}
 			length += 1;
 		} else if (has·subpath) {
@@ -224,10 +255,10 @@ char* cgirls_req2path(cgirls_req req) {
 		}
 		if (has·subpath) {
 			size_t i = 0;
-			char* c = req.cgirls_subpath[i];
+			char* c = req.subpath[i];
 			while (c) {
 				length += strlen(c) + 1;
-				c = req.cgirls_subpath[++i];
+				c = req.subpath[++i];
 			}
 		}
 	} else {
@@ -241,23 +272,23 @@ char* cgirls_req2path(cgirls_req req) {
 		return nullptr;
 	}
 	char* cursor = result;
-	if (req.cgirls_project) {
-		cursor = stpcpy(cursor, req.cgirls_project);
+	if (req.project) {
+		cursor = stpcpy(cursor, req.project);
 		(cursor++)[0] = '/';
-		if (vb != cgirls_vb_index || has·type || has·ids || has·subpath) {
+		if (req.verb != cgirls_vb_index || mtype || has·ids || has·subpath) {
 			cursor = stpcpy(cursor, vb);
-			if (has·type) {
-				cursor = stpcpy(cursor, req.cgirls_type);
+			if (mtype) {
+				cursor = stpcpy(cursor, mtype);
 			}
 			(cursor++)[0] = '/';
 		}
 		if (has·ids) {
-			if (req.cgirls_baseid) {
-				cursor = stpcpy(cursor, req.cgirls_baseid);
+			if (req.baseid_THIS_WILL_CHANGE) {
+				cursor = stpcpy(cursor, req.baseid_THIS_WILL_CHANGE);
 				cursor = stpcpy(cursor, "..");
 			}
-			if (req.cgirls_id) {
-				cursor = stpcpy(cursor, req.cgirls_id);
+			if (req.id_THIS_WILL_CHANGE) {
+				cursor = stpcpy(cursor, req.id_THIS_WILL_CHANGE);
 			}
 			(cursor++)[0] = '/';
 		} else if (has·subpath) {
@@ -265,10 +296,10 @@ char* cgirls_req2path(cgirls_req req) {
 		}
 		if (has·subpath) {
 			size_t i = 0;
-			char* c = req.cgirls_subpath[i];
+			char* c = req.subpath[i];
 			while (c) {
 				cursor = stpcpy(cursor, c);
-				c = req.cgirls_subpath[++i];
+				c = req.subpath[++i];
 				(cursor++)[0] = '/';
 			}
 		}