1
Fork 0

Initial Commit

This commit is contained in:
Guillem 2021-10-19 20:04:13 +02:00
commit e6a48b8c0e
25 changed files with 2654 additions and 0 deletions

12
Makefile Normal file
View file

@ -0,0 +1,12 @@
.PHONY: clean All
All:
@echo "----------Building project:[ UOCContacts - Debug ]----------"
@cd "UOCContacts" && "$(MAKE)" -f "UOCContacts.mk"
@echo "----------Building project:[ UOC20211 - Debug ]----------"
@"$(MAKE)" -f "UOC20211.mk"
clean:
@echo "----------Cleaning project:[ UOCContacts - Debug ]----------"
@cd "UOCContacts" && "$(MAKE)" -f "UOCContacts.mk" clean
@echo "----------Cleaning project:[ UOC20211 - Debug ]----------"
@"$(MAKE)" -f "UOC20211.mk" clean

4
README.txt Normal file
View file

@ -0,0 +1,4 @@
gsboeck@uoc.edu
Solà i Boeck, Guillem
Fedora release 34 (Thirty Four) x86_64
gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)

143
UOC20211.mk Normal file
View file

@ -0,0 +1,143 @@
##
## Auto Generated makefile by CodeLite IDE
## any manual changes will be erased
##
## Debug
ProjectName :=UOC20211
ConfigurationName :=Debug
WorkspacePath :=W:/Docencia/PP/20211/PR1/UOC20211
ProjectPath :=W:/Docencia/PP/20211/PR1/UOC20211
IntermediateDirectory :=./bin/Debug
OutDir := $(IntermediateDirectory)
CurrentFileName :=
CurrentFilePath :=
CurrentFileFullPath :=
User :=xavie
Date :=11/10/2021
CodeLitePath :="C:/Program Files/CodeLite"
LinkerName :=C:/TDM-GCC-64/bin/g++.exe
SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC
ObjectSuffix :=.o
DependSuffix :=.o.d
PreprocessSuffix :=.i
DebugSwitch :=-g
IncludeSwitch :=-I
LibrarySwitch :=-l
OutputSwitch :=-o
LibraryPathSwitch :=-L
PreprocessorSwitch :=-D
SourceSwitch :=-c
OutputFile :=./bin/$(ProjectName)d
Preprocessors :=
ObjectSwitch :=-o
ArchiveOutputSwitch :=
PreprocessOnlySwitch :=-E
ObjectsFileList :="UOC20211.txt"
PCHCompileFlags :=
MakeDirCommand :=makedir
RcCmpOptions :=
RcCompilerName :=C:/TDM-GCC-64/bin/windres.exe
LinkOptions :=
IncludePath := $(IncludeSwitch). $(IncludeSwitch). $(IncludeSwitch)test/include $(IncludeSwitch)UOCContacts/include
IncludePCH :=
RcIncludePath :=
Libs := $(LibrarySwitch)UOCContactsd
ArLibs := "libUOCContactsd.a"
LibPath := $(LibraryPathSwitch). $(LibraryPathSwitch)./lib
##
## Common variables
## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables
##
AR := C:/TDM-GCC-64/bin/ar.exe rcu
CXX := C:/TDM-GCC-64/bin/g++.exe
CC := C:/TDM-GCC-64/bin/gcc.exe
CXXFLAGS := -g -O0 -Wall $(Preprocessors)
CFLAGS := -g -O0 -Wall $(Preprocessors)
ASFLAGS :=
AS := C:/TDM-GCC-64/bin/as.exe
##
## User defined environment variables
##
CodeLiteDir:=C:\Program Files\CodeLite
Objects0=$(IntermediateDirectory)/src_main.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix)
Objects=$(Objects0)
##
## Main Build Targets
##
.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs
all: $(OutputFile)
$(OutputFile): $(IntermediateDirectory)/.d ".build-debug\UOCContacts" $(Objects)
@$(MakeDirCommand) $(@D)
@echo "" > $(IntermediateDirectory)/.d
@echo $(Objects0) > $(ObjectsFileList)
$(LinkerName) $(OutputSwitch)$(OutputFile) @$(ObjectsFileList) $(LibPath) $(Libs) $(LinkOptions)
".build-debug\UOCContacts":
@$(MakeDirCommand) ".build-debug"
@echo stam > ".build-debug\UOCContacts"
MakeIntermediateDirs:
@$(MakeDirCommand) "./bin/Debug"
$(IntermediateDirectory)/.d:
@$(MakeDirCommand) "./bin/Debug"
PreBuild:
##
## Objects
##
$(IntermediateDirectory)/src_main.c$(ObjectSuffix): src/main.c $(IntermediateDirectory)/src_main.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/src/main.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_main.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/src_main.c$(DependSuffix): src/main.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_main.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_main.c$(DependSuffix) -MM src/main.c
$(IntermediateDirectory)/src_main.c$(PreprocessSuffix): src/main.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_main.c$(PreprocessSuffix) src/main.c
$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix): test/src/test_suite.c $(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test_suite.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix): test/src/test_suite.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix) -MM test/src/test_suite.c
$(IntermediateDirectory)/test_src_test_suite.c$(PreprocessSuffix): test/src/test_suite.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test_suite.c$(PreprocessSuffix) test/src/test_suite.c
$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix): test/src/test.c $(IntermediateDirectory)/test_src_test.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/test_src_test.c$(DependSuffix): test/src/test.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test.c$(DependSuffix) -MM test/src/test.c
$(IntermediateDirectory)/test_src_test.c$(PreprocessSuffix): test/src/test.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test.c$(PreprocessSuffix) test/src/test.c
$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix): test/src/test_pr1.c $(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test_pr1.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix): test/src/test_pr1.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix) -MM test/src/test_pr1.c
$(IntermediateDirectory)/test_src_test_pr1.c$(PreprocessSuffix): test/src/test_pr1.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test_pr1.c$(PreprocessSuffix) test/src/test_pr1.c
-include $(IntermediateDirectory)/*$(DependSuffix)
##
## Clean
##
clean:
$(RM) -r ./bin/Debug/

140
UOC20211.project Normal file
View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="UOC20211" Version="10.0.0" InternalType="Console">
<Plugins>
<Plugin Name="qmake">
<![CDATA[00020001N0005Debug0000000000000001N0007Release000000000000]]>
</Plugin>
</Plugins>
<VirtualDirectory Name="src">
<File Name="src/main.c"/>
</VirtualDirectory>
<VirtualDirectory Name="test">
<VirtualDirectory Name="include">
<File Name="test/include/test_pr1.h"/>
<File Name="test/include/test.h"/>
<File Name="test/include/test_suite.h"/>
</VirtualDirectory>
<VirtualDirectory Name="src">
<File Name="test/src/test_pr1.c"/>
<File Name="test/src/test.c"/>
<File Name="test/src/test_suite.c"/>
</VirtualDirectory>
</VirtualDirectory>
<Reconciliation>
<Regexes/>
<Excludepaths/>
<Ignorefiles/>
<Extensions>
<![CDATA[*.cpp;*.c;*.h;*.hpp;*.xrc;*.wxcp;*.fbp]]>
</Extensions>
<Topleveldir>/Docencia/PP/20211/PR1/UOC20211</Topleveldir>
</Reconciliation>
<Description/>
<Dependencies/>
<Dependencies Name="Debug">
<Project Name="UOCContacts"/>
</Dependencies>
<Dependencies Name="Release">
<Project Name="UOCContacts"/>
</Dependencies>
<Settings Type="Executable">
<GlobalSettings>
<Compiler Options="" C_Options="" Assembler="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
<Configuration Name="Debug" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-g;-O0;-Wall" C_Options="-g;-O0;-Wall" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
<IncludePath Value="test/include"/>
<IncludePath Value="UOCContacts/include"/>
</Compiler>
<Linker Options="" Required="yes">
<LibraryPath Value="./lib"/>
<Library Value="libUOCContactsd.a"/>
</Linker>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="./bin/$(ProjectName)d" IntermediateDirectory="./bin/Debug" Command="$(ProjectName)d" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="./bin" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
<BuildSystem Name="Default"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
<![CDATA[]]>
</Environment>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
<Completion EnableCpp11="no" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
</Configuration>
<Configuration Name="Release" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-O2;-Wall" C_Options="-O2;-Wall" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
<IncludePath Value="test/include"/>
<IncludePath Value="UOCContacts/include"/>
<Preprocessor Value="NDEBUG"/>
</Compiler>
<Linker Options="" Required="yes">
<LibraryPath Value="./lib"/>
<Library Value="libUOCContacts.a"/>
</Linker>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="./bin/$(ProjectName)" IntermediateDirectory="./bin/Release" Command="$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="./bin" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
<BuildSystem Name="Default"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
<![CDATA[]]>
</Environment>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
<Completion EnableCpp11="no" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
</Configuration>
</Settings>
</CodeLite_Project>

1
UOC20211.txt Normal file
View file

@ -0,0 +1 @@
./bin/Debug/src_main.c.o ./bin/Debug/test_src_test_suite.c.o ./bin/Debug/test_src_test.c.o ./bin/Debug/test_src_test_pr1.c.o

17
UOC20211.workspace Normal file
View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Workspace Name="UOC20211" Database="" Version="10.0.0">
<Project Name="UOC20211" Path="UOC20211.project" Active="Yes"/>
<Project Name="UOCContacts" Path="UOCContacts/UOCContacts.project"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Environment/>
<Project Name="UOC20211" ConfigName="Debug"/>
<Project Name="UOCContacts" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Environment/>
<Project Name="UOC20211" ConfigName="Release"/>
<Project Name="UOCContacts" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>

138
UOCContacts/UOCContacts.mk Normal file
View file

@ -0,0 +1,138 @@
##
## Auto Generated makefile by CodeLite IDE
## any manual changes will be erased
##
## Debug
ProjectName :=UOCContacts
ConfigurationName :=Debug
WorkspacePath :=W:/Docencia/PP/20211/PR1/UOC20211
ProjectPath :=W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts
IntermediateDirectory :=../bin/Debug
OutDir := $(IntermediateDirectory)
CurrentFileName :=
CurrentFilePath :=
CurrentFileFullPath :=
User :=xavie
Date :=11/10/2021
CodeLitePath :="C:/Program Files/CodeLite"
LinkerName :=C:/TDM-GCC-64/bin/g++.exe
SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC
ObjectSuffix :=.o
DependSuffix :=.o.d
PreprocessSuffix :=.i
DebugSwitch :=-g
IncludeSwitch :=-I
LibrarySwitch :=-l
OutputSwitch :=-o
LibraryPathSwitch :=-L
PreprocessorSwitch :=-D
SourceSwitch :=-c
OutputFile :=../lib/lib$(ProjectName)d.a
Preprocessors :=
ObjectSwitch :=-o
ArchiveOutputSwitch :=
PreprocessOnlySwitch :=-E
ObjectsFileList :="UOCContacts.txt"
PCHCompileFlags :=
MakeDirCommand :=makedir
RcCmpOptions :=
RcCompilerName :=C:/TDM-GCC-64/bin/windres.exe
LinkOptions :=
IncludePath := $(IncludeSwitch). $(IncludeSwitch). $(IncludeSwitch)include
IncludePCH :=
RcIncludePath :=
Libs :=
ArLibs :=
LibPath := $(LibraryPathSwitch).
##
## Common variables
## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables
##
AR := C:/TDM-GCC-64/bin/ar.exe rcu
CXX := C:/TDM-GCC-64/bin/g++.exe
CC := C:/TDM-GCC-64/bin/gcc.exe
CXXFLAGS := -g $(Preprocessors)
CFLAGS := -g $(Preprocessors)
ASFLAGS :=
AS := C:/TDM-GCC-64/bin/as.exe
##
## User defined environment variables
##
CodeLiteDir:=C:\Program Files\CodeLite
Objects0=$(IntermediateDirectory)/src_date.c$(ObjectSuffix) $(IntermediateDirectory)/src_person.c$(ObjectSuffix) $(IntermediateDirectory)/src_csv.c$(ObjectSuffix) $(IntermediateDirectory)/src_api.c$(ObjectSuffix)
Objects=$(Objects0)
##
## Main Build Targets
##
.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs
all: $(IntermediateDirectory) $(OutputFile)
$(OutputFile): $(Objects)
@$(MakeDirCommand) $(@D)
@echo "" > $(IntermediateDirectory)/.d
@echo $(Objects0) > $(ObjectsFileList)
$(AR) $(ArchiveOutputSwitch)$(OutputFile) @$(ObjectsFileList) $(ArLibs)
@$(MakeDirCommand) "W:\Docencia\PP\20211\PR1\UOC20211/.build-debug"
@echo rebuilt > "W:\Docencia\PP\20211\PR1\UOC20211/.build-debug/UOCContacts"
MakeIntermediateDirs:
@$(MakeDirCommand) "../bin/Debug"
../bin/Debug:
@$(MakeDirCommand) "../bin/Debug"
PreBuild:
##
## Objects
##
$(IntermediateDirectory)/src_date.c$(ObjectSuffix): src/date.c $(IntermediateDirectory)/src_date.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/date.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_date.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/src_date.c$(DependSuffix): src/date.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_date.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_date.c$(DependSuffix) -MM src/date.c
$(IntermediateDirectory)/src_date.c$(PreprocessSuffix): src/date.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_date.c$(PreprocessSuffix) src/date.c
$(IntermediateDirectory)/src_person.c$(ObjectSuffix): src/person.c $(IntermediateDirectory)/src_person.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/person.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_person.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/src_person.c$(DependSuffix): src/person.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_person.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_person.c$(DependSuffix) -MM src/person.c
$(IntermediateDirectory)/src_person.c$(PreprocessSuffix): src/person.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_person.c$(PreprocessSuffix) src/person.c
$(IntermediateDirectory)/src_csv.c$(ObjectSuffix): src/csv.c $(IntermediateDirectory)/src_csv.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/csv.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_csv.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/src_csv.c$(DependSuffix): src/csv.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_csv.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_csv.c$(DependSuffix) -MM src/csv.c
$(IntermediateDirectory)/src_csv.c$(PreprocessSuffix): src/csv.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_csv.c$(PreprocessSuffix) src/csv.c
$(IntermediateDirectory)/src_api.c$(ObjectSuffix): src/api.c $(IntermediateDirectory)/src_api.c$(DependSuffix)
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/api.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_api.c$(ObjectSuffix) $(IncludePath)
$(IntermediateDirectory)/src_api.c$(DependSuffix): src/api.c
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_api.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_api.c$(DependSuffix) -MM src/api.c
$(IntermediateDirectory)/src_api.c$(PreprocessSuffix): src/api.c
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_api.c$(PreprocessSuffix) src/api.c
-include $(IntermediateDirectory)/*$(DependSuffix)
##
## Clean
##
clean:
$(RM) -r ../bin/Debug/

View file

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<CodeLite_Project Name="UOCContacts" Version="10.0.0" InternalType="Library">
<Plugins>
<Plugin Name="qmake">
<![CDATA[00020001N0005Debug0000000000000001N0007Release000000000000]]>
</Plugin>
</Plugins>
<Reconciliation>
<Regexes/>
<Excludepaths/>
<Ignorefiles/>
<Extensions>
<![CDATA[*.cpp;*.c;*.h;*.hpp;*.xrc;*.wxcp;*.fbp]]>
</Extensions>
<Topleveldir>/Docencia/PP/20211/PR1/UOC20211/UOCContacts</Topleveldir>
</Reconciliation>
<Description/>
<Dependencies/>
<VirtualDirectory Name="src">
<File Name="src/date.c"/>
<File Name="src/person.c"/>
<File Name="src/csv.c"/>
<File Name="src/api.c"/>
</VirtualDirectory>
<VirtualDirectory Name="include">
<File Name="include/date.h"/>
<File Name="include/person.h"/>
<File Name="include/csv.h"/>
<File Name="include/error.h"/>
<File Name="include/api.h"/>
</VirtualDirectory>
<Settings Type="Static Library">
<GlobalSettings>
<Compiler Options="" C_Options="" Assembler="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
<Configuration Name="Debug" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Static Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-g" C_Options="-g" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
<IncludePath Value="include"/>
</Compiler>
<Linker Options="" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="../lib/lib$(ProjectName)d.a" IntermediateDirectory="../bin/Debug" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
<BuildSystem Name="Default"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
<![CDATA[]]>
</Environment>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName/>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
<Completion EnableCpp11="no" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
</Configuration>
<Configuration Name="Release" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Static Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
<IncludePath Value="."/>
</Compiler>
<Linker Options="" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="../lib/lib$(ProjectName).a" IntermediateDirectory="../bin/Release" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
<BuildSystem Name="Default"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
<![CDATA[]]>
</Environment>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
<DebuggerSearchPaths/>
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName/>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
<Completion EnableCpp11="no" EnableCpp14="no">
<ClangCmpFlagsC/>
<ClangCmpFlags/>
<ClangPP/>
<SearchPaths/>
</Completion>
</Configuration>
</Settings>
</CodeLite_Project>

View file

@ -0,0 +1 @@
../bin/Debug/src_date.c.o ../bin/Debug/src_person.c.o ../bin/Debug/src_csv.c.o ../bin/Debug/src_api.c.o

40
UOCContacts/include/api.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef __UOCCONTACTS_API__H
#define __UOCCONTACTS_API__H
#include <stdbool.h>
#include "error.h"
#include "csv.h"
// Type that stores all the application data
typedef struct _ApiData {
//////////////////////////////////
// Ex PR1 2:
/////////////////////////////////
} tApiData;
// Get the API version information
const char* api_version();
// Load data from a CSV file. If reset is true, remove previous data
tApiError api_loadData(tApiData* data, const char* filename, bool reset);
// Add a new entry
tApiError api_addDataEntry(tApiData* data, tCSVEntry entry);
// Free all used memory
tApiError api_freeData(tApiData* data);
// Initialize the data structure
tApiError api_initData(tApiData* data);
// Get person data
tApiError api_findPerson(tApiData* data, const char* document, tCSVEntry* person);
// Get all geolocation data for a given person
tApiError api_getPersonGeolocation(tApiData* data, const char* document, tCSVData* geodata);
// Remove a person
tApiError api_removePerson(tApiData* data, const char* document);
#endif // __UOCCONTACTS_API__H

72
UOCContacts/include/csv.h Normal file
View file

@ -0,0 +1,72 @@
#ifndef __CSV_H__
#define __CSV_H__
#include <stdbool.h>
#define CSV_SEPARATOR_CHAR ;
// Store one entry from a CSV file
typedef struct _tCSVEntry {
int numFields;
char* type;
char** fields;
} tCSVEntry;
// Store the content of a CSV file
typedef struct _tCSVData {
tCSVEntry *entries;
int count;
bool isValid;
} tCSVData;
// Initialize the tCSVData structure
void csv_init(tCSVData* data);
// Initialize the tCSVEntry structure
void csv_initEntry(tCSVEntry* entry);
// Parse the contents of a CSV file
void csv_parse(tCSVData* data, const char* input, const char* type);
// Add a new entry to the CSV Data
void csv_addStrEntry(tCSVData* data, const char* entry, const char* type);
// Print the content of the CSV data structure
void csv_print(tCSVData data);
// Print the content of the CSV entry structure
void csv_printEntry(tCSVEntry entry);
// Parse the contents of a CSV line "f1;f2;f3" => field_0 = f1, field_1 = f2, field_2 = f3
void csv_parseEntry(tCSVEntry* entry, const char* input, const char* type);
// Get the number of entries
bool csv_isValid(tCSVData data);
// Remove all data from structure
void csv_free(tCSVData* data);
// Remove all data from structure
void csv_freeEntry(tCSVEntry* entry);
// Get the number of entries
int csv_numEntries(tCSVData data);
// Get the type of information contained in the entry
const char* csv_getType(tCSVEntry* entry);
// Get an entry from the CSV data
tCSVEntry* csv_getEntry(tCSVData data, int position);
// Get the number of fields for a given entry
int csv_numFields(tCSVEntry entry);
// Get a field from the given entry as integer
int csv_getAsInteger(tCSVEntry entry, int position);
// Get a field from the given entry as string. The value is copied to the provided buffer with provided maximum length
void csv_getAsString(tCSVEntry entry, int position, char* buffer, int length);
// Get a field from the given entry as integer
float csv_getAsReal(tCSVEntry entry, int position);
#endif

View file

@ -0,0 +1,28 @@
#ifndef __DATE_H__
#define __DATE_H__
#include <stdbool.h>
typedef struct _tDate {
int day;
int month;
int year;
} tDate;
typedef struct _tTime {
int hour;
int minutes;
} tTime;
typedef struct _tDateTime {
tDate date;
tTime time;
} tDateTime;
// Parse a tDateTime from string information
void dateTime_parse(tDateTime* dateTime, const char* date, const char* time);
// Compare two tDateTime structures and return true if they contain the same value or false otherwise.
bool dateTime_cmp(tDateTime dateTime1, tDateTime dateTime2);
#endif // __DATE_H__

View file

@ -0,0 +1,19 @@
#ifndef __UOCCONTACTS_ERROR__H
#define __UOCCONTACTS_ERROR__H
// Define error codes
enum _tApiError
{
E_SUCCESS = 0, // No error
E_NOT_IMPLEMENTED = -1, // Called method is not implemented
E_FILE_NOT_FOUND = -2, // File not found
E_PERSON_NOT_FOUND = -3, // Person not found
E_INVALID_ENTRY_TYPE = -4, // Invalid entry type
E_INVALID_ENTRY_FORMAT = -5, // Invalid entry format
E_DUPLICATED_ENTRY = -6, // Duplicated entry
};
// Define an error type
typedef enum _tApiError tApiError;
#endif // __UOCCONTACTS_ERRORS__H

View file

@ -0,0 +1,48 @@
#ifndef __PERSON_H__
#define __PERSON_H__
#include "csv.h"
#include "date.h"
typedef struct _tPerson {
char* document;
char* name;
char* surname;
char* cp;
char* email;
char* address;
tDate birthday;
} tPerson;
typedef struct _tPopulation {
tPerson* elems;
int count;
} tPopulation;
// Initialize the population data
void population_init(tPopulation* data);
// Remove the data from a person
void person_free(tPerson* data);
// Remove the data from all persons
void population_free(tPopulation* data);
// Parse input from CSVEntry
void person_parse(tPerson* data, tCSVEntry entry);
// Add a new person
void population_add(tPopulation* data, tPerson person);
// Remove a person
void population_del(tPopulation* data, const char *document);
// Return the position of a person with provided document. -1 if it does not exist
int population_find(tPopulation data, const char* document);
// Print the person data
void population_print(tPopulation data);
// Copy the data from the source to destination
void person_cpy(tPerson* destination, tPerson source);
#endif

114
UOCContacts/src/api.c Normal file
View file

@ -0,0 +1,114 @@
#include <stdio.h>
#include <assert.h>
#include "csv.h"
#include "api.h"
#include <string.h>
#define FILE_READ_BUFFER_SIZE 2048
// Get the API version information
const char* api_version() {
return "UOC PP 20211";
}
// Load data from a CSV file. If reset is true, remove previous data
tApiError api_loadData(tApiData* data, const char* filename, bool reset) {
tApiError error;
FILE *fin;
char buffer[FILE_READ_BUFFER_SIZE];
tCSVEntry entry;
// Check input data
assert( data != NULL );
assert(filename != NULL);
// Reset current data
if (reset) {
// Remove previous information
error = api_freeData(data);
if (error != E_SUCCESS) {
return error;
}
// Initialize the data
error = api_initData(data);
if (error != E_SUCCESS) {
return error;
}
}
// Open the input file
fin = fopen(filename, "r");
if (fin == NULL) {
return E_FILE_NOT_FOUND;
}
// Read file line by line
while (fgets(buffer, FILE_READ_BUFFER_SIZE, fin)) {
// Remove new line character
buffer[strcspn(buffer, "\n\r")] = '\0';
csv_initEntry(&entry);
csv_parseEntry(&entry, buffer, NULL);
// Add this new entry to the api Data
error = api_addDataEntry(data, entry);
if (error != E_SUCCESS) {
return error;
}
}
fclose(fin);
return E_SUCCESS;
}
// Add a new entry
tApiError api_addDataEntry(tApiData* data, tCSVEntry entry) {
//////////////////////////////////
// Ex PR1 2
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}
// Free all used memory
tApiError api_freeData(tApiData* data) {
//////////////////////////////////
// Ex PR1 2:
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}
// Initialize the data structure
tApiError api_initData(tApiData* data) {
//////////////////////////////////
// Ex PR1 2:
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}
// Get person data
tApiError api_findPerson(tApiData* data, const char* document, tCSVEntry* person) {
//////////////////////////////////
// Ex PR1 3
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}
// Get all geolocation data for a given person
tApiError api_getPersonGeolocation(tApiData* data, const char* document, tCSVData* geodata) {
//////////////////////////////////
// Ex PR1 3
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}
// Remove a person
tApiError api_removePerson(tApiData* data, const char* document) {
//////////////////////////////////
// Ex PR1 3
/////////////////////////////////
return E_NOT_IMPLEMENTED;
}

232
UOCContacts/src/csv.c Normal file
View file

@ -0,0 +1,232 @@
#include "csv.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
// Initialize the tCSVData structure
void csv_init(tCSVData* data) {
data->count = 0;
data->isValid = false;
data->entries = NULL;
}
// Initialize the tCSVEntry structure
void csv_initEntry(tCSVEntry* entry) {
entry->numFields = 0;
entry->fields = NULL;
entry->type = NULL;
}
// Add a new entry to the CSV Data
void csv_addStrEntry(tCSVData* data, const char* entry, const char* type) {
assert( data != NULL );
assert( entry != NULL );
data->count++;
if (data->count == 1) {
data->entries = (tCSVEntry*) malloc(sizeof(tCSVEntry));
} else {
data->entries = (tCSVEntry*) realloc(data->entries, data->count * sizeof(tCSVEntry));
}
csv_initEntry(&(data->entries[data->count-1]));
csv_parseEntry(&(data->entries[data->count-1]), entry, type);
}
// Parse the contents of a CSV file
void csv_parse(tCSVData* data, const char* input, const char* type) {
const char *pStart, *pEnd;
char *line;
int len;
assert(data->count == 0);
assert(data->entries == NULL);
assert(!data->isValid);
pStart = input;
pEnd = strchr(pStart, '\n');
while(pEnd != NULL && pEnd != pStart) {
len = pEnd - pStart + 1;
line = (char*) malloc(len * sizeof(char));
memset(line, 0, len * sizeof(char));
strncpy(line, pStart, pEnd - pStart);
// Add the new entry line
csv_addStrEntry(data, line, type);
free(line);
pStart = pEnd + 1;
pEnd = strchr(pStart, '\n');
}
pEnd = strchr(pStart, '\0');
if (pEnd != NULL && pEnd != pStart) {
len = pEnd - pStart + 1;
line = (char*) malloc(len * sizeof(char));
memset(line, 0, len * sizeof(char));
strncpy(line, pStart, pEnd - pStart);
data->count++;
if (data->count == 1) {
data->entries = (tCSVEntry*) malloc(sizeof(tCSVEntry));
} else {
data->entries = (tCSVEntry*) realloc(data->entries, data->count * sizeof(tCSVEntry));
}
csv_initEntry(&(data->entries[data->count-1]));
csv_parseEntry(&(data->entries[data->count-1]), line, type);
free(line);
}
data->isValid = true;
}
// Print the content of the CSV data structure
void csv_print(tCSVData data) {
int i;
tCSVEntry* entry = NULL;
for (i = 0; i < csv_numEntries(data); i++) {
entry = csv_getEntry(data, i);
printf("===============\n");
printf("Entry %d: %s\n", i, entry->type);
printf("===============\n");
csv_printEntry(*entry);
printf("===============\n");
}
}
// Print the content of the CSV entry structure
void csv_printEntry(tCSVEntry entry) {
int i;
char buffer[512];
printf("\tNum Fields: %d\n", csv_numFields(entry));
for (i = 0; i < csv_numFields(entry); i++) {
csv_getAsString(entry, i, buffer, 512);
printf("\tField %d: %s\n", i, buffer);
}
}
// Parse the contents of a CSV line
void csv_parseEntry(tCSVEntry* entry, const char* input, const char* type) {
const char *pStart, *pEnd;
int len;
bool readType = true;
assert(entry->numFields == 0);
assert(entry->fields == NULL);
// If the type of the entry is not provided, use the first field
if(type != NULL) {
len = strlen(type) + 1;
entry->type = (char*) malloc(len * sizeof(char));
memset(entry->type, 0, len * sizeof(char));
strncpy(entry->type, type, len);
readType = false;
}
pStart = input;
pEnd = strchr(pStart, ';');
while(pEnd != NULL && pEnd != pStart) {
// Get the length of the field
len = pEnd - pStart + 1;
if(readType) {
entry->type = (char*) malloc(len * sizeof(char));
memset(entry->type, 0, len * sizeof(char));
strncpy(entry->type, pStart, pEnd - pStart);
readType = false;
} else {
entry->numFields++;
if (entry->numFields == 1) {
entry->fields = (char**) malloc(sizeof(char*));
} else {
entry->fields = (char**) realloc(entry->fields, entry->numFields * sizeof(char*));
}
entry->fields[entry->numFields - 1] = (char*) malloc(len * sizeof(char));
memset(entry->fields[entry->numFields - 1], 0, len * sizeof(char));
strncpy(entry->fields[entry->numFields - 1], pStart, pEnd - pStart);
}
pStart = pEnd + 1;
pEnd = strchr(pStart, ';');
}
pEnd = strchr(pStart, '\0');
if (pEnd != NULL && pEnd != pStart) {
assert(!readType);
entry->numFields++;
if (entry->numFields == 1) {
entry->fields = (char**) malloc(sizeof(char*));
} else {
entry->fields = (char**) realloc(entry->fields, entry->numFields * sizeof(char*));
}
len = pEnd - pStart + 1;
entry->fields[entry->numFields - 1] = (char*) malloc(len * sizeof(char));
memset(entry->fields[entry->numFields - 1], 0, len * sizeof(char));
strncpy(entry->fields[entry->numFields - 1], pStart, pEnd - pStart);
}
}
// Get the number of entries
bool csv_isValid(tCSVData data) {
return data.isValid;
}
// Remove all data from structure
void csv_free(tCSVData* data) {
int i;
for (i = 0; i < data->count; i++) {
csv_freeEntry(&(data->entries[i]));
}
free(data->entries);
csv_init(data);
}
// Remove all data from structure
void csv_freeEntry(tCSVEntry* entry) {
int i;
if(entry->fields != NULL) {
for(i = 0; i < entry->numFields; i++) {
free(entry->fields[i]);
entry->fields[i] = NULL;
}
free(entry->fields);
}
if(entry->type != NULL) {
free(entry->type);
}
csv_initEntry(entry);
}
// Get the number of entries
int csv_numEntries(tCSVData data) {
return data.count;
}
// Get the type of information contained in the entry
const char* csv_getType(tCSVEntry* entry) {
return (const char*)entry->type;
}
// Get an entry from the CSV data
tCSVEntry* csv_getEntry(tCSVData data, int position) {
return &(data.entries[position]);
}
// Get the number of fields for a given entry
int csv_numFields(tCSVEntry entry) {
return entry.numFields;
}
// Get a field from the given entry as integer
int csv_getAsInteger(tCSVEntry entry, int position) {
return atoi(entry.fields[position]);
}
// Get a field from the given entry as string
void csv_getAsString(tCSVEntry entry, int position, char* buffer, int length) {
memset(buffer, 0, length);
strncpy(buffer, entry.fields[position], length - 1);
}
// Get a field from the given entry as integer
float csv_getAsReal(tCSVEntry entry, int position) {
return atof(entry.fields[position]);
}

34
UOCContacts/src/date.c Normal file
View file

@ -0,0 +1,34 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "date.h"
// Parse a tDateTime from string information
void dateTime_parse(tDateTime* dateTime, const char* date, const char* time) {
// Check output data
assert(dateTime != NULL);
// Check input date
assert(date != NULL);
assert(strlen(date) == 10);
// Check input time
assert(time != NULL);
assert(strlen(time) == 5);
// Parse the input date
sscanf(date, "%d/%d/%d", &(dateTime->date.day), &(dateTime->date.month), &(dateTime->date.year));
// Parse the input time
sscanf(time, "%d:%d", &(dateTime->time.hour), &(dateTime->time.minutes));
}
// Compare two tDateTime structures and return true if they contain the same value or false otherwise.
bool dateTime_cmp(tDateTime dateTime1, tDateTime dateTime2) {
if (dateTime1.date.day != dateTime2.date.day || dateTime1.date.month != dateTime2.date.month || dateTime1.date.year != dateTime2.date.year) {
return false;
}
return dateTime1.time.hour == dateTime2.time.hour && dateTime1.time.minutes == dateTime2.time.minutes;
}

241
UOCContacts/src/person.c Normal file
View file

@ -0,0 +1,241 @@
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "person.h"
// Initialize the population data
void population_init(tPopulation* data) {
// Check input/output data
assert(data != NULL);
data->elems = NULL;
data->count = 0;
}
// Remove the data from a person
void person_free(tPerson* data) {
// Check input data
assert(data != NULL);
// Release document data
if(data->document != NULL) free(data->document);
data->document = NULL;
// Release name data
if(data->name != NULL) free(data->name);
data->name = NULL;
// Release surname data
if(data->surname != NULL) free(data->surname);
data->surname = NULL;
// Release email data
if(data->email != NULL) free(data->email);
data->email = NULL;
// Release address data
if(data->address != NULL) free(data->address);
data->address = NULL;
// Release cp data
if(data->cp != NULL) free(data->cp);
data->cp = NULL;
}
// Remove the data from all persons
void population_free(tPopulation* data) {
int i;
// Check input data
assert(data != NULL);
// Remove contents
for(i = 0; i < data->count; i++) {
person_free(&(data->elems[i]));
}
// Release memory
if (data->count > 0) {
free(data->elems);
data->elems = NULL;
data->count = 0;
}
}
// Parse input from CSVEntry
void person_parse(tPerson* data, tCSVEntry entry) {
// Check input data
assert(data != NULL);
// Check entry fields
assert(csv_numFields(entry) == 7);
// Copy identity document data
data->document = (char*) malloc((strlen(entry.fields[0]) + 1) * sizeof(char));
assert(data->document != NULL);
memset(data->document, 0, (strlen(entry.fields[0]) + 1) * sizeof(char));
csv_getAsString(entry, 0, data->document, strlen(entry.fields[0]) + 1);
// Copy name data
data->name = (char*) malloc((strlen(entry.fields[1]) + 1) * sizeof(char));
assert(data->name != NULL);
memset(data->name, 0, (strlen(entry.fields[1]) + 1) * sizeof(char));
csv_getAsString(entry, 1, data->name, strlen(entry.fields[1]) + 1);
// Copy surname data
data->surname = (char*) malloc((strlen(entry.fields[2]) + 1) * sizeof(char));
assert(data->surname != NULL);
memset(data->surname, 0, (strlen(entry.fields[2]) + 1) * sizeof(char));
csv_getAsString(entry, 2, data->surname, strlen(entry.fields[2]) + 1);
// Copy email data
data->email = (char*) malloc((strlen(entry.fields[3]) + 1) * sizeof(char));
assert(data->email != NULL);
memset(data->email, 0, (strlen(entry.fields[3]) + 1) * sizeof(char));
csv_getAsString(entry, 3, data->email, strlen(entry.fields[3]) + 1);
// Copy address data
data->address = (char*) malloc((strlen(entry.fields[4]) + 1) * sizeof(char));
assert(data->address != NULL);
memset(data->address, 0, (strlen(entry.fields[4]) + 1) * sizeof(char));
csv_getAsString(entry, 4, data->address, strlen(entry.fields[4]) + 1);
// Copy cp data
data->cp = (char*) malloc((strlen(entry.fields[5]) + 1) * sizeof(char));
assert(data->cp != NULL);
memset(data->cp, 0, (strlen(entry.fields[5]) + 1) * sizeof(char));
csv_getAsString(entry, 5, data->cp, strlen(entry.fields[5]) + 1);
// Check birthday lenght
assert(strlen(entry.fields[6]) == 10);
// Parse the birthday date
sscanf(entry.fields[6], "%d/%d/%d", &(data->birthday.day), &(data->birthday.month), &(data->birthday.year));
}
// Add a new person
void population_add(tPopulation* data, tPerson person) {
// Check input data
assert(data != NULL);
// If person does not exist add it
if(population_find(data[0], person.document) < 0) {
// Allocate memory for new element
if (data->count == 0) {
// Request new memory space
data->elems = (tPerson*) malloc(sizeof(tPerson));
} else {
// Modify currently allocated memory
data->elems = (tPerson*) realloc(data->elems, (data->count + 1) * sizeof(tPerson));
}
assert(data->elems != NULL);
// Copy the data to the new position
person_cpy(&(data->elems[data->count]), person);
// Increase the number of elements
data->count ++;
}
}
// Remove a person
void population_del(tPopulation* data, const char *document) {
int i;
int pos;
// Check input data
assert(data != NULL);
// Find if it exists
pos = population_find(data[0], document);
if (pos >= 0) {
// Remove current position memory
person_free(&(data->elems[pos]));
// Shift elements
for(i = pos; i < data->count-1; i++) {
// Copy address of element on position i+1 to position i
data->elems[i] = data->elems[i+1];
}
// Update the number of elements
data->count--;
// Resize the used memory
if (data->count == 0) {
// No element remaining
free(data->elems);
data->elems = NULL;
} else {
// Still some elements are remaining
data->elems = (tPerson*)realloc(data->elems, data->count * sizeof(tPerson));
}
}
}
// Return the position of a person with provided document. -1 if it does not exist
int population_find(tPopulation data, const char* document) {
int i;
for(i = 0; i < data.count; i++) {
if(strcmp(data.elems[i].document, document) == 0 ) {
return i;
}
}
return -1;
}
// Print the person data
void population_print(tPopulation data) {
int i;
for(i = 0; i < data.count; i++) {
// Print position and document
printf("%d;%s;", i, data.elems[i].document);
// Print name and surname
printf("%s;%s;", data.elems[i].name, data.elems[i].surname);
// Print email
printf("%s;", data.elems[i].email);
// Print address and CP
printf("%s;%s;", data.elems[i].address, data.elems[i].cp);
// Print birthday date
printf("%02d/%02d/%04d\n", data.elems[i].birthday.day, data.elems[i].birthday.month, data.elems[i].birthday.year);
}
}
// Copy the data from the source to destination
void person_cpy(tPerson* destination, tPerson source) {
// Copy identity document data
destination->document = (char*) malloc((strlen(source.document) + 1) * sizeof(char));
assert(destination->document != NULL);
strcpy(destination->document, source.document);
// Copy name data
destination->name = (char*) malloc((strlen(source.name) + 1) * sizeof(char));
assert(destination->name != NULL);
strcpy(destination->name, source.name);
// Copy surname data
destination->surname = (char*) malloc((strlen(source.surname) + 1) * sizeof(char));
assert(destination->surname != NULL);
strcpy(destination->surname, source.surname);
// Copy email data
destination->email = (char*) malloc((strlen(source.email) + 1) * sizeof(char));
assert(destination->email != NULL);
strcpy(destination->email, source.email);
// Copy address data
destination->address = (char*) malloc((strlen(source.address) + 1) * sizeof(char));
assert(destination->address != NULL);
strcpy(destination->address, source.address);
// Copy cp data
destination->cp = (char*) malloc((strlen(source.cp) + 1) * sizeof(char));
assert(destination->cp != NULL);
strcpy(destination->cp, source.cp);
// Copy the birthday date
destination->birthday = source.birthday;
}

104
src/main.c Normal file
View file

@ -0,0 +1,104 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
#include "api.h"
typedef struct _AppArguments {
char* app_name;
char* out_file;
char* in_file;
bool wait_on_exit;
} tAppArguments;
// Wait user key
void waitKey(tAppArguments parameters) {
if (parameters.wait_on_exit) {
printf("Press key to continue...");
getchar();
}
}
// Display help text
void help(const char* app_name) {
printf("%s [--help] [--in <input_test_file>] [--out <output_file>] [--test-out <output_test_file>]\n", app_name);
printf("\t[%s] %s\n", "--help", "Show this help information.");
printf("\t[%s] %s\n", "--no-wait", "Do not wait user key press on exit.");
printf("\t[%s] %s\n", "--in", "Provide file with input test data in CSV format.");
printf("\t[%s] %s\n", "--out", "Write the result of tests in a file in JSON format.");
}
bool parseArguments(tAppArguments* arguments, int argc, char **argv) {
int i;
// Initialize the arguments
arguments->app_name = NULL;
arguments->out_file = NULL;
arguments->in_file = NULL;
arguments->wait_on_exit = true;
// Parse input arguments
arguments->app_name = argv[0];
for (i=1; i < argc; i += 2) {
if (strcmp(argv[i], "--help") == 0) {
help(argv[0]);
}
if (strcmp(argv[i], "--no-wait") == 0) {
arguments->wait_on_exit = false;
}
if (strcmp(argv[i], "--in") == 0) {
if (argc < i + 1) {
help(argv[0]);
return false;
}
arguments->in_file = argv[i+1];
}
if (strcmp(argv[i], "--out") == 0) {
if (argc < i + 1) {
help(argv[0]);
return false;
}
arguments->out_file = argv[i+1];
}
}
return true;
}
int main(int argc, char **argv)
{
tAppArguments parameters;
tTestSuite testSuite;
// Parse input arguments
if (!parseArguments(&parameters, argc, argv)) {
printf("ERROR: Invalid input arguments");
// Wait user to press a key to ensure error is shown
waitKey(parameters);
// Exit with error
exit(EXIT_FAILURE);
}
// Initialize the test suite
testSuite_init(&testSuite);
// Run all tests
testSuite_run(&testSuite, parameters.in_file);
// Print test results
testSuite_print(&testSuite);
// Store test results
if (parameters.out_file != NULL) {
testSuite_export(&testSuite, parameters.out_file);
printf("Restults stored in %s\n", parameters.out_file);
}
// Remove test suite data
testSuite_free(&testSuite);
// Wait user to press a key to ensure results are shown
waitKey(parameters);
exit(EXIT_SUCCESS);
}

11
test/include/test.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef __TEST__H
#define __TEST__H
#include "test_suite.h"
// Run all available tests
void testSuite_run(tTestSuite* test_suite, const char* input);
// Check if README.txt is available and have the correct information
//void readReadme(tTestSuite* test_suite);
#endif // __TEST__H

20
test/include/test_pr1.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef __TEST_PR1_H__
#define __TEST_PR1_H__
#include <stdbool.h>
#include "test_suite.h"
// Run all tests for PR1
bool run_pr1(tTestSuite* test_suite, const char* input);
// Run tests for PR1 exercice 1
bool run_pr1_ex1(tTestSection* test_section, const char* input);
// Run tests for PR1 exercice 2
bool run_pr1_ex2(tTestSection* test_section, const char* input);
// Run tests for PR1 exercice 3
bool run_pr1_ex3(tTestSection* test_section, const char* input);
#endif // __TEST_PR1_H__

151
test/include/test_suite.h Normal file
View file

@ -0,0 +1,151 @@
#ifndef __TEST_SUITE__H
#define __TEST_SUITE__H
#include <stdbool.h>
#include <stdbool.h>
#include <stdio.h>
// #define PRINT_TEST_PROGRESS
// Size of the buffer used to read files data
#define BUFFER_SIZE 2048
// Status of a test
typedef enum {
TEST_RUNNING,
TEST_NOT_IMPLEMENTED,
TEST_PASSED,
TEST_FAILED
} tTestResult;
// A single test
typedef struct {
// Code of the test
char* code;
// Description of the test
char* description;
// Result of the test
tTestResult result;
} tTest;
// Grup of tests
typedef struct {
// Code of the test section
char* code;
// Title of the section
char* title;
// Number of tests
int numTests;
// Array of tests
tTest* tests;
} tTestSection;
// Test suit learner data
typedef struct {
// Email
char* email;
// Username
char* username;
// First name
char* first_name;
// Last name
char* last_name;
// Environment
char* environment;
// Whether the learner data file exists or not
bool file_exists;
} tLearnerData;
// Test suit with multiple sections
typedef struct {
// Learner data
tLearnerData learner;
// Number of sections
int numSections;
// Array of sections
tTestSection* sections;
} tTestSuite;
// Initialize a test Suite
void testSuite_init(tTestSuite* object);
// Load learner data
bool testSuite_load_learner(tTestSuite* object, const char* file);
// Remove a test Suite
void testSuite_free(tTestSuite* object);
// Add a test Section
void testSuite_addSection(tTestSuite* object, const char* code, const char* title);
// Add a test
void testSuite_addTest(tTestSuite* object, const char* section_code, const char* code, const char* description, tTestResult result);
// Update a test result
void testSuite_updateTest(tTestSuite* object, const char* section_code, const char* test_code, tTestResult result);
// Get a pointer to a section
tTestSection* testSuite_getSection(tTestSuite* object, const char* section_code);
// Get a pointer to a test
tTest* testSuite_getTest(tTestSuite* object, const char* section_code, const char* test_code);
// Get test statistics
void testSuite_getStats(tTestSuite* object, int* total, int* passed, int* failed, int* not_implemented);
// Print test suite
void testSuite_print(tTestSuite* object);
// Export a test suite
void testSuite_export(tTestSuite* object, const char* output);
// Initialize a test Section
void testSection_init(tTestSection* object, const char* code, const char* title);
// Remove a test Section
void testSection_free(tTestSection* object);
// Add a test to the Section
void testSection_addTest(tTestSection* object, const char* code, const char* description, tTestResult result);
// Update a test result
void testSection_updateTest(tTestSection* object, const char* test_code, tTestResult result);
// Get a pointer to a test
tTest* testSection_getTest(tTestSection* object, const char* test_code);
// Get test statistics
void testSection_getStats(tTestSection* object, int* total, int* passed, int* failed, int* not_implemented);
// Print test section
void testSection_print(tTestSection* object);
// Export a test section
void testSection_export(tTestSection* object, FILE* fout);
// Initialize a test
void test_init(tTest* object, const char* code, const char* description, tTestResult result);
// Remove a test
void test_free(tTest* object);
// Update a test result
void test_updateTest(tTest* object, tTestResult result);
// Print test
void test_print(tTest* object);
// Export a test
void test_export(tTest* object, FILE* fout);
// Start a test
void start_test(tTestSection* section, const char* code, const char* description);
// Finish a test
void end_test(tTestSection* section, const char* code, bool passed);
#endif // __TEST_SUITE__H

39
test/src/test.c Normal file
View file

@ -0,0 +1,39 @@
#include <assert.h>
#include <string.h>
#include "test.h"
#include "test_pr1.h"
// Define default test data
const char* test_data_str = "PERSON;87654321K;John;Smith;john.smith@example.com;My street, 25;08001;30/12/1980\n" \
"PERSON;98765432J;Jane;Doe;jane.doe@example.com;Her street, 5;08500;12/01/1995\n" \
"GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698\n" \
"GEOLOCATION;87654321K;15/10/2021;13:45;41.3870;2.1695\n" \
"GEOLOCATION;98765432J;15/10/2021;13:50;41.3871;2.1697\n" \
"GEOLOCATION;87654321K;15/10/2021;13:50;41.3871;2.1697\n";
// Run all available tests
void testSuite_run(tTestSuite* test_suite, const char* input) {
const char* default_input = "default_data.csv";
FILE *fout;
const char* filename;
assert(test_suite != NULL);
// Load the README.txt file
testSuite_load_learner(test_suite, "../README.txt");
// If no file is provided, use default data
if (input == NULL) {
filename = default_input;
fout = fopen(filename, "w");
assert(fout != NULL);
fwrite(test_data_str, strlen(test_data_str), 1, fout);
fclose(fout);
} else {
filename = input;
}
// Run tests for PR1
run_pr1(test_suite, filename);
}

364
test/src/test_pr1.c Normal file
View file

@ -0,0 +1,364 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "test_pr1.h"
#include "api.h"
// Run all tests for PR1
bool run_pr1(tTestSuite* test_suite, const char* input) {
bool ok = true;
tTestSection* section = NULL;
assert(test_suite != NULL);
testSuite_addSection(test_suite, "PR1", "Tests for PR1 exercices");
section = testSuite_getSection(test_suite, "PR1");
assert(section != NULL);
ok = run_pr1_ex1(section, input);
ok = run_pr1_ex2(section, input) && ok;
ok = run_pr1_ex3(section, input) && ok;
return ok;
}
// Run all tests for Exercice 1 of PR1
bool run_pr1_ex1(tTestSection* test_section, const char* input) {
bool passed = true, failed = false;
const char* version;
/////////////////////////////
///// PR1 EX1 TEST 1 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX1_1", "Read version information.");
// Get the version+
version = api_version();
if (strcmp(version, "UOC PP 20211") != 0) {
failed = true;
passed = false;
}
end_test(test_section, "PR1_EX1_1", !failed);
return passed;
}
// Run all tests for Exercice 2 of PR1
bool run_pr1_ex2(tTestSection* test_section, const char* input) {
tApiData data;
tApiError error;
tCSVEntry entry;
tCSVEntry entry2;
bool passed = true, failed = false;
bool fail_all = false;
/////////////////////////////
///// PR1 EX2 TEST 1 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_1", "Initialize the API data structure");
// Initialize the data
error = api_initData(&data);
if (error != E_SUCCESS) {
failed = true;
passed = false;
fail_all = true;
}
end_test(test_section, "PR1_EX2_1", !failed);
/////////////////////////////
///// PR1 EX2 TEST 2 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_2", "Load data from file");
// Load basic data to the API
if (fail_all) {
failed = true;
} else {
error = api_loadData(&data, input, true);
if (error != E_SUCCESS) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_2", !failed);
/////////////////////////////
///// PR1 EX2 TEST 3 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_3", "Add an entry with invalid type");
// Create an entry with invalid type
csv_initEntry(&entry);
csv_parseEntry(&entry, "68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", "INVALID_TYPE");
if (fail_all) {
failed = true;
} else {
// Add the entry
error = api_addDataEntry(&data, entry);
if (error != E_INVALID_ENTRY_TYPE) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_3", !failed);
// Free memory
csv_freeEntry(&entry);
/////////////////////////////
///// PR1 EX2 TEST 4 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_4", "Add a person entry with invalid format");
// Create an entry with invalid number of fields
csv_initEntry(&entry);
csv_parseEntry(&entry, "PERSON;68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500", NULL);
if (fail_all) {
failed = true;
} else {
error = api_addDataEntry(&data, entry);
if (error != E_INVALID_ENTRY_FORMAT) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_4", !failed);
// Free memory
csv_freeEntry(&entry);
/////////////////////////////
///// PR1 EX2 TEST 5 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_5", "Add a geoposition entry with invalid format");
// Create an entry with invalid number of fields
csv_initEntry(&entry);
csv_parseEntry(&entry, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698;Extra comment", NULL);
if (fail_all) {
failed = true;
} else {
error = api_addDataEntry(&data, entry);
if (error != E_INVALID_ENTRY_FORMAT) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_5", !failed);
// Free memory
csv_freeEntry(&entry);
/////////////////////////////
///// PR1 EX2 TEST 6 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_6", "Add a duplicated person");
// Create an entry
csv_initEntry(&entry);
csv_parseEntry(&entry, "PERSON;68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
if (fail_all) {
failed = true;
} else {
// Insert once to ensure it is present
api_addDataEntry(&data, entry);
// Try to insert it again
error = api_addDataEntry(&data, entry);
if (error != E_DUPLICATED_ENTRY) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_6", !failed);
// Free memory
csv_freeEntry(&entry);
/////////////////////////////
///// PR1 EX2 TEST 7 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_7", "Add a duplicated geoposition");
// Create an entry
csv_initEntry(&entry);
csv_parseEntry(&entry, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698", NULL);
if (fail_all) {
failed = true;
} else {
// Insert once to ensure it is present
api_addDataEntry(&data, entry);
// Try to insert it again
error = api_addDataEntry(&data, entry);
if (error != E_DUPLICATED_ENTRY) {
failed = true;
passed = false;
}
}
end_test(test_section, "PR1_EX2_7", !failed);
// Free memory
csv_freeEntry(&entry);
/////////////////////////////
///// PR1 EX2 TEST 8 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX2_8", "Remove all data");
// Create a person entry
csv_initEntry(&entry);
csv_parseEntry(&entry, "PERSON;87654321K;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
// Create a geodata entry
csv_initEntry(&entry2);
csv_parseEntry(&entry2, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698", NULL);
if (fail_all) {
failed = true;
} else {
// Ensure we cannot insert them
if (api_addDataEntry(&data, entry) != E_DUPLICATED_ENTRY || api_addDataEntry(&data, entry2) != E_DUPLICATED_ENTRY) {
failed = true;
passed = false;
} else {
// Remove all data
api_freeData(&data);
// Try to insert again
if (api_addDataEntry(&data, entry) != E_SUCCESS || api_addDataEntry(&data, entry2) != E_SUCCESS) {
failed = true;
passed = false;
}
}
}
end_test(test_section, "PR1_EX2_8", !failed);
// Free memory
csv_freeEntry(&entry);
csv_freeEntry(&entry2);
return passed;
}
// Run all tests for Exercice 3 of PR1
bool run_pr1_ex3(tTestSection* test_section, const char* input) {
tApiData data;
tApiError error;
tCSVEntry entry;
tCSVEntry person;
tCSVData geoData;
bool passed = true, failed = false;
bool fail_all = false;
// Load basic data to the API
if (api_initData(&data) != E_SUCCESS) {
fail_all = true;
}
if (!fail_all && api_loadData(&data, input, true) != E_SUCCESS) {
fail_all = true;
}
/////////////////////////////
///// PR1 EX3 TEST 1 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_1", "Find an exixting person");
if (fail_all) {
failed = true;
} else {
// Create a person entry to ensure it exists
csv_initEntry(&entry);
csv_parseEntry(&entry, "PERSON;87654321K;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
api_addDataEntry(&data, entry);
error = api_findPerson(&data, "87654321K", &person);
if (error != E_SUCCESS || csv_numFields(person) != 7) {
failed = true;
}
// Free memory
csv_freeEntry(&entry);
csv_freeEntry(&person);
}
end_test(test_section, "PR1_EX3_1", !failed);
/////////////////////////////
///// PR1 EX3 TEST 2 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_2", "Find a non exixting person");
if (fail_all) {
failed = true;
} else {
error = api_findPerson(&data, "00000000L", &person);
if (error != E_PERSON_NOT_FOUND) {
failed = true;
}
}
end_test(test_section, "PR1_EX3_2", !failed);
/////////////////////////////
///// PR1 EX3 TEST 3 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_3", "Get geoplocation from an exixting person");
if (fail_all) {
failed = true;
} else {
error = api_getPersonGeolocation(&data, "87654321K", &geoData);
if (error != E_SUCCESS) {
failed = true;
}
// Free memory
csv_free(&geoData);
}
end_test(test_section, "PR1_EX3_3", !failed);
/////////////////////////////
///// PR1 EX3 TEST 4 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_4", "Get geoplocation from a non exixting person");
if (fail_all) {
failed = true;
} else {
error = api_getPersonGeolocation(&data, "00000000L", &geoData);
if (error != E_PERSON_NOT_FOUND) {
failed = true;
}
}
end_test(test_section, "PR1_EX3_4", !failed);
/////////////////////////////
///// PR1 EX3 TEST 5 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_5", "Remove an exixting person");
if (fail_all) {
failed = true;
} else {
error = api_removePerson(&data, "87654321K");
if (error != E_SUCCESS) {
failed = true;
} else {
error = api_getPersonGeolocation(&data, "87654321K", &geoData);
if (error != E_PERSON_NOT_FOUND) {
failed = true;
}
}
}
end_test(test_section, "PR1_EX3_5", !failed);
/////////////////////////////
///// PR1 EX3 TEST 6 //////
/////////////////////////////
failed = false;
start_test(test_section, "PR1_EX3_6", "Remove a non exixting person");
if (fail_all) {
failed = true;
} else {
if (error != E_PERSON_NOT_FOUND) {
failed = true;
}
}
end_test(test_section, "PR1_EX3_6", !failed);
return passed;
}

559
test/src/test_suite.c Normal file
View file

@ -0,0 +1,559 @@
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "test_suite.h"
// Initialize a test Suite
void testSuite_init(tTestSuite* object) {
assert(object != NULL);
object->learner.email = NULL;
object->learner.username = NULL;
object->learner.first_name = NULL;
object->learner.last_name = NULL;
object->learner.environment = NULL;
object->learner.file_exists = false;
object->numSections = 0;
object->sections = NULL;
}
// Load learner data
bool testSuite_load_learner(tTestSuite* object, const char* file) {
char buffer[BUFFER_SIZE];
FILE *fin=NULL;
int state;
char* pos;
assert(object != NULL);
assert(file != NULL);
fin = fopen(file, "r");
if (fin == NULL) {
object->learner.email = NULL;
object->learner.username = NULL;
object->learner.first_name = NULL;
object->learner.last_name = NULL;
object->learner.environment = NULL;
object->learner.file_exists = false;
return false;
}
state = 0;
while (fgets(buffer, BUFFER_SIZE, fin)) {
if (state == 0) {
// Read email
object->learner.email = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
memset(object->learner.email, 0, (strlen(buffer) + 1) * sizeof(char));
strncpy(object->learner.email, buffer, strcspn(buffer, "\n\r"));
} else if(state == 1) {
// Read Surname, Name
pos = strchr(buffer, ',');
if (pos > 0) {
// Copy the surnames
object->learner.last_name = (char*) malloc((pos - buffer) * sizeof(char));
memset(object->learner.last_name, 0, (pos - buffer) * sizeof(char));
strncpy(object->learner.last_name, buffer, strcspn(buffer, ",") - 1);
// Skip the comma
pos++;
// Skip initial blank spaces
while (pos < &buffer[BUFFER_SIZE] && *pos==' ') pos++;
// Copy the first name
object->learner.first_name = (char*) malloc((strlen(pos) + 1) * sizeof(char));
memset(object->learner.first_name, 0, (strlen(pos) + 1) * sizeof(char));
strncpy(object->learner.first_name, pos, strcspn(pos, "\n\r"));
} else {
object->learner.first_name = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
memset(object->learner.first_name, 0, (strlen(buffer) + 1) * sizeof(char));
strcpy(object->learner.first_name, buffer);
}
} else if(state == 2) {
object->learner.environment = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(object->learner.environment, buffer);
} else if(state > 2) {
object->learner.environment = (char*) realloc(object->learner.environment, (strlen(object->learner.environment) + strlen(buffer) + 1) * sizeof(char));
strcat(object->learner.environment, buffer);
}
state ++;
}
object->learner.file_exists = true;
fclose(fin);
return true;
}
// Remove a test Suite
void testSuite_free(tTestSuite* object) {
int i;
assert(object != NULL);
// Free learner data
if(object->learner.email != NULL) {
free(object->learner.email);
object->learner.email = NULL;
}
if(object->learner.username != NULL) {
free(object->learner.username);
object->learner.username = NULL;
}
if(object->learner.first_name != NULL) {
free(object->learner.first_name);
object->learner.first_name = NULL;
}
if(object->learner.last_name != NULL) {
free(object->learner.last_name);
object->learner.last_name = NULL;
}
if(object->learner.environment != NULL) {
free(object->learner.environment);
object->learner.environment = NULL;
}
object->learner.file_exists = false;
// Free test data
if(object->sections != NULL) {
for(i = 0; i < object->numSections; i++) {
testSection_free(&(object->sections[i]));
}
free(object->sections);
}
}
// Add a test Section
void testSuite_addSection(tTestSuite* object, const char* code, const char* title) {
assert(object != NULL);
object->numSections++;
if(object->sections == NULL) {
object->sections = (tTestSection*)malloc(object->numSections * sizeof(tTestSection));
} else {
object->sections = (tTestSection*)realloc(object->sections, object->numSections * sizeof(tTestSection));
}
assert(object->sections != NULL);
testSection_init(&(object->sections[object->numSections - 1]), code, title);
}
// Add a test
void testSuite_addTest(tTestSuite* object, const char* section_code, const char* code, const char* description, tTestResult result) {
tTestSection* section = NULL;
assert(object != NULL);
assert(section_code != NULL);
assert(code != NULL);
assert(description != NULL);
section = testSuite_getSection(object, section_code);
assert(section != NULL);
testSection_addTest(section, code, description, result);
}
// Update a test result
void testSuite_updateTest(tTestSuite* object, const char* section_code, const char* test_code, tTestResult result) {
tTestSection* section = NULL;
assert(object != NULL);
assert(section_code != NULL);
assert(test_code != NULL);
section = testSuite_getSection(object, section_code);
assert(section != NULL);
testSection_updateTest(section, test_code, result);
}
// Get a pointer to a section
tTestSection* testSuite_getSection(tTestSuite* object, const char* section_code) {
int i;
assert(object != NULL);
assert(section_code != NULL);
for(i = 0; i < object->numSections; i++) {
if(strcmp(object->sections[i].code, section_code) == 0) {
return &(object->sections[i]);
}
}
return NULL;
}
// Get a pointer to a test
tTest* testSuite_getTest(tTestSuite* object, const char* section_code, const char* test_code) {
tTestSection* section = NULL;
assert(object != NULL);
assert(section_code != NULL);
assert(test_code != NULL);
section = testSuite_getSection(object, section_code);
assert(section != NULL);
if(section != NULL) {
return testSection_getTest(section, test_code);
}
return NULL;
}
// Get test statistics
void testSuite_getStats(tTestSuite* object, int* total, int* passed, int* failed, int* not_implemented) {
int i;
int s_total, s_passed, s_failed, s_not_implemented;
assert(object != NULL);
assert(total != NULL);
assert(passed != NULL);
assert(failed != NULL);
assert(not_implemented != NULL);
*total = 0;
*passed = 0;
*failed = 0;
*not_implemented = 0;
for(i = 0; i < object->numSections; i++) {
testSection_getStats(&(object->sections[i]), &s_total, &s_passed, &s_failed, &s_not_implemented);
*total += s_total;
*passed += s_passed;
*failed += s_failed;
*not_implemented += s_not_implemented;
}
}
// Print test suite
void testSuite_print(tTestSuite* object) {
int i;
int total, passed, failed, not_implemented;
assert(object != NULL);
// Print the header
if (object->learner.file_exists) {
printf("\n=========================================================================\n");
if (object->learner.first_name != NULL && object->learner.last_name != NULL) {
printf("\t Name: %s %s\n", object->learner.first_name, object->learner.last_name);
} else {
printf("\t Name: <not provided>\n");
}
if (object->learner.email != NULL) {
printf("\t Email: %s\n", object->learner.email);
} else {
printf("\t Email: <not provided>\n");
}
printf("=========================================================================\n");
} else {
printf("\n=========================================================================\n");
printf("\t NO LEARNER DATA\n");
printf("=========================================================================\n");
}
testSuite_getStats(object, &total, &passed, &failed, &not_implemented);
printf("\n=========================================================================\n");
printf("\t TEST RESULTS\n");
printf("=========================================================================\n");
if(object->numSections == 0) {
printf("NO TEST DEFINED\n");
} else {
for(i = 0; i < object->numSections; i++) {
testSection_print(&(object->sections[i]));
}
}
printf("\n=========================================================================\n");
if(total > 0) {
printf("Total Tests: %d\n", total);
printf("Passed Tests: %d ( %2.02f %% )\n", passed, ((float)passed / (float)total) * 100.0);
printf("Failed Tests: %d ( %2.02f %% )\n", failed, ((float)failed / (float)total) * 100.0);
//printf("Not Implemented: %d ( %2.02f %% )\n", not_implemented, ((float)not_implemented/(float)total)*100.0);
printf("=========================================================================\n");
}
}
void write_nullable_field(FILE* fout, const char* value) {
if (value == NULL) {
fprintf(fout, "null");
} else {
fprintf(fout, "\"%s\"", value);
}
}
// Export a test suite
void testSuite_export(tTestSuite* object, const char* output) {
int i;
int total, passed, failed, not_implemented;
FILE* fout = NULL;
assert(object != NULL);
assert(output != NULL);
fout = fopen(output, "w");
assert(fout != NULL);
fprintf(fout, "{ \"learner\": {\"first_name\": ");
write_nullable_field(fout, object->learner.first_name);
fprintf(fout, ", \"last_name\": ");
write_nullable_field(fout, object->learner.last_name);
fprintf(fout, ", \"email\": ");
write_nullable_field(fout, object->learner.email);
fprintf(fout, ", \"username\": ");
write_nullable_field(fout, object->learner.username);
fprintf(fout, ", \"environment\": ");
write_nullable_field(fout, object->learner.environment);
fprintf(fout, "}, ");
testSuite_getStats(object, &total, &passed, &failed, &not_implemented);
fprintf(fout, "{ \"total\": %d, \"passed\": %d, \"failed\": %d, \"not_implemented\": %d, \"sections\": [", total, passed, failed, not_implemented);
for(i = 0; i < object->numSections; i++) {
if(i > 0) {
fprintf(fout, ", ");
}
testSection_export(&(object->sections[i]), fout);
}
fprintf(fout, "]}");
fclose(fout);
}
// Initialize a test Section
void testSection_init(tTestSection* object, const char* code, const char* title) {
assert(object != NULL);
object->code = (char*) malloc((strlen(code) + 1) * sizeof(char));
assert(object->code != NULL);
strcpy(object->code, code);
object->title = (char*) malloc((strlen(title) + 1) * sizeof(char));
assert(object->title != NULL);
strcpy(object->title, title);
object->numTests = 0;
object->tests = NULL;
}
// Remove a test Section
void testSection_free(tTestSection* object) {
int i;
assert(object != NULL);
assert(object->code != NULL);
free(object->code);
free(object->title);
if(object->tests != NULL) {
for(i = 0; i < object->numTests; i++) {
test_free(&(object->tests[i]));
}
free(object->tests);
}
}
// Add a test to the Section
void testSection_addTest(tTestSection* object, const char* code, const char* description, tTestResult result) {
assert(object != NULL);
object->numTests++;
if(object->tests == NULL) {
object->tests = (tTest*)malloc(object->numTests * sizeof(tTest));
} else {
object->tests = (tTest*)realloc(object->tests, object->numTests * sizeof(tTestSection));
}
assert(object->tests != NULL);
test_init(&(object->tests[object->numTests - 1]), code, description, result);
}
// Update a test result
void testSection_updateTest(tTestSection* object, const char* test_code, tTestResult result) {
tTest* test = NULL;
assert(object != NULL);
test = testSection_getTest(object, test_code);
assert(test != NULL);
test_updateTest(test, result);
}
// Get a pointer to a test
tTest* testSection_getTest(tTestSection* object, const char* test_code) {
int i;
assert(object != NULL);
assert(test_code != NULL);
for(i = 0; i < object->numTests; i++) {
if(strcmp(object->tests[i].code, test_code) == 0) {
return &(object->tests[i]);
}
}
return NULL;
}
// Get test statistics
void testSection_getStats(tTestSection* object, int* total, int* passed, int* failed, int* not_implemented) {
int i;
assert(object != NULL);
assert(total != NULL);
assert(passed != NULL);
assert(failed != NULL);
assert(not_implemented != NULL);
*total = object->numTests;
*passed = 0;
*failed = 0;
*not_implemented = 0;
for(i = 0; i < object->numTests; i++) {
if(object->tests[i].result == TEST_PASSED) {
(*passed)++;
} else
if(object->tests[i].result == TEST_FAILED) {
(*failed)++;
} else
if(object->tests[i].result == TEST_FAILED) {
(*not_implemented)++;
}
}
}
// Print test section
void testSection_print(tTestSection* object) {
int i;
int total, passed, failed, not_implemented;
assert(object != NULL);
testSection_getStats(object, &total, &passed, &failed, &not_implemented);
printf("\n\t=================================================================\n");
printf("\t%s\n", object->title);
printf("\t=================================================================\n");
if(object->numTests == 0) {
printf("\tNO TEST DEFINED\n");
} else {
for(i = 0; i < object->numTests; i++) {
test_print(&(object->tests[i]));
}
}
printf("\t=================================================================\n");
if(total > 0) {
printf("\tTotal Tests: %d\n", total);
printf("\tPassed Tests: %d ( %2.2f %% )\n", passed, ((float)passed / (float)total) * 100.0);
printf("\tFailed Tests: %d ( %2.2f %%)\n", failed, ((float)failed / (float)total) * 100.0);
//printf("\tNot Implemented: %d ( %2.2f %%)\n", not_implemented, ((float)not_implemented/(float)total)*100.0);
printf("\t=================================================================\n");
}
}
// Export a test section
void testSection_export(tTestSection* object, FILE* fout) {
int i;
int total, passed, failed, not_implemented;
assert(object != NULL);
assert(fout != NULL);
testSection_getStats(object, &total, &passed, &failed, &not_implemented);
fprintf(fout, "{ \"code\": \"%s\", \"title\": \"%s\", \"total\": %d, \"passed\": %d, \"failed\": %d, \"not_implemented\": %d, \"tests\": [", object->code, object->title, total, passed, failed, not_implemented);
for(i = 0; i < object->numTests; i++) {
if(i > 0) {
fprintf(fout, ", ");
}
test_export(&(object->tests[i]), fout);
}
fprintf(fout, "]}");
}
// Initialize a test
void test_init(tTest* object, const char* code, const char* description, tTestResult result) {
assert(object != NULL);
object->code = (char*) malloc((strlen(code) + 1) * sizeof(char));
assert(object->code != NULL);
object->description = (char*) malloc((strlen(description) + 1) * sizeof(char));
assert(object->description != NULL);
strcpy(object->code, code);
strcpy(object->description, description);
object->result = TEST_RUNNING;
}
// Remove a test
void test_free(tTest* object) {
assert(object != NULL);
assert(object->code != NULL);
assert(object->description != NULL);
free(object->code);
free(object->description);
}
// Update a test result
void test_updateTest(tTest* object, tTestResult result) {
assert(object != NULL);
object->result = result;
}
// Print test
void test_print(tTest* object) {
assert(object != NULL);
printf("\t\t");
if(object->result == TEST_RUNNING) {
printf("[%s]", "RUNNING");
} else
if(object->result == TEST_NOT_IMPLEMENTED) {
printf("[%s]", "NOT IMPLEMENTED");
} else
if(object->result == TEST_PASSED) {
printf("[%s]", "OK");
} else
if(object->result == TEST_FAILED) {
printf("[%s]", "FAIL");
}
printf(":\t [%s] %s\n", object->code, object->description);
}
// Export a test
void test_export(tTest* object, FILE* fout) {
assert(object != NULL);
assert(fout != NULL);
fprintf(fout, "{ \"code\": \"%s\", \"description\": \"%s\", \"result\": ", object->code, object->description);
if(object->result == TEST_RUNNING) {
fprintf(fout, "\"%s\"}", "RUNNING");
} else
if(object->result == TEST_NOT_IMPLEMENTED) {
fprintf(fout, "\"%s\"}", "NOT IMPLEMENTED");
} else
if(object->result == TEST_PASSED) {
fprintf(fout, "\"%s\"}", "OK");
} else
if(object->result == TEST_FAILED) {
fprintf(fout, "\"%s\"}", "FAIL");
}
}
// Start a test
void start_test(tTestSection* section, const char* code, const char* description) {
tTest* test = NULL;
assert(section != NULL);
assert(code != NULL);
assert(description != NULL);
#ifdef PRINT_TEST_PROGRESS
printf("\n[START] ==> Running test [%s] - %s\n", code, description);
#endif // PRINT_TEST_PROGRESS
testSection_addTest(section, code, description, TEST_RUNNING);
test = testSection_getTest(section, code);
assert(test != NULL);
}
// Finish a test
void end_test(tTestSection* section, const char* code, bool passed) {
tTest* test = NULL;
assert(section != NULL);
assert(code != NULL);
test = testSection_getTest(section, code);
assert(test != NULL);
if(passed) {
#ifdef PRINT_TEST_PROGRESS
printf("\n[OK] ==> Finished test [%s] - %s\n", test->code, test->description);
#endif // PRINT_TEST_PROGRESS
test_updateTest(test, TEST_PASSED);
} else {
#ifdef PRINT_TEST_PROGRESS
printf("\n[FAIL] ==> Finished test [%s] - %s\n", test->code, test->description);
#endif // PRINT_TEST_PROGRESS
test_updateTest(test, TEST_FAILED);
}
}