Design Pattern Examples
Overview of object-oriented design patterns
Composite_Exercise.c
Go to the documentation of this file.
1
6
7#include <stdbool.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "helpers/datetime.h"
14#include "helpers/formatstring.h"
15#include "helpers/makelocaltime.h"
16
19#include "Composite_Exercise.h"
20
21
22//=============================================================================
23//=============================================================================
24
34static void Composite_Exercise_FormatEntry(FileDirEntry* entry, int depth, DynamicString* output)
35{
36 size_t NAME_PADDING_SIZE = 20;
37
38 char indentspaces[20] = {0};
39 const char *entryName = FileDirEntry_GetName(entry);
40 const char *dir_marker = (FileDirEntry_GetFileDirType(entry) == FileDirType_Directory) ? "/" : "";
41 size_t nameSize = strlen(entryName);
42 size_t padding = NAME_PADDING_SIZE - nameSize - (depth * 2);
43 int entryLength = FileDirEntry_GetLength(entry);
44 const char *timestampAsString = datetime_to_string(FileDirEntry_GetWhenModified(entry));
45 for (int index = 0; index < depth * 2 && index < (int)(sizeof(indentspaces) - 1); index++)
46 {
47 indentspaces[index] = ' ';
48 }
49
50 char* line = formatstring("%s%s%-*s%4d %s\n", indentspaces, entryName, padding, dir_marker, entryLength, timestampAsString);
51 if (line != NULL)
52 {
53 if (DynamicString_Append(output, line))
54 {
55 free(line);
56 line = NULL;
58 if (child != NULL)
59 {
60 while (child != NULL)
61 {
62 Composite_Exercise_FormatEntry(child, depth + 1, output);
63 child = child->next;
64 }
65 }
66 }
67 else
68 {
69 free(line);
70 line = NULL;
71 printf(" Error! Out of memory appending line to the output in Composite_Exercise_FormatEntry()!\n");
72 }
73 }
74 else
75 {
76 printf(" Error! Out of memory formatting line in Composite_Exercise_FormatEntry()!\n");
77 }
78}
79
80//-----------------------------------------------------------------------------
81
88{
89 DynamicString output = { 0 };
90
91 Composite_Exercise_FormatEntry(entry, 2, &output);
92 printf("%s\n", output.string);
93 DynamicString_Clear(&output);
94
95}
96
97//=============================================================================
98//=============================================================================
99
111// ! [Using Composite in C]
113{
114 printf("\nComposite_Exercise\n");
115
116 const char* filepath = "root";
117 FileDirEntry* rootEntry = Composite_FileAccess_GetEntry(filepath);
118 if (rootEntry != NULL)
119 {
120 printf(" Showing object '%s'\n", filepath);
122
123 filepath = "root/subdir1/FileD.txt";
124 rootEntry = Composite_FileAccess_GetEntry(filepath);
125 if (rootEntry != NULL)
126 {
127 printf(" Showing object '%s'\n", filepath);
129 }
130 else
131 {
132 printf(" Error! Unable to get a FileDirEntry for the path \"%s\"!", filepath);
133 }
134 }
135 else
136 {
137 printf(" Error! Unable to get a FileDirEntry for the path \"%s\"!", filepath);
138 }
139 printf(" Done.\n");
140}
141// ! [Using Composite in C]
void Composite_Exercise(void)
Example of using the Composite Pattern.
static void Composite_Exercise_ShowEntry(FileDirEntry *entry)
Recursively display the contents of the hierarchical list of FileDirEntry objects starting with the g...
static void Composite_Exercise_FormatEntry(FileDirEntry *entry, int depth, DynamicString *output)
Format the specified entry for display.
FileDirEntry * Composite_FileAccess_GetEntry(const char *path)
Return a FileDirEntry object representing the specified file "path" from an internal list of data ent...
const char * FileDirEntry_GetName(FileDirEntry *entry)
Retrieve the name of the given FileDirEntry object.
long FileDirEntry_GetLength(FileDirEntry *entry)
Get the length of the given FileDirEntry object. For Files, this is a static value....
FileDirTypes FileDirEntry_GetFileDirType(FileDirEntry *entry)
Get the type of this FileDirEntry object as a value from the FileDirTypes enumeration.
FileDirEntry * FileDirEntry_GetChildren(FileDirEntry *entry)
Retrieve a pointer to the first child of the given FileDirEntry object. If the entry does not support...
time_t FileDirEntry_GetWhenModified(FileDirEntry *entry)
Retrieve the last modified time of the given FileDirEntry object.
@ FileDirType_Directory
Represents a directory entry that can contain other FileDirEntry components.
Declaration of the Composite_Exercise() function as used in the Composite Pattern.
Declaration of the Composite_FileAccess class used in the Composite Pattern.
Implementation of the FileDirEntry, FileEntry, and DirEntry classes used in the Composite Pattern.
const char * datetime_to_string(time_t timestamp)
Convert the specified time stamp to a string.
Definition: datetime.c:12
void DynamicString_Clear(DynamicString *string)
Clear a DynamicString object, releasing any allocated memory. Resets to an empty string.
Definition: dynamicstring.c:27
bool DynamicString_Append(DynamicString *string, const char *s)
Append the specified string to the DynamicString object.
Definition: dynamicstring.c:39
Declaration of the DynamicString structure and supporting functions to work with dynamic strings.
char * formatstring(const char *format,...)
Use the given string and arguments to return a buffer containing the formatted string....
Definition: formatstring.c:15
Represents a string that can be grown dynamically.
Definition: dynamicstring.h:16
char * string
The string that can grow.
Definition: dynamicstring.h:17
Structure representing a File (FileEntry) or Directory (DirEntry) entry. This is included as the firs...
struct FileDirEntry * next
Points to the next entry in a linked list of FileDirEntry objects. NULL means no more in list.