Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions homework_4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ project(homework_4)
set(homeworkName "${PROJECT_NAME}")

add_subdirectory(task_1)
add_subdirectory(task_2)
2 changes: 2 additions & 0 deletions homework_4/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Homework 4

[Task 1. Binary representation](/homework_4/task_1)

[Task 2. Phone database](/homework_4/task_2)
1 change: 1 addition & 0 deletions homework_4/task_2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
phoneDatabase
9 changes: 9 additions & 0 deletions homework_4/task_2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
project("${homeworkName}_task_2")

add_library(phoneBook database.c personEntry.c)

add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} phoneBook)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test phoneBook)
149 changes: 149 additions & 0 deletions homework_4/task_2/database.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#include "database.h"

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DB_SIGNATURE "#!hw_phonebook"
#define DB_BEGIN "{{"
#define DB_END "}}"

Database *createDatabase() {
Database *database = malloc(sizeof(Database));
if (database == NULL) {
return NULL;
}
database->entriesCount = 0;

return database;
}

bool addEntry(Database *database, PersonEntry entry) {
if (database == NULL) {
return false;
}

// entries count cannot be more than DB_MAX_ENTRIES, but check this case too
if (database->entriesCount >= DB_MAX_ENTRIES) {
return false;
}

database->entries[database->entriesCount] = entry;
++database->entriesCount;
return true;
}

#pragma region Save/Load

bool saveDatabase(FILE *stream, Database *database) {
if (stream == NULL) {
return false;
}

if (database == NULL) {
return false;
}

fprintf(stream, "%s\n", DB_SIGNATURE);
fprintf(stream, "%s\n", DB_BEGIN);

for (int i = 0; i < database->entriesCount; ++i) {
PersonEntry entry = database->entries[i];
fprintf(stream, "%s\n", entry.personName);
fprintf(stream, "%s\n", entry.phoneNumber);
}

fprintf(stream, "%s\n", DB_END);

return true;
}

// reads line and sets first '\n' to '\0'
bool tryReadLine(char *buffer, int count, FILE *file) {
if (fgets(buffer, count, file) == NULL || feof(file)) {
return false;
}

for (int i = 0; i < count; ++i) {
if (buffer[i] == '\n') {
buffer[i] = '\0';
break;
}
}

return true;
}

Database *loadDatabase(FILE *stream) {
if (stream == NULL) {
return NULL;
}

Database *database = createDatabase();

if (database == NULL) {
return NULL;
}

char buffer[256] = { 0 };

if (!tryReadLine(buffer, sizeof(buffer), stream) && strcmp(buffer, DB_SIGNATURE) != 0) {
return NULL;
}

if (!tryReadLine(buffer, sizeof(buffer), stream) && strcmp(buffer, DB_BEGIN) != 0) {
return NULL;
}

while (true) {
// person name or db end anchor
if (!tryReadLine(buffer, sizeof(buffer), stream)) {
return NULL;
}

if (strcmp(buffer, DB_END) == 0) {
break;
}

char *personName = strdup(buffer);
if (personName == NULL) {
return NULL;
}

// phone number
if (!tryReadLine(buffer, sizeof(buffer), stream)) {
return NULL;
}

PhoneNumber phoneNumber;
if (!tryParsePhoneNumber(buffer, &phoneNumber)) {
return NULL;
}

PersonEntry entry = {
.personName = personName,
.phoneNumber = phoneNumber
};

if (!addEntry(database, entry)) {
// no space left, not an error
break;
}
}

return database;
}

#pragma endregion

void disposeDatabase(Database *database) {
if (database == NULL) {
return;
}

for (int i = 0; i < database->entriesCount; ++i) {
disposeEntry(&database->entries[i]);
}
free(database);
}
38 changes: 38 additions & 0 deletions homework_4/task_2/database.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <stdbool.h>
#include <stdio.h>

#include "personEntry.h"

#define DB_MAX_ENTRIES 100

typedef struct {
int entriesCount;
PersonEntry entries[DB_MAX_ENTRIES];
} Database;

/// @brief Creates empty database
/// @return `Database` if created successfully, `NULL` otherwise
Database *createDatabase();

/// @brief Adds a person entry to database
/// @param database Pointer to database
/// @param entry Entry to add
/// @return `true` if added successfully, `false` otherwise (no space in database left)
bool addEntry(Database *database, PersonEntry entry);

/// @brief Saves database to specified stream
/// @param stream Stream to save database to
/// @param database Pointer to database
/// @return `true` if saved successfully, `false` otherwise
bool saveDatabase(FILE *stream, Database *database);

/// @brief Loads database from specified file stream
/// @param stream Stream to load database from
/// @return `Database` if loaded successfully, `NULL` otherwise
Database *loadDatabase(FILE *stream);

/// @brief Disposes database and all of its entries
/// @param database Database to dispose (can be `NULL`)
void disposeDatabase(Database *database);
Loading