Adding src so far
This commit is contained in:
parent
6cf298cfea
commit
cf9e6955e8
88
.gitignore
vendored
88
.gitignore
vendored
|
@ -1,90 +1,12 @@
|
||||||
# ---> C
|
# ---> C
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
*.o
|
build/
|
||||||
*.ko
|
|
||||||
*.obj
|
|
||||||
*.elf
|
|
||||||
|
|
||||||
# Linker output
|
|
||||||
*.ilk
|
|
||||||
*.map
|
|
||||||
*.exp
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
*.lib
|
lib/
|
||||||
*.a
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
||||||
|
|
||||||
# Shared objects (inc. Windows DLLs)
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.so.*
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Executables
|
# Executables
|
||||||
*.exe
|
targets/
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
*.i*86
|
|
||||||
*.x86_64
|
|
||||||
*.hex
|
|
||||||
|
|
||||||
# Debug files
|
|
||||||
*.dSYM/
|
|
||||||
*.su
|
|
||||||
*.idb
|
|
||||||
*.pdb
|
|
||||||
|
|
||||||
# Kernel Module Compile Results
|
|
||||||
*.mod*
|
|
||||||
*.cmd
|
|
||||||
.tmp_versions/
|
|
||||||
modules.order
|
|
||||||
Module.symvers
|
|
||||||
Mkfile.old
|
|
||||||
dkms.conf
|
|
||||||
|
|
||||||
# ---> C++
|
|
||||||
# Prerequisites
|
|
||||||
*.d
|
|
||||||
|
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Precompiled Headers
|
|
||||||
*.gch
|
|
||||||
*.pch
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Fortran module files
|
|
||||||
*.mod
|
|
||||||
*.smod
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
|
|
||||||
# ---> Gradle
|
# ---> Gradle
|
||||||
.gradle
|
.gradle
|
||||||
|
@ -120,9 +42,6 @@ gradle-app.setting
|
||||||
# Local History for Visual Studio Code
|
# Local History for Visual Studio Code
|
||||||
.history/
|
.history/
|
||||||
|
|
||||||
# Built Visual Studio Code Extensions
|
|
||||||
*.vsix
|
|
||||||
|
|
||||||
# ---> Bazel
|
# ---> Bazel
|
||||||
# gitignore template for Bazel build system
|
# gitignore template for Bazel build system
|
||||||
# website: https://bazel.build/
|
# website: https://bazel.build/
|
||||||
|
@ -137,4 +56,3 @@ gradle-app.setting
|
||||||
/.ijwb/
|
/.ijwb/
|
||||||
/.aswb/
|
/.aswb/
|
||||||
/.clwb/
|
/.clwb/
|
||||||
|
|
||||||
|
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"C_Cpp.default.cStandard": "c17"
|
||||||
|
}
|
24
Makefile
Normal file
24
Makefile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
CFLAGS = -std=c17
|
||||||
|
CPPFLAGS = -std=c++17
|
||||||
|
APPS_DIR = ./apps
|
||||||
|
TARGETS_DIR = ./targets
|
||||||
|
OBJECTS_DIR = ./build
|
||||||
|
LIBS_DIR = ./src
|
||||||
|
INCLUDES = -I ./include
|
||||||
|
TESTS_DIR = ./tests
|
||||||
|
VPATH = $(TARGETS_DIR) $(OBJECTS_DIR) $(APPS_DIR) $(LIBS_DIR) $(TESTS_DIR)
|
||||||
|
|
||||||
|
main: main.c requests.o
|
||||||
|
cc $(CFLAGS) $(INCLUDES) -lcurl $(APPS_DIR)/main.c $(LIBS_DIR)/requests.c -o $(TARGETS_DIR)/main
|
||||||
|
|
||||||
|
requests.o: requests.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c $(LIBS_DIR)/requests.c -o $(OBJECTS_DIR)/requests.o
|
||||||
|
|
||||||
|
test: test_requests
|
||||||
|
$(TARGETS_DIR)/test_requests
|
||||||
|
|
||||||
|
test_requests: test_requests.cpp requests.o
|
||||||
|
$(CXX) $(CPPFLAGS) $(INCLUDES) -lcurl -lgtest -lgtest_main $(TESTS_DIR)/test_requests.cpp $(OBJECTS_DIR)/requests.o -o $(TARGETS_DIR)/test_requests
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm $(TARGETS_DIR)/* $(OBJECTS_DIR)/*
|
11
README.md
11
README.md
|
@ -1,3 +1,14 @@
|
||||||
# c-rss
|
# c-rss
|
||||||
|
|
||||||
An RSS feed reader written in C
|
An RSS feed reader written in C
|
||||||
|
|
||||||
|
I am re-learning C by writing an RSS feed reader from scratch. I plan on playing around with several build tools such as make, gradle, and bazel.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
* get better at C
|
||||||
|
* get better at Makefiles
|
||||||
|
* learn how to write gradle plugins
|
||||||
|
* get better at SQL
|
||||||
|
* compare make, gradle, and bazel
|
||||||
|
* learn how to use gtest for C projects
|
||||||
|
|
11
apps/main.c
Normal file
11
apps/main.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "requests.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("Hello, world!\n");
|
||||||
|
requestInit();
|
||||||
|
requestGet("https://google.com");
|
||||||
|
requestCleanup();
|
||||||
|
}
|
28
include/requests.h
Normal file
28
include/requests.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifndef __SHILLERBEN_REQUESTS__
|
||||||
|
#define __SHILLERBEN_REQUESTS__
|
||||||
|
|
||||||
|
typedef struct GetRequestResult GetRequestResult;
|
||||||
|
struct GetRequestResult {
|
||||||
|
int errorCode;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void requestsInit(void);
|
||||||
|
void requestsCleanup(void);
|
||||||
|
GetRequestResult requestGet(const char* url);
|
||||||
|
|
||||||
|
size_t _getRequestCb(char *buffer, size_t size, size_t nmemb, GetRequestResult *result);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
73
src/requests.c
Normal file
73
src/requests.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "requests.h"
|
||||||
|
|
||||||
|
void requestsInit(void) {
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void requestsCleanup(void) {
|
||||||
|
curl_global_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
GetRequestResult requestGet(const char* url) {
|
||||||
|
printf("requestGet(%s)\n", url);
|
||||||
|
|
||||||
|
GetRequestResult result = {
|
||||||
|
.errorCode = -1,
|
||||||
|
.data = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
CURL *handle = curl_easy_init();
|
||||||
|
CURLcode err;
|
||||||
|
|
||||||
|
err = curl_easy_setopt(handle, CURLOPT_URL, url);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed to set url\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
err = curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, _getRequestCb);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed to set callback function\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
err = curl_easy_setopt(handle, CURLOPT_WRITEDATA, &result);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed to set callback data\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.errorCode = 0;
|
||||||
|
result.size = 0;
|
||||||
|
result.capacity = 1024;
|
||||||
|
result.data = calloc(1024, sizeof(char));
|
||||||
|
err = curl_easy_perform(handle);
|
||||||
|
if (err) {
|
||||||
|
printf("Error performing request\n");
|
||||||
|
result.errorCode = -1;
|
||||||
|
result.size = 0;
|
||||||
|
free(result.data);
|
||||||
|
result.data = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t _getRequestCb(char *buffer, size_t size, size_t nmemb, GetRequestResult *result) {
|
||||||
|
size_t numBytes = size * nmemb;
|
||||||
|
while (result->size + numBytes > result->capacity + 1 /*extra byte for null terminator*/) {
|
||||||
|
size_t newCapacity = result->capacity * 2;
|
||||||
|
char *newData = calloc(newCapacity, sizeof(char));
|
||||||
|
memcpy(newData, result->data, result->size);
|
||||||
|
free(result->data);
|
||||||
|
result->data = newData;
|
||||||
|
result->capacity = newCapacity;
|
||||||
|
}
|
||||||
|
memcpy(result->data + result->size, buffer, numBytes);
|
||||||
|
result->size += numBytes;
|
||||||
|
result->data[result->size] = '\0';
|
||||||
|
return numBytes;
|
||||||
|
}
|
16
tests/test_requests.cpp
Normal file
16
tests/test_requests.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include <string>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "requests.h"
|
||||||
|
|
||||||
|
TEST(RequestsTest, HttpsGetTest) {
|
||||||
|
requestsInit();
|
||||||
|
std::string expected = "<!DOCTYPE html>\n<html >\n<head><meta charset=\"utf-8\">\n<title>Ben Shiller</title>";
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
GetRequestResult result = requestGet("https://shillerben.com");
|
||||||
|
// std::cout << "GET https://shillerben.com returned: " << result.data << '\n';
|
||||||
|
ASSERT_EQ(strncmp(result.data, expected.c_str(), expected.size()), 0);
|
||||||
|
free(result.data);
|
||||||
|
}
|
||||||
|
requestsCleanup();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user