Design Pattern Examples
Overview of object-oriented design patterns
Memento_Exercise.c
Go to the documentation of this file.
1
5
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "helpers/formatstring.h"
12#include "helpers/stack.h"
13#include "helpers/replace.h"
14
15#include "Memento_Memento.h"
16#include "Memento_TextObject.h"
17#include "Memento_Exercise.h"
18
19//=============================================================================
20//=============================================================================
21
27
35static void Memento_SaveForUndo(Memento_TextObject* text, const char* operation)
36{
37 if (text != NULL && operation != NULL)
38 {
39 Memento* memento = Memento_Create(Memento_TextObject_GetText(text), operation);
40 if (memento != NULL)
41 {
43 }
44 }
45}
46
47
54static void Memento_Operation_Replace(Memento_TextObject* source, const char* searchPattern, const char* replaceText)
55{
56 if (source != NULL && searchPattern != NULL && replaceText != NULL)
57 {
58 char* newText = replace_str(Memento_TextObject_GetText(source), searchPattern, replaceText);
59 if (newText != NULL)
60 {
61 Memento_TextObject_SetText(source, newText);
62 free(newText);
63 }
64 }
65}
66
72{
73 if (source != NULL)
74 {
75 // We will change the text object in-place because we can.
76 char* text = Memento_TextObject_GetText(source);
77
78 size_t textSize = strlen(text);
79 size_t halftextSize = textSize / 2;
80 for (size_t index = 0; index < halftextSize; ++index)
81 {
82 char c = text[index];
83 text[index] = text[textSize - index - 1];
84 text[textSize - index - 1] = c;
85 }
86 }
87}
88
95{
96 if (text != NULL)
97 {
98 if (_mementoUndoList != NULL)
99 {
100 Memento* lastMemento = Stack_Pop(&_mementoUndoList);
101 Memento_TextObject_SetText(text, lastMemento->text);
102
103 // Show off what we (un)did.
104 printf(" undoing operation %-31s: \"%s\"\n", lastMemento->name, Memento_TextObject_ToString(text));
105 Memento_Destroy(lastMemento);
106 }
107 }
108}
109
118static void Memento_ApplyReplaceOperation(Memento_TextObject* text, const char* searchPattern, const char* replaceText)
119{
120 if (text != NULL && searchPattern != NULL && replaceText != NULL)
121 {
122 char *operationName = formatstring("Replace '%s' with '%s'", searchPattern, replaceText);
123 if (operationName != NULL)
124 {
125 Memento_SaveForUndo(text, operationName);
126 Memento_Operation_Replace(text, searchPattern, replaceText);
127 printf(" operation %-31s: \"%s\"\n", operationName, Memento_TextObject_ToString(text));
128 free(operationName);
129 }
130 else
131 {
132 printf(" Error! Out of memory while creating operation name for replace operation!\n");
133 }
134 }
135}
136
137
145{
146 const char* operationName = "Reverse";
147 Memento_SaveForUndo(text, operationName);
149 printf(" operation %-31s: \"%s\"\n", operationName, Memento_TextObject_ToString(text));
150}
151
152//=============================================================================
153//=============================================================================
154
179// ! [Using Memento in C]
181{
182 printf("\nMemento_Exercise\n");
183
184 _mementoUndoList = NULL;
185
186 // The base text object to work from.
187 Memento_TextObject* text = Memento_TextObject_Create("This is a line of text on which to experiment.");
188 if (text != NULL)
189 {
190 printf(" Starting text: \"%s\"\n", Memento_TextObject_ToString(text));
191
192 // Apply four operations to the text.
193 Memento_ApplyReplaceOperation(text, "text", "painting");
194 Memento_ApplyReplaceOperation(text, "on", "off");
196 Memento_ApplyReplaceOperation(text, "i", "!");
197
198 printf(" Now perform undo until back to original\n");
199
200 // Now undo the four operations.
201 Memento_Undo(text);
202 Memento_Undo(text);
203 Memento_Undo(text);
204 Memento_Undo(text);
205
206 printf(" Final text : \"%s\"\n", Memento_TextObject_ToString(text));
207
209 }
210
211 printf(" Done.\n");
212}
213// ! [Using Memento in C]
void Memento_Exercise(void)
Example of using the Memento design pattern.
static void Memento_Undo(Memento_TextObject *text)
Perform an undo on the given Command_TextObject, using the mementos in the "global" undo list....
static void Memento_ApplyReverseOperation(Memento_TextObject *text)
Helper function to reverse the order of the characters in the given Memento_TextObject after adding a...
static void Memento_Operation_Replace(Memento_TextObject *source, const char *searchPattern, const char *replaceText)
An operation to search and replace text in a Memento_TextObject.
static void Memento_SaveForUndo(Memento_TextObject *text, const char *operation)
Take a snapshot of the given text object associated with the name of given operation.
static void Memento_ApplyReplaceOperation(Memento_TextObject *text, const char *searchPattern, const char *replaceText)
Helper function to replace a pattern with another string in the given Memento_TextObject after adding...
static StackEntry * _mementoUndoList
The list of memento objects that form a series of snapshots in time of a Memento_TextObject.
static void Memento_Operation_Reverse(Memento_TextObject *source)
An operation to reverse the characters in the given Memento_TextObject.
void Memento_Destroy(Memento *memento)
Destroy an existing instance of the Memento structure. After this function returns,...
Memento * Memento_Create(const char *text, const char *name)
Create a new instance of the Memento structure, initialized to the given text and name.
Declaration of the Memento structure and support functions, Memento_Create() and Memento_Destroy(),...
char * Memento_TextObject_GetText(Memento_TextObject *textObject)
Retrieve a pointer to the text contained within the Memento_TextObject. The text can be altered throu...
void Memento_TextObject_Destroy(Memento_TextObject *textObject)
Destroy the given Memento_TextObject object and release any used memory. After this function returns,...
Memento_TextObject * Memento_TextObject_Create(const char *text)
Create a new instance of the Memento_TextObject structure and initialize it with the given text.
void Memento_TextObject_SetText(Memento_TextObject *textObject, const char *newText)
Replace the existing text in the Memento_TextObject object with the given text.
const char * Memento_TextObject_ToString(Memento_TextObject *textObject)
Return a string representation of the Memento_TextObject. In this case, it is just the underlying tex...
Declaration of the Memento_TextObject structure and support functions, Memento_TextObject_Create(),...
Declaration of the Memento_Exercise() function as used in the Memento Pattern.
char * formatstring(const char *format,...)
Use the given string and arguments to return a buffer containing the formatted string....
Definition: formatstring.c:15
char * replace_str(const char *s, const char *str1, const char *str2)
Replace all occurrences of narrow string str1 with narrow string str2 in s, using case-sensitive sear...
Definition: replace.c:127
void Stack_Push(StackEntry **stack, void *item)
Push the given entry onto the given stack.
Definition: stack.c:40
void * Stack_Pop(StackEntry **stack)
Pop the last entry from the given stack, returning the item.
Definition: stack.c:63
Declaration of the StackEntry structure and the supporting functions that represents a simple stack.
Container for a string.
Represents a single memento (snapshot) of the text state before an operation is applied....
char * text
The snapshot to be remembered by the Memento.
const char * name
The operation name that triggered the need for this Memento.
Represents an entry on a simple stack that wraps an "item" represented by an opaque pointer.
Definition: stack.h:32