Jamoma API  0.6.0.a19
TTTextHandler.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief Handles text file reading and writing to be able to store / recall state of an object into/from text files.
6  *
7  * @authors Théo de la Hogue
8  *
9  * @copyright © 2010, Théo de la Hogue @n
10  * This code is licensed under the terms of the "New BSD License" @n
11  * http://creativecommons.org/licenses/BSD/
12  */
13 
14 
15 #include "TTTextHandler.h"
16 #include <fstream>
17 
18 #define thisTTClass TTTextHandler
19 #define thisTTClassName "TextHandler"
20 #define thisTTClassTags "text, handler"
21 
22 TT_MODULAR_CONSTRUCTOR,
23 mFilePath(kTTSymEmpty),
24 mWriter(NULL),
25 mReader(NULL),
26 mLine(NULL),
27 mTabCount(0),
28 mSpaceNumberForTab(4),
29 mFirstLine(NO),
30 mLastLine(NO),
31 mIsWriting(NO),
32 mIsReading(NO)
33 {
34  addAttribute(Object, kTypeObject);
35  addAttribute(SpaceNumberForTab, kTypeInt8);
36 
39 
40  addMessage(WriteAgain);
41  addMessage(ReadAgain);
42 }
43 
44 TTTextHandler::~TTTextHandler()
45 {
46  ;
47 }
48 
49 TTErr TTTextHandler::Write(const TTValue& args, TTValue& outputValue)
50 {
51  TTValue v, none;
52  TTObject aTTObject;
53 
54  // an object have to be selected
55  if (!mObject.valid())
56  return kTTErrGeneric;
57 
58  // memorize this object because it could change if the handler is used recursively
59  aTTObject = mObject;
60 
61  if (args.size() == 1) {
62 
63  mIsWriting = true;
64 
65  // if the first argument is kTypeSymbol : get the path of the file to write
66  if (args[0].type() == kTypeSymbol) {
67 
68  mFilePath = args[0];
69 
70  // Create a new text file
71  std::ofstream file(mFilePath.string(), std::ofstream::out);
72 
73  // Create a new string text
74  this->mWriter = new TTString();
75 
76  if (!file.is_open()) {
77  TT_ASSERT("TTTextHandler : Error creating the text file\n", true);
78  return kTTErrGeneric;
79  }
80 
81  // Call the WriteAsText method of the handled object
82  aTTObject.send("WriteAsText", TTObject(this));
83 
84  // Write the writer string into the file
85  file << this->mWriter->data();
86 
87  // Close the text file
88  file.close();
89 
90  // Clear the text
91  delete this->mWriter;
92  }
93 
94  // if the first argument is kTypePointer : get the text where to write
95  else if (args[0].type() == kTypePointer) {
96 
97  mWriter = (TTString*)((TTPtr)args[0]);
98 
99  // Call the WriteAsText method of the handled object
100  aTTObject.send("WriteAsText", TTObject(this));
101 
102  }
103  else
104  return kTTErrGeneric;
105 
106  mIsWriting = false;
107 
108  // Memorize the TTObject as the last handled object
109  mObject = aTTObject;
110 
111  return kTTErrNone;
112  }
113 
114  // else
115  return aTTObject.send("WriteAsText", TTObject(this));
116 }
117 
118 TTErr TTTextHandler::WriteAgain()
119 {
120  TTValue args;
121  TTValue dummy;
122 
123  args.append(mFilePath);
124  return Write(args, dummy);
125 }
126 
127 TTErr TTTextHandler::Read(const TTValue& args, TTValue& outputValue)
128 {
129  TTObject aTTObject;
130  size_t found, last, size;
131  TTUInt8 i;
132  TTString line;
133  TTValue none;
134 
135  // an object have to be selected
136  if (!mObject.valid())
137  return kTTErrGeneric;
138 
139  // memorize this object because it could change if the handler is used recursively
140  aTTObject = mObject;
141 
142  if (args.size() == 1)
143  {
144  mIsReading = true;
145 
146  // if the first argument is kTypeSymbol : get the path of the file to read
147  if (args[0].type() == kTypeSymbol)
148  {
149  mFilePath = args[0];
150 
151  std::ifstream file(mFilePath.c_str());
152 
153  if (!file.is_open())
154  {
155  TT_ASSERT("TTTextHandler::Read : Error opening the text file\n", true);
156  return kTTErrGeneric;
157  }
158 
159  // Start the document
160  mFirstLine = YES;
161  mLastLine = NO;
162 
163  while (!file.eof())
164  {
165  // parse line
166  std::string s_line;
167  std::getline(file, s_line);
168 
169  mLine = new TTValue(TTString(s_line));
170  mLine->fromString();
171 
172  aTTObject.send("ReadFromText", TTObject(this));
173 
174  if (mFirstLine)
175  mFirstLine = NO;
176 
177  delete mLine;
178  }
179 
180  // Close the reading
181  mLine = new TTValue();
182  mLastLine = YES;
183  aTTObject.send("ReadFromText", TTObject(this));
184  delete mLine;
185  }
186 
187  // if the first argument is kTypePointer : get the text to read
188  else if (args[0].type() == kTypePointer) {
189 
190  mReader = NULL;
191  mReader = (TTString*)((TTPtr)args[0]);
192 
193  if (mReader) {
194 
195  last = 0;
196  mFirstLine = YES;
197  mLastLine = NO;
198  found = mReader->find_first_of('\n');
199  size = mReader->size();
200 
201  while (!mLastLine)
202  {
203  mLine = NULL;
204 
205  // parse line
206  if (found != last) {
207  line = mReader->substr(last, found-last);
208 
209  // count white space
210  i = 0;
211  while (line[i] == ' ') i++;
212  mTabCount = i / mSpaceNumberForTab;
213 
214  // or count tab
215  if (mTabCount == 0)
216  while (line[mTabCount] == '\t') mTabCount++;
217 
218  mLine = new TTValue(line);
219  mLine->fromString();
220  }
221 
222  // check for a next line
223  last = found+1;
224  if (last <= size) {
225  found = mReader->find_first_of('\n', last);
226  found = found < size ? found : size;
227  }
228 
229  // else set last line flag on to close the reading
230  else {
231  mLine = new TTValue();
232  mLastLine = YES;
233  }
234 
235  // send the line (even an empty line for the last)
236  if (mLine) {
237 
238  aTTObject.send("ReadFromText", TTObject(this));
239 
240  // set first line flag off
241  mFirstLine = NO;
242  delete mLine;
243  }
244  }
245  }
246  }
247  else return kTTErrGeneric;
248 
249  mIsReading = false;
250 
251  // memorize the TTObject as the last handled object
252  mObject = aTTObject;
253 
254  return kTTErrNone;
255  }
256 
257  // else
258  return aTTObject.send("ReadFromText", TTObject(this));
259 }
260 
261 TTErr TTTextHandler::ReadAgain()
262 {
263  TTValue args;
264  TTValue dummy;
265 
266  args.append(mFilePath);
267  return Read(args, dummy);
268 }
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTObjectBase to handle text file reading and writing to be able to store / recall state of an object ...
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
Object type.
Definition: TTBase.h:283
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
Symbol type.
Definition: TTBase.h:282
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
Pointer type.
Definition: TTBase.h:284
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
8-bit signed integer, range is -128 through 127.
Definition: TTBase.h:273
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174