summaryrefslogtreecommitdiff
path: root/pikul.c
diff options
context:
space:
mode:
authorꦌꦫꦶꦏ꧀ꦦꦿꦧꦮꦑꦩꦭ꧀ <erik@darapsa.co.id>2021-07-19 17:21:52 +0800
committerꦌꦫꦶꦏ꧀ꦦꦿꦧꦮꦑꦩꦭ꧀ <erik@darapsa.co.id>2021-07-19 17:21:52 +0800
commit74028cd953f94cfd2d0a1f635ed07e25d94c6802 (patch)
treebb40bcf3f0889e3a5ea4d694996171ad4742e948 /pikul.c
parentb24e0bdf48e6e4ec2cab90bec1f4a03d26cdfd50 (diff)
Merge the inline functions to pikul.c
So things are more straight forward, and this makes code more reusable.
Diffstat (limited to 'pikul.c')
-rw-r--r--pikul.c175
1 files changed, 125 insertions, 50 deletions
diff --git a/pikul.c b/pikul.c
index 11bcdf3..8a6b3c1 100644
--- a/pikul.c
+++ b/pikul.c
@@ -1,74 +1,154 @@
-#include "common.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+#include <string.h>
+#include <json.h>
+#include "private.h"
CURL *curl;
json_tokener *tokener;
struct shipping shipping;
-void headers(const char *[], char *[]);
-void handle(enum type, const char *, size_t, const char *[], const char *[], const char *[], void *);
-
-void anteraja_init(char *[]);
-void anteraja_services(const char *, const char *, double, char **, char **);
-size_t anteraja_services_handle(const char *, size_t, size_t, struct pikul_services **);
+const char **anteraja_init(char *[]);
+const char **anteraja_services(const char *, const char *, double);
void anteraja_order(const char *, const char *, const char *, const char *, const char *, const char *,
const char *, const char *, const char *, const char *, const char *, const char *, int,
- char **[], double, char **, char **);
-size_t anteraja_order_handle(const char *, size_t size, size_t nmemb, char **);
+ char **[], double);
void anteraja_cleanup();
+static void recurse(struct json_object *outer, const char *trail[], struct json_object **last)
+{
+ struct json_object *inner = NULL;
+ json_object_object_get_ex(outer, *trail, &inner);
+ if (*++trail)
+ recurse(inner, trail, last);
+ else
+ *last = inner;
+}
+
+static size_t handle(char *contents, size_t size, size_t nmemb, void *data)
+{
+ size_t realsize = size * nmemb;
+#ifdef DEBUG
+ contents[realsize] = '\0';
+ fprintf(stderr, "%s\n", contents);
+#endif
+ json_object *response = json_tokener_parse_ex(tokener, contents, realsize);
+ enum json_tokener_error error = json_tokener_get_error(tokener);
+ if (!response) {
+ if (error == json_tokener_continue)
+ return realsize;
+ else {
+ json_tokener_reset(tokener);
+ return realsize;
+ }
+ } else if (!json_object_is_type(response, json_type_object) || error != json_tokener_success)
+ return realsize;
+ struct json_object *status = NULL;
+ recurse(response, shipping.status_trail, &status);
+ if (json_object_get_int(status) != 200)
+ return realsize;
+ switch (shipping.mode) {
+ case SERVICES:
+ ;
+ struct json_object *array = NULL;
+ recurse(response, shipping.trail, &array);
+ size_t length = json_object_array_length(array);
+ shipping.data = malloc(sizeof(struct pikul_services)
+ + sizeof(struct pikul_service *[length]));
+ struct pikul_services *services = (struct pikul_services *)shipping.data;
+ services->length = length;
+ const char **attributes = (const char **)data;
+ enum { CODE, NAME, ETD, COST };
+ for (size_t i = 0; i < length; i++) {
+ services->list[i] = malloc(sizeof(struct pikul_service));
+ struct pikul_service *service = services->list[i];
+ json_object *object = json_object_array_get_idx(array, i);
+ struct json_object_iterator iterator = json_object_iter_begin(object);
+ struct json_object_iterator iterator_end = json_object_iter_end(object);
+ while (!json_object_iter_equal(&iterator, &iterator_end)) {
+ const char *name = json_object_iter_peek_name(&iterator);
+ json_object *value = json_object_iter_peek_value(&iterator);
+ if (!strcmp(name, attributes[COST]))
+ service->cost = json_object_get_double(value);
+ else {
+ int len = json_object_get_string_len(value);
+ if (len) {
+ char *string = malloc(len + 1);
+ strcpy(string, json_object_get_string(value));
+ if (!strcmp(name, attributes[CODE]))
+ service->code = string;
+ else if (!strcmp(name, attributes[NAME]))
+ service->name = string;
+ else if (!strcmp(name, attributes[ETD]))
+ service->etd = string;
+ }
+ }
+ json_object_iter_next(&iterator);
+ }
+ }
+ break;
+ case ORDER:
+ ;
+ struct json_object *string = NULL;
+ recurse(response, shipping.trail, &string);
+ shipping.data = malloc(json_object_get_string_len(string) + 1);
+ strcpy(shipping.data, json_object_get_string(string));
+ break;
+ default:
+ break;
+ }
+ return realsize;
+}
+
void pikul_init(enum pikul_company company, char *provisions[])
{
curl_global_init(CURL_GLOBAL_SSL);
curl = curl_easy_init();
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle);
#ifdef DEBUG
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#endif
shipping.company = company;
+ shipping.headers = NULL;
+ const char **fields;
switch (company) {
case PIKUL_ANTERAJA:
- anteraja_init(provisions);
+ fields = anteraja_init(provisions);
break;
default:
break;
}
+ while (*fields) {
+ char header[strlen(*fields) + strlen(":") + strlen(*provisions) + 1];
+ sprintf(header, "%s:%s", *fields++, *provisions++);
+ shipping.headers = curl_slist_append(shipping.headers, header);
+ }
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, shipping.headers);
tokener = json_tokener_new();
}
-void recurse(struct json_object *outer, const char *trail[], struct json_object **last)
-{
- struct json_object *inner = NULL;
- json_object_object_get_ex(outer, *trail, &inner);
- if (*++trail)
- recurse(inner, trail, last);
- else
- *last = inner;
-}
-
struct pikul_services *pikul_services(const char *origin, const char *destination, double weight)
{
- struct pikul_services *services = NULL;
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &services);
- char *url;
- char *post = NULL;
- size_t (*handler)(const char *, size_t, size_t, struct pikul_services **);
+ shipping.post = NULL;
+ const char **attributes;
switch (shipping.company) {
case PIKUL_ANTERAJA:
- anteraja_services(origin, destination, weight, &url, &post);
- handler = anteraja_services_handle;
+ attributes = anteraja_services(origin, destination, weight);
break;
default:
break;
}
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handler);
- if (post)
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
+ curl_easy_setopt(curl, CURLOPT_URL, shipping.url);
+ if (shipping.post)
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, shipping.post);
+ shipping.mode = SERVICES;
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, attributes);
curl_easy_perform(curl);
- if (post)
- free(post);
- free(url);
- return services;
+ if (shipping.post)
+ free(shipping.post);
+ free(shipping.url);
+ return (struct pikul_services *)shipping.data;
}
static inline void free_service(struct pikul_service *service)
@@ -117,31 +197,26 @@ char *pikul_order(const char *order_number, const char *service, const char *sen
const char *destination, const char *receiver_address, const char *receiver_postal,
int nitems, char **items[], double subtotal)
{
- char *tracking_number = NULL;
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &tracking_number);
- char *url;
- char *post = NULL;
- size_t (*handler)(const char *, size_t, size_t, char **);
+ shipping.post = NULL;
switch (shipping.company) {
case PIKUL_ANTERAJA:
anteraja_order(order_number, service, sender_name, sender_phone, origin,
sender_address, sender_postal, receiver_name, receiver_phone,
destination, receiver_address, receiver_postal, nitems, items,
- subtotal, &url, &post);
- handler = anteraja_order_handle;
+ subtotal);
break;
default:
break;
}
- curl_easy_setopt(curl, CURLOPT_URL, url);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handler);
- if (post)
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
+ curl_easy_setopt(curl, CURLOPT_URL, shipping.url);
+ if (shipping.post)
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, shipping.post);
+ shipping.mode = ORDER;
curl_easy_perform(curl);
- if (post)
- free(post);
- free(url);
- return tracking_number;
+ if (shipping.post)
+ free(shipping.post);
+ free(shipping.url);
+ return (char *)shipping.data;
}
void pikul_cleanup()