restructures the code

This commit is contained in:
SuperNovaa41
2024-01-13 21:33:33 -05:00
parent 9fc68e1b72
commit 0f125ee459
6 changed files with 3 additions and 2 deletions

67
src/curl.c Normal file
View File

@ -0,0 +1,67 @@
#include <curl/curl.h>
#include <curl/easy.h>
#include <stdlib.h>
#include <string.h>
#include "curl.h"
#define BASE_URL_SIZE 38
void init_string(string* s)
{
s->len = 0;
s->buf = malloc(s->len + 1);
if (NULL == s->buf) {
fprintf(stderr, "malloc() failed!\n");
exit(EXIT_FAILURE);
}
s->buf[0] = '\0';
}
size_t writefunc(void* ptr, size_t size, size_t nmemb, string* s)
{
size_t new_len = s->len + (size * nmemb);
s->buf = realloc(s->buf, new_len + 1);
if (NULL == s->buf) {
fprintf(stderr, "realloc() failed!\n");
exit(EXIT_FAILURE);
}
memcpy(s->buf + s->len, ptr, size * nmemb);
s->buf[new_len] = '\0';
s->len = new_len;
return size * nmemb;
}
CURLcode perform_book_get(char* isbn, string* s)
{
CURL* handler;
char* base_url;
size_t finalurl_size = BASE_URL_SIZE + 15;
char finalurl[finalurl_size];
CURLcode result;
handler = curl_easy_init();
if (!handler) {
fprintf(stderr, "cURL failed to initialize!\n");
exit(EXIT_FAILURE);
}
base_url = "https://openlibrary.org/search.json?q=";
// Setup the URL for the request
snprintf(finalurl, finalurl_size, "%s%s", base_url, isbn);
curl_easy_setopt(handler, CURLOPT_URL, finalurl);
curl_easy_setopt(handler, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(handler, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(handler, CURLOPT_WRITEDATA, s);
result = curl_easy_perform(handler);
// Always clean up
curl_easy_cleanup(handler);
return result;
}

40
src/curl.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef CURL_H
#define CURL_H
/**
* struct string_t
* char* buf - The buffer containing the string data
* size_t len - The length of the buffer
*/
typedef struct string_t {
char* buf;
size_t len;
} string;
/**
* void init_string
* string* s - The string struct
*
* Initializes the string struct
*/
void init_string(string* s);
/**
* size_t writefunc
*
* The arguments from CURLOPT_WRITEFUNCTION
*
* Writes the cURL get into the string struct
*/
size_t writefunc(void* ptr, size_t size, size_t nmemb, string* s);
/**
* CURLcode perform_book_get
* char* isbn - The ISBN
* string* s - The string struct to place the GET output in
*
* Performs a GET request with the ISBN
*/
CURLcode perform_book_get(char* isbn, string* s);
#endif

70
src/json.c Normal file
View File

@ -0,0 +1,70 @@
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl.h"
#include "json.h"
#define MAX_BUF_LEN 1024
void check_valid_query(cJSON* numfound)
{
if (0 != numfound->valueint)
return;
fprintf(stderr, "No ISBN found!\n");
exit(EXIT_FAILURE);
}
void get_authors(cJSON* bookinfo, char authors[256])
{
char* temp_author;
size_t new_len;
cJSON* author_arr = cJSON_GetObjectItemCaseSensitive(bookinfo, "author_name")->child;
snprintf(authors, strlen(author_arr->valuestring) + 1, "%s", author_arr->valuestring);
author_arr = author_arr->next;
while (NULL != author_arr) {
// The plus 1 is for the \0, the plus 2 is for the ", "
new_len = strlen(authors) + strlen(author_arr->valuestring) + 1 + 2;
temp_author = malloc(sizeof(char) * new_len);
snprintf(temp_author, new_len, "%s, %s", authors, author_arr->valuestring);
memcpy(authors, temp_author, new_len);
free(temp_author);
author_arr = author_arr->next;
}
}
void parse_json(string* s, char* isbn, book_t* book)
{
char authors[MAX_BUF_LEN];
cJSON* json = cJSON_Parse(s->buf);
if (NULL == json) {
const char* error_ptr = cJSON_GetErrorPtr();
if (NULL != error_ptr)
fprintf(stderr, "JSON error: %s\n", error_ptr);
cJSON_Delete(json);
exit(EXIT_FAILURE);
}
check_valid_query(cJSON_GetObjectItemCaseSensitive(json, "numFound"));
cJSON* bookinfo = cJSON_GetObjectItemCaseSensitive(json, "docs")->child;
book->isbn = isbn;
book->title = cJSON_GetObjectItemCaseSensitive(bookinfo, "title")->valuestring;
book->year_of_publication = cJSON_GetObjectItemCaseSensitive(bookinfo, "first_publish_year")->valueint;
book->page_len = cJSON_GetObjectItemCaseSensitive(bookinfo, "number_of_pages_median")->valueint;
get_authors(bookinfo, authors);
// Need to malloc, because we need to copy authors into the book struct
book->authors = (char*) malloc(sizeof(char) * (strlen(authors) + 1));
memcpy(book->authors, authors, strlen(authors) + 1);
}

40
src/json.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef JSON_H
#define JSON_H
#define MAX_BUF_LEN 1024
typedef struct book_t {
char* isbn;
char* title;
char* authors;
int year_of_publication;
int page_len;
} book_t;
/**
* void check_valid_query
* cJSON* numfound - The json entry that contains the numFound value
*
* Checks if there are any search results in this json entry
*/
void check_valid_query(cJSON* numfound);
/**
* void get_authors
* cJSON* bookinfo - The JSON entry that has all of the information about the book
* char* authors - The string to fill
*
* Takes the JSON entry from bookinfo and combines all of the authors into one final string
*/
void get_authors(cJSON* bookinfo, char* authors);
/**
* void parse_json
* string* s - The string struct
* char* isbn - The ISBN
* book_t* book - The struct to fill with book information
*
* Parses through the given JSON entry and gathers all of the information we need
*/
void parse_json(string* s, char* isbn, book_t* book);
#endif

124
src/main.c Normal file
View File

@ -0,0 +1,124 @@
#include <curl/curl.h>
#include <cjson/cJSON.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "curl.h"
#include "json.h"
#define FILE_NAME "books.csv"
#define MAX_BUF_LEN 1024
void print_book(book_t* book)
{
printf("ISBN: %s\n", book->isbn);
printf("Title: %s\n", book->title);
printf("Author(s): %s\n", book->authors);
printf("(First) Year of Publication: %d\n", book->year_of_publication);
printf("Page length: %d\n", book->page_len);
}
void write_to_file(book_t* book)
{
FILE* file;
int file_exists;
/**
* We want to check if the file exists
* if it doesnt, we create a new one
* otherwise, we write to the existing one
*/
file_exists = access(FILE_NAME, F_OK);
if (0 != file_exists) {
file = fopen(FILE_NAME, "w");
fprintf(file, "isbn,title,authors,year of publication,page length\n");
} else {
file = fopen(FILE_NAME, "a");
}
// now we write the information
fprintf(file, "\"%s\",\"%s\",\"%s\",%d,%d\n",
book->isbn, book->title, book->authors, book->year_of_publication, book->page_len);
fclose(file);
}
int main(int argc, char* argv[])
{
char isbn_buf[14]; // want to hold a max of 14 so we can hold up to ISBN13s
char options[2];
CURLcode res;
book_t new_book;
if (3 != argc) {
printf("Usage: isbn [isbn] [options]\n");
return EXIT_FAILURE;
}
size_t input_len = strlen(argv[1]);
if (!(13 == input_len || 10 == input_len)) {
fprintf(stderr, "Invalid ISBN submitted!");
return EXIT_FAILURE;
}
/**
* We must initialize cURL
*/
curl_global_init(CURL_GLOBAL_ALL);
/**
* Grab the ISBN from argv
*/
snprintf(isbn_buf, 14, "%s", argv[1]);
/**
* Grab the formatting options from argv
*/
snprintf(options, 2, "%s", argv[2]);
if (!(('w' == options[0]) || ('r' == options[0]))) {
fprintf(stderr, "Invalid option submitted!\n");
return EXIT_FAILURE;
}
/**
* Setup the output string
*/
string get_output;
init_string(&get_output);
/**
* Perform the get request
*/
res = perform_book_get(isbn_buf, &get_output);
if (0 != res) {
fprintf(stderr, "Failed to perform the get request!\n");
return EXIT_FAILURE;
}
/**
* Now we want to parse the JSON input
*/
parse_json(&get_output, isbn_buf, &new_book);
/**
* We need to free this string
*/
free(get_output.buf);
/**
* NOW we either print or save the book
*/
if (options[0] == 'w')
write_to_file(&new_book);
else if (options[0] == 'r')
print_book(&new_book);
return 0;
}