aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntony Kellermann2018-09-04 19:47:19 -0400
committerAntony Kellermann2018-09-04 19:47:19 -0400
commit5e2e750b4eb1adb25385ee13f6cb62c4b8868f78 (patch)
tree87e0297975a1e2b8a4c1b3aaa9cb3d1e6b4a417f
parent4166914b1a911c15fe2c18f345ac8d103155b583 (diff)
downloadaur-5e2e750b4eb1adb25385ee13f6cb62c4b8868f78.tar.gz
Refactoring
-rw-r--r--README.md7
-rw-r--r--api.c165
-rw-r--r--api.h99
-rw-r--r--curses_win.c50
-rw-r--r--gtk_win.c24
-rw-r--r--portfolio.c10
6 files changed, 180 insertions, 175 deletions
diff --git a/README.md b/README.md
index e1a857edd181..376394ec28da 100644
--- a/README.md
+++ b/README.md
@@ -133,4 +133,9 @@ the provided license for more information.
* Implement Coinmarketcap v2
* Notes for portfolio securities
* Search for securities
-* History per session \ No newline at end of file
+* History per session
+* Mutex on portfolio
+* Add security without reloading every security
+* Refactoring
+* Cache ref-data
+* streq \ No newline at end of file
diff --git a/api.c b/api.c
index 5b76a1f1325a..d2e84076c29b 100644
--- a/api.c
+++ b/api.c
@@ -1,6 +1,6 @@
#include "api.h"
-Ref_Data* api_ref_data_init_from_length(size_t length) {
+Ref_Data* ref_data_init_length(size_t length) {
Ref_Data* pRef_Data = malloc(sizeof(Ref_Data));
pointer_alloc_check(pRef_Data);
pRef_Data->symbols = malloc(length * sizeof(char*));
@@ -17,7 +17,7 @@ Ref_Data* api_ref_data_init_from_length(size_t length) {
return pRef_Data;
}
-News* api_news_init(void) {
+News* news_init(void) {
News* pNews = malloc(sizeof(News));
pointer_alloc_check(pNews);
*pNews = (News) {
@@ -26,7 +26,7 @@ News* api_news_init(void) {
return pNews;
}
-Info* api_info_init(void) {
+Info* info_init(void) {
Info* pInfo = malloc(sizeof(Info));
pointer_alloc_check(pInfo);
*pInfo = (Info) { // Null terminate every string and set every value to EMPTY
@@ -51,7 +51,7 @@ Info* api_info_init(void) {
return pInfo;
}
-Info_Array* api_info_array_init(void) {
+Info_Array* info_array_init(void) {
Info_Array* pInfo_Array = malloc(sizeof(Info_Array));
pointer_alloc_check(pInfo_Array);
*pInfo_Array = (Info_Array) {
@@ -60,18 +60,18 @@ Info_Array* api_info_array_init(void) {
return pInfo_Array;
}
-Info_Array* api_info_array_init_from_length(size_t length) {
+Info_Array* info_array_init_length(size_t length) {
if (length == 0)
- return api_info_array_init();
+ return info_array_init();
- Info_Array* pInfo_Array = api_info_array_init();
+ Info_Array* pInfo_Array = info_array_init();
pInfo_Array->length = length;
pInfo_Array->array = malloc(sizeof(Info*) * length);
pointer_alloc_check(pInfo_Array->array);
for (size_t i = 0; i < length; i++)
- pInfo_Array->array[i] = api_info_init();
+ pInfo_Array->array[i] = info_init();
- pInfo_Array->totals = api_info_init();
+ pInfo_Array->totals = info_init();
strcpy(pInfo_Array->totals->symbol, "TOTALS");
return pInfo_Array;
}
@@ -79,11 +79,11 @@ Info_Array* api_info_array_init_from_length(size_t length) {
void info_array_append(Info_Array* pInfo_Array, const char* symbol) {
pInfo_Array->array = realloc(pInfo_Array->array, sizeof(char*) * (pInfo_Array->length + 1));
pInfo_Array->length++;
- pInfo_Array->array[pInfo_Array->length - 1] = api_info_init();
+ pInfo_Array->array[pInfo_Array->length - 1] = info_init();
strcpy(pInfo_Array->array[pInfo_Array->length - 1]->symbol, symbol);
}
-size_t api_string_writefunc(void* ptr, size_t size, size_t nmemb, String* pString) {
+size_t string_writefunc(void* ptr, size_t size, size_t nmemb, String* pString) {
size_t new_len = pString->len + size * nmemb;
pString->data = realloc(pString->data, new_len + 1);
pointer_alloc_check(pString->data);
@@ -93,7 +93,7 @@ size_t api_string_writefunc(void* ptr, size_t size, size_t nmemb, String* pStrin
return size * nmemb;
}
-String* api_curl_data(const char* url) {
+String* api_curl_url(const char* url) {
CURL* curl = curl_easy_init();
CURLcode res;
if (!curl) // Error creating curl object
@@ -102,7 +102,7 @@ String* api_curl_data(const char* url) {
String* pString = string_init();
curl_easy_setopt(curl, CURLOPT_URL, url); // Set URL
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Needed for HTTPS
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, api_string_writefunc); // Specify writefunc for return data
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, string_writefunc); // Specify writefunc for return data
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pString->data); // Specify object for return data
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
@@ -114,7 +114,7 @@ String* api_curl_data(const char* url) {
return pString;
}
-void iex_batch_store_data_info_array(Info_Array* pInfo_Array, Data_Level data_level) {
+void api_iex_store_info_array(Info_Array* pInfo_Array, Data_Level data_level) {
char** symbol_array = malloc(pInfo_Array->length * sizeof(char*));
pointer_alloc_check(symbol_array);
for (size_t i = 0; i < pInfo_Array->length; i++) {
@@ -123,9 +123,9 @@ void iex_batch_store_data_info_array(Info_Array* pInfo_Array, Data_Level data_le
strcpy(symbol_array[i], pInfo_Array->array[i]->symbol);
}
- String* pString = iex_batch_get_data_string(symbol_array, pInfo_Array->length, data_level);
+ String* pString = api_iex_get_data_string(symbol_array, pInfo_Array->length, data_level);
Json* jobj = json_tokener_parse(pString->data);
- info_array_store_all_from_json(pInfo_Array, jobj);
+ info_array_store_endpoints_json(pInfo_Array, jobj);
for (size_t i = 0; i < pInfo_Array->length; i++)
free(symbol_array[i]);
@@ -135,36 +135,36 @@ void iex_batch_store_data_info_array(Info_Array* pInfo_Array, Data_Level data_le
string_destroy(&pString);
}
-void iex_batch_store_data_info(Info* pInfo, Data_Level data_level) {
+void api_iex_store_info(Info* pInfo, Data_Level data_level) {
char* symbol_array = malloc(SYMBOL_MAX_LENGTH);
pointer_alloc_check(symbol_array);
strcpy(symbol_array, pInfo->symbol);
- String* pString = iex_batch_get_data_string(&symbol_array, 1, data_level);
+ String* pString = api_iex_get_data_string(&symbol_array, 1, data_level);
Json* jobj = json_tokener_parse(pString->data);
Json* jsymbol = json_object_object_get(jobj, pInfo->symbol);
if (jsymbol != NULL)
- info_store_all_from_json(pInfo, jsymbol);
+ info_store_endpoints_json(pInfo, jsymbol);
free(symbol_array);
json_object_put(jobj);
string_destroy(&pString);
}
-String* iex_batch_get_data_string(char* symbol_array[SYMBOL_MAX_LENGTH], size_t len,
- Data_Level data_level) {
+String* api_iex_get_data_string(char** symbol_array, size_t len,
+ Data_Level data_level) {
char endpoints[128];
- if (data_level == ALL)
+ if (data_level == DATA_LEVEL_ALL)
strcpy(endpoints, "quote,chart,company,stats,peers,news,earnings&range=5y");
- else if (data_level == CHECK)
+ else if (data_level == DATA_LEVEL_CHECK)
strcpy(endpoints, "quote,chart");
- else if (data_level == MISC)
+ else if (data_level == DATA_LEVEL_MISC)
strcpy(endpoints, "company,stats,peers,news,earnings&range=5y");
else strcpy(endpoints, "news");
size_t num_partitions = len / 100 + (len % 100 > 0), idx;
char iex_api_string[num_partitions][URL_MAX_LENGTH * 2];
- char symbol_list_string[num_partitions][INFO_TEXT_MAX];
- memset(symbol_list_string, '\0', num_partitions * INFO_TEXT_MAX);
+ char symbol_list_string[num_partitions][INFO_MAX_LENGTH];
+ memset(symbol_list_string, '\0', num_partitions * INFO_MAX_LENGTH);
String* string_array[num_partitions];
pthread_t threads[num_partitions];
for (size_t i = 0; i < num_partitions; i++) {
@@ -181,7 +181,7 @@ String* iex_batch_get_data_string(char* symbol_array[SYMBOL_MAX_LENGTH], size_t
sprintf(iex_api_string[i],
"https://api.iextrading.com/1.0/stock/market/batch?symbols=%s&types=%s",
symbol_list_string[i], endpoints);
- if (pthread_create(&threads[i], NULL, (void* (*)(void*)) api_curl_data,
+ if (pthread_create(&threads[i], NULL, (void* (*)(void*)) api_curl_url,
(void*) iex_api_string[i]))
EXIT_MSG("Error creating thread!");
}
@@ -209,7 +209,7 @@ String* iex_batch_get_data_string(char* symbol_array[SYMBOL_MAX_LENGTH], size_t
return string_array[0];
}
-void* morningstar_store_info(void* vpInfo) {
+void* api_morningstar_store_info(void* vpInfo) {
Info* symbol_info = vpInfo;
char today_str[DATE_MAX_LENGTH], five_year_str[DATE_MAX_LENGTH], morningstar_api_string[URL_MAX_LENGTH];
time_t now = time(NULL);
@@ -223,7 +223,7 @@ void* morningstar_store_info(void* vpInfo) {
"http://globalquote.morningstar.com/globalcomponent/RealtimeHistoricalStockData.ashx?showVol=true&dtype=his"
"&f=d&curry=USD&isD=true&isS=true&hasF=true&ProdCode=DIRECT&ticker=%s&range=%s|%s",
symbol_info->symbol, five_year_str, today_str);
- String* pString = api_curl_data(morningstar_api_string);
+ String* pString = api_curl_url(morningstar_api_string);
if (pString == NULL)
return NULL;
@@ -232,7 +232,7 @@ void* morningstar_store_info(void* vpInfo) {
return NULL;
}
- symbol_info->api_provider = MORNINGSTAR;
+ symbol_info->api_provider = API_PROVIDER_MORNINGSTAR;
Json* jobj = json_tokener_parse(pString->data);
Json* datapoints = json_object_object_get(
@@ -257,7 +257,7 @@ void* morningstar_store_info(void* vpInfo) {
return vpInfo;
}
-void* alphavantage_store_info(void* vpInfo) {
+void* api_alphavantage_store_info(void* vpInfo) {
Info* symbol_info = vpInfo;
if (symbol_info->symbol[0] == '\0')
return NULL;
@@ -266,7 +266,7 @@ void* alphavantage_store_info(void* vpInfo) {
sprintf(alphavantage_api_string, "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY"
"&symbol=%s&apikey=DFUMLJ1ILOM2G7IH&outputsize=full&datatype"
"=csv", symbol_info->symbol);
- String* pString = api_curl_data(alphavantage_api_string);
+ String* pString = api_curl_url(alphavantage_api_string);
if (pString == NULL)
return NULL;
@@ -275,7 +275,7 @@ void* alphavantage_store_info(void* vpInfo) {
return NULL;
}
- symbol_info->api_provider = ALPHAVANTAGE;
+ symbol_info->api_provider = API_PROVIDER_ALPHAVANTAGE;
size_t len = string_get_num_lines(pString) - 1, idx = 0;
if (len > 1260) // 5 years
@@ -303,11 +303,11 @@ void* alphavantage_store_info(void* vpInfo) {
return vpInfo;
}
-void* coinmarketcap_store_info(void* vpInfo) {
+void* api_coinmarketcap_store_info(void* vpInfo) {
Info* symbol_info = vpInfo;
char coinmarketcap_api_string[URL_MAX_LENGTH];
sprintf(coinmarketcap_api_string, "https://api.coinmarketcap.com/v1/ticker/%s", symbol_info->symbol);
- String* pString = api_curl_data(coinmarketcap_api_string);
+ String* pString = api_curl_url(coinmarketcap_api_string);
if (pString == NULL)
return NULL;
@@ -316,7 +316,7 @@ void* coinmarketcap_store_info(void* vpInfo) {
return NULL;
}
- symbol_info->api_provider = COINMARKETCAP;
+ symbol_info->api_provider = API_PROVIDER_COINMARKETCAP;
Json* jobj = json_tokener_parse(pString->data);
Json* data = json_object_array_get_idx(jobj, 0);
@@ -338,8 +338,8 @@ void* coinmarketcap_store_info(void* vpInfo) {
return vpInfo;
}
-void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_level) {
- iex_batch_store_data_info_array(pInfo_Array, data_level);
+void api_store_info_array(Info_Array* pInfo_Array, Data_Level data_level) {
+ api_iex_store_info_array(pInfo_Array, data_level);
// All IEX securities are accounted for
Info* pInfo;
@@ -351,9 +351,9 @@ void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_le
if (pInfo->api_provider == EMPTY && strcmp(pInfo->symbol, "USD$") != 0) {
open_threads[i] = 1;
if (strlen(pInfo->symbol) > 5 && pthread_create(&threads[i], NULL,
- coinmarketcap_store_info, pInfo)) { // Crypto
+ api_coinmarketcap_store_info, pInfo)) { // Crypto
EXIT_MSG("Error creating thread!");
- } else if (pthread_create(&threads[i], NULL, alphavantage_store_info, pInfo)) {
+ } else if (pthread_create(&threads[i], NULL, api_alphavantage_store_info, pInfo)) {
EXIT_MSG("Error creating thread!");
}
}
@@ -371,7 +371,7 @@ void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_le
// Crypto with 5 char or less name
if (pInfo->api_provider == EMPTY && strcmp(pInfo->symbol, "USD$") != 0 &&
- pthread_create(&threads[i], NULL, coinmarketcap_store_info, pInfo))
+ pthread_create(&threads[i], NULL, api_coinmarketcap_store_info, pInfo))
EXIT_MSG("Error creating thread!");
}
@@ -383,21 +383,22 @@ void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_le
open_threads[i] = 0;
}
- info_store_check_data(pInfo_Array->array[i]);
+ info_store_portfolio_data(pInfo_Array->array[i]);
}
info_array_store_totals(pInfo_Array);
}
-void api_info_store_data_batch(Info* pInfo, Data_Level data_level) {
- iex_batch_store_data_info(pInfo, data_level);
- if (data_level == NEWS || (pInfo->api_provider == EMPTY &&
- alphavantage_store_info(pInfo) == NULL && coinmarketcap_store_info(pInfo) == NULL))
+void api_store_info(Info* pInfo, Data_Level data_level) {
+ api_iex_store_info(pInfo, data_level);
+ if (data_level == DATA_LEVEL_NEWS || (pInfo->api_provider == EMPTY &&
+ api_alphavantage_store_info(pInfo) == NULL &&
+ api_coinmarketcap_store_info(pInfo) == NULL))
return;
- info_store_check_data(pInfo);
+ info_store_portfolio_data(pInfo);
}
-void info_store_check_data(Info* pInfo) {
+void info_store_portfolio_data(Info* pInfo) {
if (strcmp(pInfo->symbol, "USD$") != 0) {
if (pInfo->amount != EMPTY) {
pInfo->current_value = pInfo->amount * pInfo->price;
@@ -450,13 +451,13 @@ void info_array_store_totals(Info_Array* pInfo_Array) {
pInfo_Array->totals->total_spent;
}
-Ref_Data* iex_get_valid_symbols(void) {
- String* pString = api_curl_data("https://api.iextrading.com/1.0/ref-data/symbols");
+Ref_Data* api_iex_store_ref_data(void) {
+ String* pString = api_curl_url("https://api.iextrading.com/1.0/ref-data/symbols");
if (pString == NULL)
return NULL;
Json* jobj = json_tokener_parse(pString->data), * idx;
- Ref_Data* pRef_Data = api_ref_data_init_from_length(json_object_array_length(jobj));
+ Ref_Data* pRef_Data = ref_data_init_length(json_object_array_length(jobj));
for (size_t i = 0; i < pRef_Data->length; i++) {
idx = json_object_array_get_idx(jobj, i);
strcpy(pRef_Data->symbols[i], json_object_get_string(json_object_object_get(idx,
@@ -471,18 +472,18 @@ Ref_Data* iex_get_valid_symbols(void) {
return pRef_Data;
}
-void info_array_store_all_from_json(Info_Array* pInfo_Array, const Json* jobj) {
+void info_array_store_endpoints_json(Info_Array* pInfo_Array, const Json* jobj) {
Json* jsymbol;
for (size_t i = 0; i < pInfo_Array->length; i++) {
jsymbol = json_object_object_get(jobj, pInfo_Array->array[i]->symbol);
if (jsymbol != NULL)
- info_store_all_from_json(pInfo_Array->array[i], jsymbol);
+ info_store_endpoints_json(pInfo_Array->array[i], jsymbol);
}
}
-void info_store_all_from_json(Info* pInfo, const Json* jsymbol) {
+void info_store_endpoints_json(Info* pInfo, const Json* jsymbol) {
Json* jquote, * jchart, * jcompany, * jstats, * jpeers, * jnews, * jearnings;
- pInfo->api_provider = IEX;
+ pInfo->api_provider = API_PROVIDER_IEX;
jquote = json_object_object_get(jsymbol, "quote");
jchart = json_object_object_get(jsymbol, "chart");
jcompany = json_object_object_get(jsymbol, "company");
@@ -491,22 +492,22 @@ void info_store_all_from_json(Info* pInfo, const Json* jsymbol) {
jnews = json_object_object_get(jsymbol, "news");
jearnings = json_object_object_get(jsymbol, "earnings");
if (jquote != NULL)
- info_store_quote_from_json(pInfo, jquote);
+ info_store_quote_json(pInfo, jquote);
if (jchart != NULL)
- info_store_chart_from_json(pInfo, jchart);
+ info_store_chart_json(pInfo, jchart);
if (jcompany != NULL)
- info_store_company_from_json(pInfo, jcompany);
+ info_store_company_json(pInfo, jcompany);
if (jstats != NULL)
- info_store_stats_from_json(pInfo, jstats);
+ info_store_stats_json(pInfo, jstats);
if (jpeers != NULL)
- info_store_peers_from_json(pInfo, jpeers);
+ info_store_peers_json(pInfo, jpeers);
if (jnews != NULL)
- info_store_news_from_json(pInfo, jnews);
+ info_store_news_json(pInfo, jnews);
if (jearnings != NULL)
- info_store_earnings_from_json(pInfo, jearnings);
+ info_store_earnings_json(pInfo, jearnings);
}
-void info_store_quote_from_json(Info* pInfo, const Json* jquote) {
+void info_store_quote_json(Info* pInfo, const Json* jquote) {
if (json_object_get_int64(json_object_object_get(jquote, "extendedPriceTime")) >
json_object_get_int64(json_object_object_get(jquote, "latestUpdate"))) {
pInfo->price = json_object_get_double(json_object_object_get(jquote, "extendedPrice"));
@@ -526,7 +527,7 @@ void info_store_quote_from_json(Info* pInfo, const Json* jquote) {
}
-void info_store_chart_from_json(Info* pInfo, const Json* jchart) {
+void info_store_chart_json(Info* pInfo, const Json* jchart) {
free(pInfo->points);
size_t len = json_object_array_length(jchart);
pInfo->points = calloc(len + 1, sizeof(double));
@@ -544,7 +545,7 @@ void info_store_chart_from_json(Info* pInfo, const Json* jchart) {
pInfo->price_30d = pInfo->points[0];
}
-void info_store_company_from_json(Info* pInfo, const Json* jcompany) {
+void info_store_company_json(Info* pInfo, const Json* jcompany) {
Json* jsymbol, * jname, * jindustry, * jwebsite, * jdescription, * jceo, * jtype, * jsector;
jsymbol = json_object_object_get(jcompany, "symbol");
jname = json_object_object_get(jcompany, "companyName");
@@ -575,7 +576,7 @@ void info_store_company_from_json(Info* pInfo, const Json* jcompany) {
strcpy(pInfo->sector, json_object_get_string(jsector));
}
-void info_store_stats_from_json(Info* pInfo, const Json* jstats) {
+void info_store_stats_json(Info* pInfo, const Json* jstats) {
pInfo->div_yield = json_object_get_double(json_object_object_get(jstats, "dividendYield"));
pInfo->revenue = json_object_get_int64(json_object_object_get(jstats, "revenue"));
pInfo->gross_profit = json_object_get_int64(json_object_object_get(jstats, "grossProfit"));
@@ -583,23 +584,20 @@ void info_store_stats_from_json(Info* pInfo, const Json* jstats) {
pInfo->debt = json_object_get_int64(json_object_object_get(jstats, "debt"));
}
-void info_store_peers_from_json(Info* pInfo, const Json* jpeers) {
+void info_store_peers_json(Info* pInfo, const Json* jpeers) {
size_t len = json_object_array_length(jpeers);
if (len == 0)
return;
- if (len > MAX_PEERS)
- len = MAX_PEERS;
-
- pInfo->peers = api_info_array_init_from_length(len);
+ pInfo->peers = info_array_init_length(len);
for (size_t i = 0; i < pInfo->peers->length; i++)
strcpy(pInfo->peers->array[i]->symbol, json_object_get_string(
json_object_array_get_idx(jpeers, i)));
- api_info_array_store_data_batch(pInfo->peers, CHECK);
+ api_store_info_array(pInfo->peers, DATA_LEVEL_CHECK);
}
-void info_store_news_from_json(Info* pInfo, const Json* jnews) {
+void info_store_news_json(Info* pInfo, const Json* jnews) {
Json* idx, * headline, * source, * date, * summary, * url, * related;
size_t len = json_object_array_length(jnews);
if (len < (unsigned) pInfo->num_articles)
@@ -627,7 +625,7 @@ void info_store_news_from_json(Info* pInfo, const Json* jnews) {
break;
}
- pInfo->articles[i] = api_news_init();
+ pInfo->articles[i] = news_init();
if (headline != NULL)
strcpy(pInfo->articles[i]->headline, json_object_get_string(headline));
if (source != NULL)
@@ -654,7 +652,7 @@ void info_store_news_from_json(Info* pInfo, const Json* jnews) {
}
}
-void info_store_earnings_from_json(Info* pInfo, const Json* jearnings) {
+void info_store_earnings_json(Info* pInfo, const Json* jearnings) {
// ETFs don't report earnings
if (!json_object_is_type(json_object_object_get(jearnings, "earnings"), json_type_array))
return;
@@ -733,7 +731,7 @@ Info* info_array_find_symbol_recursive(const Info_Array* pInfo_Array, const char
return NULL;
}
-void api_ref_data_destroy(Ref_Data** phRef_Data) {
+void ref_data_destroy(Ref_Data** phRef_Data) {
if (*phRef_Data == NULL)
return;
@@ -748,7 +746,7 @@ void api_ref_data_destroy(Ref_Data** phRef_Data) {
*phRef_Data = NULL;
}
-void api_news_destroy(News** phNews) {
+void news_destroy(News** phNews) {
if (*phNews == NULL)
return;
@@ -756,7 +754,7 @@ void api_news_destroy(News** phNews) {
*phNews = NULL;
}
-void api_info_destroy(Info** phInfo) {
+void info_destroy(Info** phInfo) {
if (*phInfo == NULL)
return;
@@ -764,26 +762,25 @@ void api_info_destroy(Info** phInfo) {
free(pInfo->points);
if (pInfo->articles != NULL)
for (int i = 0; i < pInfo->num_articles; i++)
- api_news_destroy(&pInfo->articles[i]);
+ news_destroy(&pInfo->articles[i]);
if (pInfo->peers != NULL)
- api_info_array_destroy(&pInfo->peers);
+ info_array_destroy(&pInfo->peers);
free(pInfo->articles);
free(*phInfo);
*phInfo = NULL;
}
-void api_info_array_destroy(Info_Array** phInfo_Array) {
+void info_array_destroy(Info_Array** phInfo_Array) {
if (*phInfo_Array == NULL)
return;
Info_Array* pInfo_Array = *phInfo_Array;
for (size_t i = 0; i < pInfo_Array->length; i++)
- api_info_destroy(&pInfo_Array->array[i]);
+ info_destroy(&pInfo_Array->array[i]);
free(pInfo_Array->array);
- if (pInfo_Array->totals != NULL)
- api_info_destroy(&pInfo_Array->totals);
+ info_destroy(&pInfo_Array->totals);
free(*phInfo_Array);
*phInfo_Array = NULL;
} \ No newline at end of file
diff --git a/api.h b/api.h
index 49cac22e7909..566ca5e3d872 100644
--- a/api.h
+++ b/api.h
@@ -9,24 +9,24 @@
#define TICK_API_H
typedef enum api_providers {
- IEX, MORNINGSTAR, ALPHAVANTAGE, COINMARKETCAP
+ API_PROVIDER_IEX, API_PROVIDER_MORNINGSTAR,
+ API_PROVIDER_ALPHAVANTAGE, API_PROVIDER_COINMARKETCAP
} Api_Provider;
typedef enum data_level {
- ALL, CHECK, MISC, NEWS
+ DATA_LEVEL_ALL, DATA_LEVEL_CHECK, DATA_LEVEL_MISC, DATA_LEVEL_NEWS
} Data_Level;
-#define QUARTERS 4
-#define DATE_MAX_LENGTH 32
#define CELL_MAX_LENGTH 16
+#define DATE_MAX_LENGTH 32
#define SYMBOL_MAX_LENGTH 32
#define NAME_MAX_LENGTH 128
#define URL_MAX_LENGTH 2048
-#define INFO_TEXT_MAX 2048
+#define INFO_MAX_LENGTH 2048
#define NEWS_MAX_LENGTH 10500
+
+#define QUARTERS 4
#define EMPTY (-999)
-#define DEFAULT_NUM_ARTICLES 3
-#define MAX_PEERS 12
#include <stddef.h>
#include <curl/curl.h>
@@ -41,19 +41,17 @@ typedef struct ref_data {
} Ref_Data;
typedef struct news_article {
- char headline[INFO_TEXT_MAX];
- char source[INFO_TEXT_MAX];
+ char headline[INFO_MAX_LENGTH];
+ char source[INFO_MAX_LENGTH];
char date[DATE_MAX_LENGTH];
- char summary[INFO_TEXT_MAX];
+ char summary[INFO_MAX_LENGTH];
char url[URL_MAX_LENGTH];
- char related[INFO_TEXT_MAX];
+ char related[INFO_MAX_LENGTH];
} News;
-typedef struct info Info;
-
typedef struct info_array Info_Array;
-struct info {
+typedef struct info {
int api_provider; // IEX, MORNINGSTAR, ALPHAVANTAGE, COINMARKETCAP
/** API DATA **/
@@ -62,7 +60,7 @@ struct info {
char name[NAME_MAX_LENGTH]; // ex. Apple Inc.
char industry[NAME_MAX_LENGTH]; // ex. Computer Hardware
char website[URL_MAX_LENGTH]; // ex. apple.com
- char description[INFO_TEXT_MAX]; // Paragraph description of company
+ char description[INFO_MAX_LENGTH]; // Paragraph description of company
char ceo[NAME_MAX_LENGTH]; // ex. Timothy D. Cook
char issue_type[3]; /* ad – American Depository Receipt (ADR’s)
re – Real Estate Investment Trust (REIT’s)
@@ -141,7 +139,7 @@ struct info {
char fprofit_7d_percent[CELL_MAX_LENGTH]; // Profit since seven days ago %
char fprofit_30d[CELL_MAX_LENGTH]; // Profit since thirty days ago
char fprofit_30d_percent[CELL_MAX_LENGTH]; // Profit since thirty days ago %
-};
+} Info;
struct info_array {
Info** array;
@@ -149,33 +147,38 @@ struct info_array {
Info* totals;
};
-Ref_Data* api_ref_data_init_from_length(size_t length);
+/**
+ * Allocates a Ref_Data struct with length and returns a pointer to it.
+ * @param length
+ * @return Ref_Data*
+ */
+Ref_Data* ref_data_init_length(size_t length);
/**
* Allocates a News struct and returns a pointer to it.
* @return News*
*/
-News* api_news_init(void);
+News* news_init(void);
/**
* Allocates an Info struct and returns a pointer to it. All numbers are set to EMPTY, all strings are NULL
* terminated at length 0, and all pointers are set to NULL.
* @return Info*
*/
-Info* api_info_init(void);
+Info* info_init(void);
/**
* Allocates an Info_Array struct with length 0.
* @return Info_Array*
*/
-Info_Array* api_info_array_init(void);
+Info_Array* info_array_init(void);
/**
* Allocates an Info_Array struct with allocated length.
* @param length number of Info pointers to allocate
* @return Info_Array*
*/
-Info_Array* api_info_array_init_from_length(size_t length);
+Info_Array* info_array_init_length(size_t length);
/**
* Appends a security to an Info_Array.
@@ -185,31 +188,31 @@ Info_Array* api_info_array_init_from_length(size_t length);
void info_array_append(Info_Array* pInfo_Array, const char* symbol);
/**
- * writefunction for cURL HTTP GET/POST
+ * writefunction for cURL HTTP GET
* stolen from a nice man on stackoverflow
*/
-size_t api_string_writefunc(void* ptr, size_t size, size_t nmemb, String* pString);
+size_t string_writefunc(void* ptr, size_t size, size_t nmemb, String* pString);
/**
* Performs a HTTP GET. Response data is stored and returned in an allocated String*.
* @param url API url to GET
* @return NULL if error or no response from server. Otherwise, String* containing data.
*/
-String* api_curl_data(const char* url);
+String* api_curl_url(const char* url);
/**
* Calls IEX's batch API to store data in pInfo_Array. symbol must be a valid string in each Info
* @param pInfo_Array the Info_Array to fill
* @param data_level the level of data to store
*/
-void iex_batch_store_data_info_array(Info_Array* pInfo_Array, Data_Level data_level);
+void api_iex_store_info_array(Info_Array* pInfo_Array, Data_Level data_level);
/**
* Calls IEX's batch API to store data in pInfo. symbol must be a valid string in pInfo
* @param pInfo the Info to fill
* @param data_level the level of data to store
*/
-void iex_batch_store_data_info(Info* pInfo, Data_Level data_level);
+void api_iex_store_info(Info* pInfo, Data_Level data_level);
/**
* This function will only store stock and ETF data.
@@ -221,8 +224,8 @@ void iex_batch_store_data_info(Info* pInfo, Data_Level data_level);
* @param pInfo_Array the Info_Array
* @param data_level endpoints to query
*/
-String* iex_batch_get_data_string(char* symbol_array[SYMBOL_MAX_LENGTH], size_t len,
- Data_Level data_level);
+String* api_iex_get_data_string(char** symbol_array, size_t len,
+ Data_Level data_level);
/**
* Designed for threading
*
@@ -231,7 +234,7 @@ String* iex_batch_get_data_string(char* symbol_array[SYMBOL_MAX_LENGTH], size_t
* @param vpInfo Info*
* @return vpInfo on success, NULL on error
*/
-void* morningstar_store_info(void* vpInfo);
+void* api_morningstar_store_info(void* vpInfo);
/**
* Designed for threading
@@ -241,7 +244,7 @@ void* morningstar_store_info(void* vpInfo);
* @param vpInfo Info*
* @return vpInfo on Success, NULL on error
*/
-void* alphavantage_store_info(void* vpInfo);
+void* api_alphavantage_store_info(void* vpInfo);
/**
* Designed for threading
@@ -251,7 +254,7 @@ void* alphavantage_store_info(void* vpInfo);
* @param vpInfo Info*
* @return vpInfo on success, NULL on error
*/
-void* coinmarketcap_store_info(void* vpInfo);
+void* api_coinmarketcap_store_info(void* vpInfo);
/**
* Queries IEX, AlphaVantage, and Coinmarketcap to store api data in pInfo_Array. data_level will
@@ -259,7 +262,7 @@ void* coinmarketcap_store_info(void* vpInfo);
* @param pInfo_Array the Info_Array
* @param data_level the data level to store
*/
-void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_level);
+void api_store_info_array(Info_Array* pInfo_Array, Data_Level data_level);
/**
* Queries IEX, AlphaVantage, and Coinmarketcap to store api data in pInfo. data_level will
@@ -267,14 +270,14 @@ void api_info_array_store_data_batch(Info_Array* pInfo_Array, Data_Level data_le
* @param pInfo
* @param data_level
*/
-void api_info_store_data_batch(Info* pInfo, Data_Level data_level);
+void api_store_info(Info* pInfo, Data_Level data_level);
/**
* After API data and portfolio have already been collected, uses them to populate the Info fields current_value and
* all the profit fields.
* @param pInfo Info*
*/
-void info_store_check_data(Info* pInfo);
+void info_store_portfolio_data(Info* pInfo);
/**
* Adds up values of Info array and sets values in totals.
@@ -286,21 +289,21 @@ void info_array_store_totals(Info_Array* pInfo_Array);
* Returns a pointer to an Info_Array containing a list of all iex listed securities.
* @return Info_Array*
*/
-Ref_Data* iex_get_valid_symbols(void);
+Ref_Data* api_iex_store_ref_data(void);
/**
* Stores the data found in IEX formatted jobj in the Info_Array.
* @param pInfo_Array
* @param jobj
*/
-void info_array_store_all_from_json(Info_Array* pInfo_Array, const Json* jobj);
+void info_array_store_endpoints_json(Info_Array* pInfo_Array, const Json* jobj);
/**
* Stores the data found in IEX formatted jsymbol in the Info_Array.
* @param pInfo
* @param jsymbol
*/
-void info_store_all_from_json(Info* pInfo, const Json* jsymbol);
+void info_store_endpoints_json(Info* pInfo, const Json* jsymbol);
/**
* IEX quote endpoint.
@@ -308,7 +311,7 @@ void info_store_all_from_json(Info* pInfo, const Json* jsymbol);
* @param pInfo
* @param jquote
*/
-void info_store_quote_from_json(Info* pInfo, const Json* jquote);
+void info_store_quote_json(Info* pInfo, const Json* jquote);
/**
* IEX chart endpoint.
@@ -316,7 +319,7 @@ void info_store_quote_from_json(Info* pInfo, const Json* jquote);
* @param pInfo
* @param jchart
*/
-void info_store_chart_from_json(Info* pInfo, const Json* jchart);
+void info_store_chart_json(Info* pInfo, const Json* jchart);
/**
* IEX company endpoint.
@@ -324,7 +327,7 @@ void info_store_chart_from_json(Info* pInfo, const Json* jchart);
* @param pInfo
* @param jcompany
*/
-void info_store_company_from_json(Info* pInfo, const Json* jcompany);
+void info_store_company_json(Info* pInfo, const Json* jcompany);
/**
* IEX stats endpoint.
@@ -332,7 +335,7 @@ void info_store_company_from_json(Info* pInfo, const Json* jcompany);
* @param pInfo
* @param jstats
*/
-void info_store_stats_from_json(Info* pInfo, const Json* jstats);
+void info_store_stats_json(Info* pInfo, const Json* jstats);
/**
* IEX peers endpoint.
@@ -340,7 +343,7 @@ void info_store_stats_from_json(Info* pInfo, const Json* jstats);
* @param pInfo
* @param jpeers
*/
-void info_store_peers_from_json(Info* pInfo, const Json* jpeers);
+void info_store_peers_json(Info* pInfo, const Json* jpeers);
/**
* IEX news endpoint.
@@ -348,7 +351,7 @@ void info_store_peers_from_json(Info* pInfo, const Json* jpeers);
* @param pInfo
* @param jnews
*/
-void info_store_news_from_json(Info* pInfo, const Json* jnews);
+void info_store_news_json(Info* pInfo, const Json* jnews);
/**
* IEX earnings endpoint.
@@ -356,7 +359,7 @@ void info_store_news_from_json(Info* pInfo, const Json* jnews);
* @param pInfo
* @param jearnings
*/
-void info_store_earnings_from_json(Info* pInfo, const Json* jearnings);
+void info_store_earnings_json(Info* pInfo, const Json* jearnings);
/**
* Searches through an Info_Array and returns a ponter to the Info which has the same symbol as
@@ -403,24 +406,24 @@ Info* info_array_find_symbol_recursive(const Info_Array* pInfo_Array, const char
* Destroys Ref_Data object and frees memory. Sets the pointer of the Ref_Data to NULL
* @param phRef_Data the Ref_Data to destroy
*/
-void api_ref_data_destroy(Ref_Data** phRef_Data);
+void ref_data_destroy(Ref_Data** phRef_Data);
/**
* Destroys News object and frees memory. Sets the pointer of the News to NULL
* @param phNews the News to destroy
*/
-void api_news_destroy(News** phNews);
+void news_destroy(News** phNews);
/**
* Destroys Info object and frees memory. Sets the pointer to the Info to NULL
* @param phInfo the Info to destroy
*/
-void api_info_destroy(Info** phInfo);
+void info_destroy(Info** phInfo);
/**
* Destroys Info_Array object and frees memory. Sets the pointer to the Info to NULL
* @param phInfo_Array the Info_Array to destroy
*/
-void api_info_array_destroy(Info_Array** phInfo_Array);
+void info_array_destroy(Info_Array** phInfo_Array);
#endif \ No newline at end of file
diff --git a/curses_win.c b/curses_win.c
index 3dad17f33eb8..a611da435548 100644
--- a/curses_win.c
+++ b/curses_win.c
@@ -8,9 +8,9 @@ void portfolio_printw(void) {
Info_Array* portfolio_data = portfolio_info_array_init_from_portfolio_string(
pString);
if (portfolio_data != NULL) {
- api_info_array_store_data_batch(portfolio_data, CHECK);
+ api_store_info_array(portfolio_data, DATA_LEVEL_CHECK);
info_array_portfolio_printw(portfolio_data);
- api_info_array_destroy(&portfolio_data);
+ info_array_destroy(&portfolio_data);
}
string_destroy(&pString);
}
@@ -34,7 +34,7 @@ void info_array_portfolio_printw(Info_Array* portfolio_data) {
if (cols < 110) {
endwin();
puts("Terminal too small.");
- api_info_array_destroy(&portfolio_data);
+ info_array_destroy(&portfolio_data);
return;
}
@@ -160,13 +160,13 @@ void portfolio_print_stock(const char* symbol) {
if (i == len)
GOTO_CLEAN_MSG("Your portfolio does not contain any of this security.")
- Info* info = api_info_init();
+ Info* info = info_init();
strcpy(info->symbol, symbol);
- api_info_store_data_batch(info, CHECK);
+ api_store_info(info, DATA_LEVEL_CHECK);
info->amount = json_object_get_double(json_object_object_get(json_object_array_get_idx(jobj, i), "Shares"));
info->total_spent = json_object_get_double(json_object_object_get(json_object_array_get_idx(jobj, i), "USD_Spent"));
- info_store_check_data(info);
+ info_store_portfolio_data(info);
printf(" AMOUNT SYMBOL VALUE SPENT PROFIT (%%) 24H (%%) 7D "
" (%%) 30D "
" (%%)\n%8.2lf %6s %8.2lf %8.2lf %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%) %8.2lf (%6.2lf%%)\n",
@@ -174,24 +174,24 @@ void portfolio_print_stock(const char* symbol) {
info->profit_total_percent, info->profit_last_close, info->profit_last_close_percent,
info->profit_7d, info->profit_7d_percent, info->profit_30d, info->profit_30d_percent);
- api_info_destroy(&info);
+ info_destroy(&info);
cleanup:
json_object_put(jobj);
string_destroy(&pString);
}
void interface_print(const char* symbol) {
- Info* symbol_info = api_info_init();
+ Info* symbol_info = info_init();
strcpy(symbol_info->symbol, symbol);
- api_info_store_data_batch(symbol_info, ALL);
+ api_store_info(symbol_info, DATA_LEVEL_ALL);
if (symbol_info->api_provider == EMPTY) {
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
RET_MSG("Invalid symbol.")
}
if (symbol_info->points == NULL || symbol_info->name[0] == '\0') { // If not IEX print to stdout
info_print(symbol_info);
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
return;
}
@@ -238,7 +238,7 @@ void interface_print(const char* symbol) {
cleanup:
endwin();
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
}
void header_printw(WINDOW* window, const Info* symbol_info) {
@@ -355,19 +355,19 @@ void news_print(const char* symbol, int num_articles) {
if (num_articles > 50 || num_articles < 1)
RET_MSG("You cannot request more than 50 articles.");
- Info* symbol_info = api_info_init();
+ Info* symbol_info = info_init();
strcpy(symbol_info->symbol, symbol);
symbol_info->num_articles = num_articles;
- api_info_store_data_batch(symbol_info, NEWS);
+ api_store_info(symbol_info, DATA_LEVEL_NEWS);
if (symbol_info->api_provider == EMPTY) {
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
RET_MSG("Invalid symbol");
}
for (int i = 0; i < symbol_info->num_articles; i++)
printf("%s | %s | %s\n%s\n%s | Related: %s\n\n",
symbol_info->articles[i]->headline, symbol_info->articles[i]->source, symbol_info->articles[i]->date,
symbol_info->articles[i]->summary, symbol_info->articles[i]->url, symbol_info->articles[i]->related);
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
}
void news_printw(WINDOW* window, const Info* symbol_info) {
@@ -396,21 +396,21 @@ void peers_printw(WINDOW* window, const Info* symbol_info) {
}
void graph_print(const char* symbol, const char* symbol2) {
- Info* symbol_info = api_info_init(), * symbol_info2 = NULL;
+ Info* symbol_info = info_init(), * symbol_info2 = NULL;
strcpy(symbol_info->symbol, symbol);
- api_info_store_data_batch(symbol_info, CHECK);
+ api_store_info(symbol_info, DATA_LEVEL_CHECK);
if (symbol_info->api_provider == EMPTY || symbol_info->points == NULL) {
- api_info_destroy(&symbol_info);
+ info_destroy(&symbol_info);
RET_MSG("Invalid symbol")
}
if (symbol2 != NULL) {
- symbol_info2 = api_info_init();
+ symbol_info2 = info_init();
strcpy(symbol_info2->symbol, symbol2);
- api_info_store_data_batch(symbol_info2, CHECK);
+ api_store_info(symbol_info2, DATA_LEVEL_CHECK);
if (symbol_info2->api_provider == EMPTY || symbol_info2->points == NULL) {
- api_info_destroy(&symbol_info);
- api_info_destroy(&symbol_info2);
+ info_destroy(&symbol_info);
+ info_destroy(&symbol_info2);
RET_MSG("Invalid symbol")
}
}
@@ -421,8 +421,8 @@ void graph_print(const char* symbol, const char* symbol2) {
}
graph_printw(stdscr, symbol_info, symbol_info2);
- api_info_destroy(&symbol_info);
- api_info_destroy(&symbol_info2);
+ info_destroy(&symbol_info);
+ info_destroy(&symbol_info2);
endwin();
}
diff --git a/gtk_win.c b/gtk_win.c
index bb10bf6a3634..78ed4b74b3e2 100644
--- a/gtk_win.c
+++ b/gtk_win.c
@@ -11,7 +11,7 @@ void window_main(void) {
app.portfolio_data = NULL;
app.portfolio_string = NULL;
app.builder = gtk_builder_new();
- app.info_cache = api_info_array_init();
+ app.info_cache = info_array_init();
app.iex_ref_data = NULL;
app.password[0] = '\0';
app.last_reload = 0;
@@ -36,7 +36,7 @@ void window_main(void) {
void check_list_create_from_string(void) {
GtkListStore* pListStore = GTK_LIST_STORE(GET_OBJECT("check_list"));
gtk_list_store_clear(pListStore); // Clear in case reloading
- api_info_array_destroy(&app.portfolio_data); // Destroy in case reloading
+ info_array_destroy(&app.portfolio_data); // Destroy in case reloading
app.portfolio_data = portfolio_info_array_init_from_portfolio_string(app.portfolio_string);
if (app.portfolio_data == NULL) // Empty JSON array
return;
@@ -138,12 +138,12 @@ void on_load_button_clicked(GtkButton* button) {
}
// Destroy and create a new Info_Array with portfolio and api data
- api_info_array_destroy(&app.portfolio_data);
+ info_array_destroy(&app.portfolio_data);
app.portfolio_data = portfolio_info_array_init_from_portfolio_string(app.portfolio_string);
if (app.portfolio_data != NULL) { // If file is not a length 0 JSON array
check_list_create_from_string();
app.last_reload = now;
- api_info_array_store_data_batch(app.portfolio_data, CHECK);
+ api_store_info_array(app.portfolio_data, DATA_LEVEL_CHECK);
check_list_add_api_data();
}
@@ -331,8 +331,8 @@ void on_check_window_destroy(void) {
// Destroy String and Info_Array and exit main GTK loop
string_destroy(&app.portfolio_string);
- api_info_array_destroy(&app.portfolio_data);
- api_ref_data_destroy(&app.iex_ref_data);
+ info_array_destroy(&app.portfolio_data);
+ ref_data_destroy(&app.iex_ref_data);
gtk_main_quit();
}
@@ -367,7 +367,7 @@ void on_search_entry_focus_in_event(GtkWidget* search_entry, GdkEvent* event) {
if (app.iex_ref_data != NULL) // If ref data has already been loaded return
return;
- app.iex_ref_data = iex_get_valid_symbols();
+ app.iex_ref_data = api_iex_store_ref_data();
GtkListStore* list_store = GTK_LIST_STORE(GET_OBJECT("search_entry_completion_store"));
GtkTreeIter iter;
for (size_t i = 0; i < app.iex_ref_data->length; i++) {
@@ -395,8 +395,8 @@ void symbol_show_info(const char* symbol) {
if (pInfo == NULL) { // Append to cache
if (app.info_cache->length == INFO_ARRAY_CACHE_MAX) {
- api_info_array_destroy(&app.info_cache);
- app.info_cache = api_info_array_init();
+ info_array_destroy(&app.info_cache);
+ app.info_cache = info_array_init();
}
info_array_append(app.info_cache, symbol);
@@ -404,9 +404,9 @@ void symbol_show_info(const char* symbol) {
}
if (pInfo->price == EMPTY)
- api_info_store_data_batch(pInfo, ALL);
+ api_store_info(pInfo, DATA_LEVEL_ALL);
else if (pInfo->name[0] == '\0')
- api_info_store_data_batch(pInfo, MISC);
+ api_store_info(pInfo, DATA_LEVEL_MISC);
if (pInfo->peers != NULL)
format_cells(pInfo->peers);
@@ -497,7 +497,7 @@ void list_store_update(void) {
// Recreate Info_Array
check_list_create_from_string(); // Will set app.portfolio_data if success
if (app.portfolio_data != NULL) {
- api_info_array_store_data_batch(app.portfolio_data, CHECK);
+ api_store_info_array(app.portfolio_data, DATA_LEVEL_CHECK);
check_list_add_api_data();
}
}
diff --git a/portfolio.c b/portfolio.c
index 83ad3f7987bd..9bbc6e1944c6 100644
--- a/portfolio.c
+++ b/portfolio.c
@@ -82,15 +82,15 @@ int portfolio_modify_string(String* pString, const char* symbol, double quantity
}
if (strcmp("USD$", symbol) != 0) { // Check that the symbol is valid, except if it's USD
- Info* data = api_info_init();
+ Info* data = info_init();
strcpy(data->symbol, symbol);
- api_info_store_data_batch(data, CHECK);
+ api_store_info(data, DATA_LEVEL_CHECK);
if (data->api_provider == EMPTY) {// If NULL response from APIs, it's invalid
- api_info_destroy(&data);
+ info_destroy(&data);
status = 1;
GOTO_CLEAN_MSG("Invalid symbol.")
}
- api_info_destroy(&data);
+ info_destroy(&data);
}
Json* new_object = json_object_new_object(); // Creates new array index and adds values to it
@@ -153,7 +153,7 @@ Info_Array* portfolio_info_array_init_from_portfolio_string(String* pString) {
RETNULL_MSG("Your portfolio is empty.");
}
- Info_Array* portfolio_data = api_info_array_init_from_length(length);
+ Info_Array* portfolio_data = info_array_init_length(length);
portfolio_data->totals->total_spent = 0;
for (size_t i = 0; i < portfolio_data->length; i++) {
strcpy(portfolio_data->array[i]->symbol,