diff --git a/include/mastodont.h b/include/mastodont.h index fddcebd..7afb9f5 100644 --- a/include/mastodont.h +++ b/include/mastodont.h @@ -25,4 +25,6 @@ void mastodont_global_curl_cleanup(); int mastodont_init(mastodont_t* data); void mastodont_free(mastodont_t* data); +void mastodont_storage_cleanup(struct mstdnt_storage* storage); + #endif /* MASTODONT_H */ diff --git a/include/mastodont_status.h b/include/mastodont_status.h index 8cbff66..3613e67 100644 --- a/include/mastodont_status.h +++ b/include/mastodont_status.h @@ -15,6 +15,7 @@ #ifndef MASTODONT_STATUS #define MASTODONT_STATUS +#include #include "mastodont_types.h" #include "mastodont_attachment.h" #include "mastodont_application.h" @@ -76,4 +77,6 @@ struct mstdnt_status mstdnt_bool pinned; }; +int mstdnt_load_status_from_json(struct mstdnt_status* status, cJSON* js); + #endif /* MASTODONT_STATUS */ diff --git a/include/mastodont_timeline.h b/include/mastodont_timeline.h index 62733a6..06026a7 100644 --- a/include/mastodont_timeline.h +++ b/include/mastodont_timeline.h @@ -30,6 +30,7 @@ struct mstdnt_timeline_public_args { int mastodont_timeline_public(mastodont_t* data, struct mstdnt_timeline_public_args* args, + struct mstdnt_storage* storage, struct mstdnt_status* response[]); #endif /* MASTODONT_TIMELINE_H */ diff --git a/include/mastodont_types.h b/include/mastodont_types.h index 353e0a9..c7b45a0 100644 --- a/include/mastodont_types.h +++ b/include/mastodont_types.h @@ -16,6 +16,7 @@ #ifndef MASTODONT_TYPES_H #define MASTODONT_TYPES_H #include +#include #define MSTDNT_URLSIZE 2048 typedef unsigned char mstdnt_bool; @@ -26,4 +27,10 @@ typedef struct mastodont CURL* curl; } mastodont_t; +struct mstdnt_storage +{ + int needs_cleanup; /* Double free safe */ + cJSON* root; +}; + #endif /* MASTODONT_TYPES_H */ diff --git a/src/mastodont.c b/src/mastodont.c index c58fb42..2a27eab 100644 --- a/src/mastodont.c +++ b/src/mastodont.c @@ -22,3 +22,8 @@ void mastodont_free(mastodont_t* data) { curl_easy_cleanup(data->curl); } + +void mastodont_storage_cleanup(struct mstdnt_storage* storage) +{ + cJSON_Delete(storage->root); +} diff --git a/src/status.c b/src/status.c new file mode 100644 index 0000000..1e56398 --- /dev/null +++ b/src/status.c @@ -0,0 +1,50 @@ +/* + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include +#include + +int mstdnt_load_status_from_json(struct mstdnt_status* status, cJSON* js) +{ + cJSON* v; + for (v = js; v; v = v->next) + { + if (cJSON_IsString(v)) + { + if(strcmp("id", v->string)==0) status->id = v->valuestring; + if(strcmp("uri", v->string)==0) status->uri = v->valuestring; + if(strcmp("created_at", v->string)==0) status->created_at = v->valuestring; + if(strcmp("content", v->string)==0) status->content = v->valuestring; + if(strcmp("spoiler_text", v->string)==0) status->spoiler_text = v->valuestring; + if(strcmp("in_reply_to_id", v->string)==0) status->in_reply_to_id = v->valuestring; + if(strcmp("in_reply_to_account_id", v->string)==0) status->in_reply_to_account_id = v->valuestring; + if(strcmp("in_reply_to_id", v->string)==0) status->in_reply_to_id = v->valuestring; + if(strcmp("language", v->string)==0) status->language = v->valuestring; + if(strcmp("text", v->string)==0) status->text = v->valuestring; + if(strcmp("in_reply_to_id", v->string)==0) status->in_reply_to_id = v->valuestring; + } + else if (cJSON_IsBool(v)) + { + /* It's probably an int 1/0, but for portability reasons I'll use the typedefs */ + const int val = cJSON_IsTrue(v) ? cJSON_True : cJSON_False; + if (strcmp("sensitive", v->string) == 0) status->sensitive = val; + if (strcmp("favourited", v->string) == 0) status->favourited = val; + if (strcmp("reblogged", v->string) == 0) status->reblogged = val; + if (strcmp("muted", v->string) == 0) status->sensitive = val; + if (strcmp("bookmarked", v->string) == 0) status->bookmarked = val; + if (strcmp("pinned", v->string) == 0) status->pinned = val; + } + } +} diff --git a/src/timeline.c b/src/timeline.c index 92952c9..ee12fac 100644 --- a/src/timeline.c +++ b/src/timeline.c @@ -20,11 +20,14 @@ int mastodont_timeline_public(mastodont_t* data, struct mstdnt_timeline_public_args* args, + struct mstdnt_storage* storage, struct mstdnt_status* statuses[]) { int res; - cJSON* p; + cJSON* root, *status_j_list; + size_t i = 0; struct mstdnt_fetch_results results = { 0 }; + /* Default args */ struct mstdnt_timeline_public_args _args; if (args == NULL) @@ -38,20 +41,39 @@ int mastodont_timeline_public(mastodont_t* data, _args.limit = 20; args = &_args; } + storage->needs_cleanup = 0; res = mastodont_fetch_curl(data, "api/v1/timelines/public", &results); - cJSON* parse = cJSON_ParseWithLength(results.response, results.size); - if (parse == NULL) + root = cJSON_ParseWithLength(results.response, results.size); + if (root == NULL) { const char* jerror = cJSON_GetErrorPtr(); if (jerror) fprintf(stderr, "cJSON_Parse: %s\n", jerror); goto cleanup; } + storage->needs_cleanup = 1; + + if (!cJSON_IsArray(root)) + { + /* Likely an error */ + goto cleanup; + } + + /* malloc array */ + *statuses = malloc(cJSON_GetArraySize(root) * sizeof(struct mstdnt_status)); + if (*statuses == NULL) + { + perror("malloc"); + goto cleanup; + } + cJSON_ArrayForEach(status_j_list, root) + { + mstdnt_load_status_from_json((*statuses) + i++, status_j_list->child); + } cleanup: - if (parse) cJSON_Delete(parse); mastodont_fetch_results_cleanup(&results); return res;