#include "CSV_Utilities.hpp" extern "C" { #include "stdlib.h" #include "string.h" #include "stdio.h" } CSV_Table::CSV_Table() { this->column_count = 0; this->mem_use = 0; this->max_element_depth = 0; this->Column_List_End = this->Column_List_Head = nullptr; } CSV_Table::~CSV_Table() { this->reset(); } void CSV_Table::reset() { // 清理尾指针 this->Column_List_End = nullptr; this->max_element_depth = 0; this->column_count = 0; this->mem_use = 0; // 清理头指针及其内容 if (this->Column_List_Head != nullptr) { // 释放列 while (this->Column_List_Head != nullptr) { decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; // 释放单元格列表 while (p_target_column->Cell_List_Head != nullptr) { decltype(p_target_column->Cell_List_Head) p_target_cell = p_target_column->Cell_List_Head; // 释放单元格内容 if (p_target_cell->content_str != nullptr) free(p_target_cell->content_str); p_target_column->Cell_List_Head = p_target_cell->p_next_cell; free(p_target_cell->content_str); } // 释放标题 if (p_target_column->column_title_str != nullptr) free(p_target_column->column_title_str); this->Column_List_Head = p_target_column->p_next_column; free(p_target_column); } } } CSV_Type::CSV_Err CSV_Table::append_column(const char *title_name_str) { // 开辟新节点 decltype(this->Column_List_Head) p_new_column = (decltype(this->Column_List_Head))malloc(sizeof(*(this->Column_List_Head))); if (p_new_column == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_column); // 节点初始化 p_new_column->Cell_List_Head = p_new_column->Cell_List_End = nullptr; p_new_column->p_next_column = nullptr; p_new_column->element_count = 0; // 存储列标题名 if (title_name_str != nullptr) { char *p_title = (char *)malloc(strlen(title_name_str) + 1); // +1 for '\0' if (p_title == nullptr) { free(p_new_column); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(title_name_str) + 1; strcpy(p_title, title_name_str); p_new_column->column_title_str = p_title; } else p_new_column->column_title_str = nullptr; // 插入列链表 if (this->column_count == 0) this->Column_List_End = this->Column_List_Head = p_new_column; else { this->Column_List_End->p_next_column = p_new_column; this->Column_List_End = p_new_column; } this->column_count++; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::insert_column_after(const char *target_column_title_str, const char *title_name_str) { size_t count = 0; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; while (p_target_column != nullptr) { if (!strcmp(p_target_column->column_title_str, target_column_title_str)) return this->insert_column_after(count, title_name_str); p_target_column = p_target_column->p_next_column; count++; } return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; } CSV_Type::CSV_Err CSV_Table::insert_column_after(size_t target_column_position, const char *title_name_str) { if (!(((target_column_position + 1) <= this->column_count) || ((target_column_position == 0) && (this->column_count == 0)))) return CSV_Type::CSV_ERROR_ILLEGAL_COLUMN_POSITION; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; for (size_t count = 0; count < target_column_position; count++) p_target_column = p_target_column->p_next_column; // 开辟新节点 decltype(p_target_column) p_new_column = (decltype(p_target_column))malloc(sizeof(*(p_target_column))); if (p_new_column == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_column); // 节点初始化 p_new_column->Cell_List_Head = p_new_column->Cell_List_End = nullptr; p_new_column->p_next_column = nullptr; p_new_column->element_count = 0; // 存储列标题名 if (title_name_str != nullptr) { char *p_title = (char *)malloc(strlen(title_name_str) + 1); // +1 for '\0' if (p_title == nullptr) { free(p_new_column); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(title_name_str) + 1; strcpy(p_title, title_name_str); p_new_column->column_title_str = p_title; } else p_new_column->column_title_str = nullptr; // 内部列表为空 if (this->column_count == 0) this->Column_List_Head = this->Column_List_End = p_new_column; else { // 链接节点 p_new_column->p_next_column = p_target_column->p_next_column; p_target_column->p_next_column = p_new_column; // 目标位置在末尾时 if (target_column_position == this->column_count - 1) this->Column_List_End = p_new_column; } this->column_count++; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::insert_column_before(const char *target_column_title_str, const char *title_name_str) { size_t count = 0; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; while (p_target_column != nullptr) { if (!strcmp(p_target_column->column_title_str, target_column_title_str)) return this->insert_column_before(count, title_name_str); p_target_column = p_target_column->p_next_column; count++; } return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; } CSV_Type::CSV_Err CSV_Table::insert_column_before(size_t target_column_position, const char *title_name_str) { if (!(((target_column_position + 1) <= this->column_count) || ((target_column_position == 0) && (this->column_count == 0)))) return CSV_Type::CSV_ERROR_ILLEGAL_COLUMN_POSITION; decltype(this->Column_List_Head) p_pre_column = this->Column_List_Head; decltype(this->Column_List_Head) p_target_column = this->column_count > 0 ? this->Column_List_Head->p_next_column : nullptr; for (size_t count = 1; count < target_column_position; count++) { p_pre_column = p_pre_column->p_next_column; p_target_column = p_target_column->p_next_column; } // 开辟新节点 decltype(p_target_column) p_new_column = (decltype(p_target_column))malloc(sizeof(*(p_target_column))); if (p_new_column == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_column); // 节点初始化 p_new_column->Cell_List_Head = p_new_column->Cell_List_End = nullptr; p_new_column->p_next_column = nullptr; p_new_column->element_count = 0; // 存储列标题名 if (title_name_str != nullptr) { char *p_title = (char *)malloc(strlen(title_name_str) + 1); // +1 for '\0' if (p_title == nullptr) { free(p_new_column); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(title_name_str) + 1; strcpy(p_title, title_name_str); p_new_column->column_title_str = p_title; } else p_new_column->column_title_str = nullptr; // 链接节点 if (this->column_count == 0) this->Column_List_Head = this->Column_List_End = p_new_column; else { if (target_column_position == 0) { // 目标为表头 p_new_column->p_next_column = this->Column_List_Head; this->Column_List_Head = p_new_column; } else { p_new_column->p_next_column = p_target_column; p_pre_column->p_next_column = p_new_column; } } this->column_count++; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::append_cell(const char *target_column_title_str, const char *cell_content_str) { size_t count = 0; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; while (p_target_column != nullptr) { if (!strcmp(p_target_column->column_title_str, target_column_title_str)) return this->append_cell(count, cell_content_str); p_target_column = p_target_column->p_next_column; count++; } return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; } CSV_Type::CSV_Err CSV_Table::append_cell(size_t target_column_position, const char *cell_content_str) { if ((target_column_position + 1) > this->column_count) return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; for (size_t count = 0; count < target_column_position; count++) p_target_column = p_target_column->p_next_column; decltype(p_target_column->Cell_List_Head) p_new_cell = (decltype(p_target_column->Cell_List_Head))malloc(sizeof(*(p_target_column->Cell_List_Head))); if (p_new_cell == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_cell); if (cell_content_str != nullptr) { char *p_content = (char *)malloc(strlen(cell_content_str) + 1); // +1 for '\0' if (p_content == nullptr) { free(p_new_cell); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(cell_content_str) + 1; strcpy(p_content, cell_content_str); p_new_cell->content_str = p_content; } else p_new_cell->content_str = nullptr; p_new_cell->p_next_cell = nullptr; if (p_target_column->element_count == 0) p_target_column->Cell_List_Head = p_target_column->Cell_List_End = p_new_cell; else { p_target_column->Cell_List_End->p_next_cell = p_new_cell; p_target_column->Cell_List_End = p_new_cell; } p_target_column->element_count++; if (p_target_column->element_count > this->max_element_depth) this->max_element_depth = p_target_column->element_count; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::insert_cell_after(const char *target_column_title_str, size_t target_cell_position, const char *cell_content_str) { size_t count = 0; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; while (p_target_column != nullptr) { if (!strcmp(p_target_column->column_title_str, target_column_title_str)) return this->insert_cell_after(count, target_cell_position, cell_content_str); p_target_column = p_target_column->p_next_column; count++; } return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; } CSV_Type::CSV_Err CSV_Table::insert_cell_after(size_t target_column_position, size_t target_cell_position, const char *cell_content_str) { if ((target_column_position + 1) > this->column_count) return CSV_Type::CSV_ERROR_ILLEGAL_COLUMN_POSITION; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; for (size_t count = 0; count < target_column_position; count++) p_target_column = p_target_column->p_next_column; if (!(((target_cell_position + 1) <= p_target_column->element_count) || ((target_cell_position == 0) && (p_target_column->element_count == 0)))) return CSV_Type::CSV_ERROR_ILLEGAL_CELL_POSITION; decltype(p_target_column->Cell_List_Head) p_new_cell = (decltype(p_target_column->Cell_List_Head))malloc(sizeof(*(p_target_column->Cell_List_Head))); if (p_new_cell == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_cell); if (cell_content_str != nullptr) { char *p_content = (char *)malloc(strlen(cell_content_str) + 1); // +1 for '\0' if (p_content == nullptr) { free(p_new_cell); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(cell_content_str) + 1; strcpy(p_content, cell_content_str); p_new_cell->content_str = p_content; } else p_new_cell->content_str = nullptr; if (p_target_column->element_count == 0) { p_new_cell->p_next_cell = nullptr; p_target_column->Cell_List_Head = p_target_column->Cell_List_End = p_new_cell; } else { decltype(p_new_cell) p_target_cell = p_target_column->Cell_List_Head; for (size_t count = 0; count < target_cell_position; count++) p_target_cell = p_target_cell->p_next_cell; p_new_cell->p_next_cell = p_target_cell->p_next_cell; p_target_cell->p_next_cell = p_new_cell; if ((target_cell_position + 1) == p_target_column->element_count) p_target_column->Cell_List_End = p_new_cell; } p_target_column->element_count++; if (p_target_column->element_count > this->max_element_depth) this->max_element_depth = p_target_column->element_count; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::insert_cell_before(const char *target_column_title_str, size_t target_cell_position, const char *cell_content_str) { size_t count = 0; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; while (p_target_column != nullptr) { if (!strcmp(p_target_column->column_title_str, target_column_title_str)) return this->insert_cell_before(count, target_cell_position, cell_content_str); p_target_column = p_target_column->p_next_column; count++; } return CSV_Type::CSV_ERROR_COLUMN_NOT_FOUND; } CSV_Type::CSV_Err CSV_Table::insert_cell_before(size_t target_column_position, size_t target_cell_position, const char *cell_content_str) { if ((target_column_position + 1) > this->column_count) return CSV_Type::CSV_ERROR_ILLEGAL_COLUMN_POSITION; decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; for (size_t count = 0; count < target_column_position; count++) p_target_column = p_target_column->p_next_column; if (!(((target_cell_position + 1) <= p_target_column->element_count) || ((target_cell_position == 0) && (p_target_column->element_count == 0)))) return CSV_Type::CSV_ERROR_ILLEGAL_CELL_POSITION; decltype(p_target_column->Cell_List_Head) p_new_cell = (decltype(p_target_column->Cell_List_Head))malloc(sizeof(*(p_target_column->Cell_List_Head))); if (p_new_cell == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; this->mem_use += sizeof(*p_new_cell); if (cell_content_str != nullptr) { char *p_content = (char *)malloc(strlen(cell_content_str) + 1); // +1 for '\0' if (p_content == nullptr) { free(p_new_cell); return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; } this->mem_use += strlen(cell_content_str) + 1; strcpy(p_content, cell_content_str); p_new_cell->content_str = p_content; } else p_new_cell->content_str = nullptr; if (p_target_column->element_count == 0) { p_new_cell->p_next_cell = nullptr; p_target_column->Cell_List_Head = p_target_column->Cell_List_End = p_new_cell; } else { if (target_cell_position == 0) { p_new_cell->p_next_cell = p_target_column->Cell_List_Head; p_target_column->Cell_List_Head = p_new_cell; } else { decltype(p_new_cell) p_pre_target_cell = p_target_column->Cell_List_Head; for (size_t count = 0; count < target_cell_position - 1; count++) p_pre_target_cell = p_pre_target_cell->p_next_cell; p_new_cell->p_next_cell = p_pre_target_cell->p_next_cell; p_pre_target_cell->p_next_cell = p_new_cell; } } p_target_column->element_count++; if (p_target_column->element_count > this->max_element_depth) this->max_element_depth = p_target_column->element_count; return CSV_Type::CSV_ERROR_NONE; } CSV_Type::CSV_Err CSV_Table::export_to_file(const char *file_name_str) { // 打开文件 FILE *p_file = fopen(file_name_str, "wb"); if (p_file == nullptr) return CSV_Type::CSV_ERROR_FILE_CREATE_FAILED; // 横向元素表 decltype(this->Column_List_Head->Cell_List_Head) *p_parallel_cell_list = nullptr; // 输出内容 if (this->column_count != 0) { p_parallel_cell_list = (decltype(this->Column_List_Head->Cell_List_Head) *)malloc(sizeof(*this->Column_List_Head->Cell_List_Head) * this->column_count); if (p_parallel_cell_list == nullptr) return CSV_Type::CSV_ERROR_MEM_ALLOCATE_FAILED; // 输出标题及填充横向列表 { size_t count = 0; for (decltype(this->Column_List_Head) p_target_column = this->Column_List_Head; p_target_column != nullptr; p_target_column = p_target_column->p_next_column) { if (fprintf(p_file, strstr(p_target_column->column_title_str, ",") ? "\"%s\"," : "%s,", p_target_column->column_title_str) < 0) goto file_write_error; p_parallel_cell_list[count] = p_target_column->Cell_List_Head; count++; } fseek(p_file, -1, SEEK_CUR); if (fprintf(p_file, "\r\n") < 0) goto file_write_error; } // 输出横向行内容 { for (size_t row_count = 0; row_count < this->max_element_depth; row_count++) { for (size_t column_count = 0; column_count < this->column_count; column_count++) { if (p_parallel_cell_list[column_count] != nullptr) { if (fprintf(p_file, strstr(p_parallel_cell_list[column_count]->content_str, ",") ? "\"%s\"," : "%s,", p_parallel_cell_list[column_count]->content_str) < 0) goto file_write_error; p_parallel_cell_list[column_count] = p_parallel_cell_list[column_count]->p_next_cell; } else { if (fprintf(p_file, ",") < 0) goto file_write_error; } } fseek(p_file, -1, SEEK_CUR); if (fprintf(p_file, "\r\n") < 0) goto file_write_error; } } free(p_parallel_cell_list); } fclose(p_file); return CSV_Type::CSV_ERROR_NONE; // 写入错误处理 file_write_error: if (p_parallel_cell_list != nullptr) free(p_parallel_cell_list); fclose(p_file); return CSV_Type::CSV_ERROR_FILE_WRITE_FAILED; }