le_pathIter.h

Go to the documentation of this file.
1 
2 //--------------------------------------------------------------------------------------------------
3 /**
4  * @page c_pathIter Path Iterator API
5  *
6  * @ref le_pathIter.h "API Reference"
7  *
8  * <HR>
9  *
10  * Paths are text strings that contain nodes separated by character separators. Paths are used in
11  * many common applications like file system addressing, URLs, etc. so being able to parse them
12  * is quite important.
13  *
14  * The Path Iterator API is intended for general purpose use and supports UTF-8 null-terminated
15  * strings and multi-character separators.
16  *
17  * This API can be used to iterate over paths, traversing the path node-by-node. Or creating and
18  * combining paths together while ensuring that the resultant paths are properly normalized. For
19  * instance the following path:
20  *
21  * @verbatim
22  /a//path/to/a///some/../place
23  @endverbatim
24  *
25  * Would be normalized to the path:
26  *
27  * @verbatim
28  /a/path/to/a/place
29  @endverbatim
30  *
31  * @section c_pathIter_create Create a Path Iterator
32  *
33  * Before iterating over a path, a path object must first be created by calling either
34  * @c le_pathIter_Create(), or @c le_pathIter_CreateForUnix(). @c le_pathIter_Create() will
35  * allow you to create an iterator for one of many different path styles. While
36  * @c le_pathIter_CreateForUnix() will create an iterator preconfigured for Unix style paths.
37  *
38  * All strings to this API must be formatted as UTF-8 null-terminated strings.
39  *
40  * When the path object is no longer needed, it can be deleted by calling le_pathIter_Delete().
41  *
42  * @section c_pathIter_iterate Iterating a Path
43  *
44  * Once an object is created, the nodes in it can be accessed using @c le_pathIter_GoToNext(), or
45  * @c le_pathIter_GoToPrev(). To start over at the beginning of the path call
46  * @c le_pathIter_GoToStart(). To position the iterator at the end of the path, use
47  * @c le_pathIter_GoToEnd(). On creation, the default position of the iterator is at the end of
48  * the path.
49  *
50  * Code sample, iterate over an entire path:
51  *
52  * @code
53  *
54  * // Create an iterator object, and move it to the front of the path.
55  * le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(myPathPtr);
56  *
57  * if (le_pathIter_IsEmpty(iteratorRef))
58  * {
59  * return;
60  * }
61  *
62  * le_pathIter_GoToStart(iteratorRef);
63  *
64  * // Now go through all of the path nodes and print out each one.
65  * do
66  * {
67  * char buffer[BUFFER_SIZE] = { 0 };
68  *
69  * if (le_pathIter_GetCurrentNode(iteratorRef, buffer, BUFFER_SIZE) == LE_OK)
70  * {
71  * printf("%s\n", buffer);
72  * }
73  * }
74  * while (le_pathIter_GoToNext(iteratorRef) != LE_NOT_FOUND);
75  *
76  * // All done with the iterator, so free it now.
77  * le_pathIter_Delete(iteratorRef);
78  *
79  * @endcode
80  *
81  * @note @c le_pathIter_GetNextNode() and @c le_pathIter_GetPreviousNode() treat consecutive
82  * separators as a single separator.
83  *
84  * @section c_pathIter_absoluteRelative Absolute versus Relative Paths
85  *
86  * Absolute paths begin with one or more separators. Relative paths do not begin with a separator.
87  * @c le_pathIter_IsAbsolute() can be used to determine if the path is absolute or relative.
88  *
89  * @section c_pathIter_modifyPath Modifying Paths
90  *
91  * In addition to pure iteration, the path iterator can allow you to modify a path. For instance,
92  * you can iterate to a node in the path and use @c le_pathIter_Truncate() to truncate everything at
93  * and after that point. While you can use @c le_pathIter_Append() to add new path nodes at the end
94  * of the path.
95  *
96  * Take the following code:
97  *
98  * @code
99  *
100  * le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/path/to/a/place");
101  * char fullPath[PATH_SIZE] = { 0 };
102  *
103  * le_pathIter_GoToStart(iteratorRef);
104  *
105  * le_pathIter_GoToNext(iteratorRef);
106  * le_pathIter_GoToNext(iteratorRef);
107  * le_pathIter_GoToNext(iteratorRef);
108  *
109  * le_pathIter_Truncate(iteratorRef);
110  *
111  * le_pathIter_Append(iteratorRef, "nowhere");
112  *
113  * le_pathIter_GetPath(iteratorRef, fullPath, PATH_SIZE);
114  *
115  * LE_ASSERT(strcmp(fullPath, "/a/path/to/nowhere") == 0);
116  *
117  * @endcode
118  *
119  * Note that @c le_pathIter_Append() will also normalize paths as it appends. So, the following
120  * example has the same effect as the previous one.
121  *
122  * @code
123  *
124  * le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/path/to/a/place");
125  * char fullPath[PATH_SIZE] = { 0 };
126  *
127  * le_pathIter_Append(iteratorRef, "../../nowhere");
128  * le_pathIter_GetPath(iteratorRef, fullPath, PATH_SIZE);
129  *
130  * le_pathIter_GetPath(iteratorRef, fullPath, PATH_SIZE);
131  *
132  * LE_ASSERT(strcmp(fullPath, "/a/path/to/nowhere") == 0);
133  *
134  * @endcode
135  *
136  * <HR>
137  *
138  * Copyright (C) Sierra Wireless Inc.
139  * license.
140  */
141 //--------------------------------------------------------------------------------------------------
142 /** @file le_pathIter.h
143  *
144  * Legato @ref c_pathIter include file.
145  *
146  * Copyright (C) Sierra Wireless Inc.
147  * license.
148  */
149 //--------------------------------------------------------------------------------------------------
150 
151 #ifndef LEGATO_PATH_ITER_INCLUDE_GUARD
152 #define LEGATO_PATH_ITER_INCLUDE_GUARD
153 
154 
155 //--------------------------------------------------------------------------------------------------
156 /**
157  * Objects of this type are used to iterate and manipulate path strings.
158  */
159 //--------------------------------------------------------------------------------------------------
160 typedef struct le_pathIter_t* le_pathIter_Ref_t;
161 
162 
163 //--------------------------------------------------------------------------------------------------
164 /**
165  * Create a new path iterator object. On creation, the default position of the iterator is at the
166  * end of the path.
167  *
168  * @return A new path object setup with the given parameters.
169  */
170 //--------------------------------------------------------------------------------------------------
172 (
173  const char* pathPtr, ///< [IN] Optional. Pointer to the inital path to use.
174  const char* separatorPtr, ///< [IN] Required. Path separator to use. The separator can not
175  ///< be NULL or empty.
176  const char* parentSpecPtr, ///< [IN] Optional. Used to traverse upwards in a path. Leave as
177  ///< NULL or empty to not use. This acts like how ".." is used
178  ///< in a filesystem path.
179  const char* currentSpecPtr ///< [IN] Optional. Used to refer to a current node. Much like how
180  ///< a '.' is used in a filesystem path.
181 );
182 
183 
184 //--------------------------------------------------------------------------------------------------
185 /**
186  * Create a new path iterator object that is pre-configured for Unix styled paths. On creation,
187  * the default position of the iterator is at the end of the path.
188  *
189  * The parameters are configured as follows:
190  *
191  * - separator: "/"
192  * - parentSpec: ".."
193  * - currentSpec: "."
194  *
195  * @return A new path iterator object that's ready for iterating on Unix style paths.
196  */
197 //--------------------------------------------------------------------------------------------------
199 (
200  const char* pathPtr ///< [IN] Optional. Create an iterator for this path, or start with an
201  ///< empty path.
202 );
203 
204 
205 //--------------------------------------------------------------------------------------------------
206 /**
207  * Create a clone of an existing path iterator object.
208  *
209  * @return A new path iterator object that is a duplicate of the original one.
210  */
211 //--------------------------------------------------------------------------------------------------
213 (
214  le_pathIter_Ref_t originalRef ///< [IN] The path object to duplicate.
215 );
216 
217 
218 //--------------------------------------------------------------------------------------------------
219 /**
220  * Delete an iterator object and free it's memory.
221  */
222 //--------------------------------------------------------------------------------------------------
224 (
225  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to destroy.
226 );
227 
228 
229 //--------------------------------------------------------------------------------------------------
230 /**
231  * Read the string that is being used to represent path separators in this iterator object.
232  */
233 //--------------------------------------------------------------------------------------------------
235 (
236  le_pathIter_Ref_t iterRef, ///< [IN] The iterator object to read.
237  char* bufferPtr, ///< [OUT] The string buffer to write to.
238  size_t bufferSize ///< [IN] The size of the buffer being written to.
239 );
240 
241 
242 //--------------------------------------------------------------------------------------------------
243 /**
244  * Read the string that represents parent nodes in a path string. By for Unix style paths this is
245  * "..". If an empty string is used, then it is ignored for the purposes of appending and
246  * normalizing paths.
247  */
248 //--------------------------------------------------------------------------------------------------
250 (
251  le_pathIter_Ref_t iterRef, ///< [IN] The iterator object to read.
252  char* bufferPtr, ///< [OUT] The string buffer to write to.
253  size_t bufferSize ///< [IN] The size of the buffer being written to.
254 );
255 
256 
257 //--------------------------------------------------------------------------------------------------
258 /**
259  * Read the iterators string for the current node specifier. For Unix style paths for this is ".".
260  * If an empty string is used, then this is ignored for the purposes of appending and normalizing
261  * paths.
262  */
263 //--------------------------------------------------------------------------------------------------
265 (
266  le_pathIter_Ref_t iterRef, ///< [IN] The iterator object to read.
267  char* bufferPtr, ///< [OUT] The string buffer to write to.
268  size_t bufferSize ///< [IN] The size of the string buffer being written to.
269 );
270 
271 
272 //--------------------------------------------------------------------------------------------------
273 /**
274  * Get a copy of the path currently contained within the iterator.
275  *
276  * @return LE_OK if the copy is successful.
277  * LE_OVERFLOW if the buffer isn't big enough for the path string.
278  */
279 //--------------------------------------------------------------------------------------------------
281 (
282  le_pathIter_Ref_t iterRef, ///< [IN] The iterator object to read.
283  char* bufferPtr, ///< [OUT] The string buffer to write to.
284  size_t bufferSize ///< [IN] The size of the buffer being written to.
285 );
286 
287 
288 //--------------------------------------------------------------------------------------------------
289 /**
290  * Jump the iterator to the beginning of the path.
291  *
292  * @return LE_OK if the move was successful.
293  * LE_NOT_FOUND if the path is empty, or only contains a separator.
294  */
295 //--------------------------------------------------------------------------------------------------
297 (
298  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to update.
299 );
300 
301 
302 //--------------------------------------------------------------------------------------------------
303 /**
304  * Jump the iterator to the end of the path.
305  *
306  * @return LE_OK if the move was successful.
307  * LE_NOT_FOUND if the path is empty, or only contains a separator.
308  */
309 //--------------------------------------------------------------------------------------------------
311 (
312  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to update.
313 );
314 
315 
316 //--------------------------------------------------------------------------------------------------
317 /**
318  * Move to the next node in the path.
319  *
320  * @return LE_OK if the itrator was successful in jumping to the next node. LE_NOT_FOUND is
321  * returned if there are no more nodes to move to in the path.
322  */
323 //--------------------------------------------------------------------------------------------------
325 (
326  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to update.
327 );
328 
329 
330 //--------------------------------------------------------------------------------------------------
331 /**
332  * Move to the previous node in the path.
333  *
334  * @return LE_OK if the iterator was successfuly moved, LE_NOT_FOUND if there are no prior nodes to
335  * move to.
336  */
337 //--------------------------------------------------------------------------------------------------
339 (
340  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to update.
341 );
342 
343 
344 //--------------------------------------------------------------------------------------------------
345 /**
346  * Get the text for the node the itrator is pointing at.
347  *
348  * @return
349  * LE_OK if succesful.
350  * LE_OVERFLOW if the bufferPtr is too small to hold the whole string.
351  * LE_NOT_FOUND if the iterator is at the end of the path. Or if the path is empty, or simply
352  * consists of a separator.
353  */
354 //--------------------------------------------------------------------------------------------------
356 (
357  le_pathIter_Ref_t iterRef, ///< [IN] The iterator object to read.
358  char* bufferPtr, ///< [OUT] The utf-8 formatted text buffer to write to.
359  size_t bufferSize ///< [IN] The size in bytes of the text buffer.
360 );
361 
362 
363 //--------------------------------------------------------------------------------------------------
364 /**
365  * Truncate the path at the current iterator node. If the iterator is at the beginning of the
366  * path, then the whole path is cleared. If the iterator is at the end of the path, then nothing
367  * happens.
368  *
369  * Once done, then the iterator will be pointing at the new end of the path.
370  */
371 //--------------------------------------------------------------------------------------------------
373 (
374  le_pathIter_Ref_t iterRef ///< [IN] The iterator to update.
375 );
376 
377 
378 //--------------------------------------------------------------------------------------------------
379 /**
380  * Take the new string path and combine it with the object's existing path.
381  *
382  * @note This function looks for the current and parent node strings and treats them specially.
383  * So, (assuming defaults,) combining the path "/a/b" with the path "../x" will give you the
384  * combined path of: "/a/x".
385  *
386  * @note Appending a non-relative path onto an existing path effectivly replaces the current path,
387  * for example, appending /a/rooted/path, onto the existing /a/seperate/path will given you
388  * the path: /a/rooted/path.
389  *
390  * @note This will automatically reset the internal iterator to point at the end of the newly formed
391  * path. Also, this function always appends to the end of a path, ignoring the current
392  * position of the iterator.
393  *
394  * @return
395  * LE_OK if successful.
396  * LE_OVERFLOW if the output buffer is too small for the new string.
397  * LE_UNDERFLOW if combining the path the new path tries to traverse past the root. For
398  * example: "/a/b" + "../../../x" will result in LE_UNDERFLOW. However if the base path is
399  * relative, "a/b", then the resulting string will be "../x" and a return code of LE_OK.
400  */
401 //--------------------------------------------------------------------------------------------------
403 (
404  le_pathIter_Ref_t iterRef, ///< [IN] The path object to write to.
405  const char* pathStr ///< [IN] The new path segment to append.
406 );
407 
408 
409 //--------------------------------------------------------------------------------------------------
410 /**
411  * Is this an absolute or relative path?
412  *
413  * @return True if the path is absolute, that is that it begins with a separator. False if the path
414  * is considered relative.
415  */
416 //--------------------------------------------------------------------------------------------------
418 (
419  le_pathIter_Ref_t iterRef ///< [IN] The iterator object to read.
420 );
421 
422 
423 //--------------------------------------------------------------------------------------------------
424 /**
425  * Is the path object holding an empty string?
426  *
427  * @return True if the path is empty, false if not.
428  */
429 //--------------------------------------------------------------------------------------------------
431 (
432  le_pathIter_Ref_t iterRef ///< The path object to read.
433 );
434 
435 
436 #endif // LEGATO_PATH_ITER_INCLUDE_GUARD
le_result_t le_pathIter_GetPath(le_pathIter_Ref_t iterRef, char *bufferPtr, size_t bufferSize)
void le_pathIter_Truncate(le_pathIter_Ref_t iterRef)
bool le_pathIter_IsAbsolute(le_pathIter_Ref_t iterRef)
le_result_t
Definition: le_basics.h:35
bool le_pathIter_IsEmpty(le_pathIter_Ref_t iterRef)
le_result_t le_pathIter_GetCurrentSpecifier(le_pathIter_Ref_t iterRef, char *bufferPtr, size_t bufferSize)
le_result_t le_pathIter_GoToEnd(le_pathIter_Ref_t iterRef)
le_pathIter_Ref_t le_pathIter_Create(const char *pathPtr, const char *separatorPtr, const char *parentSpecPtr, const char *currentSpecPtr)
void le_pathIter_Delete(le_pathIter_Ref_t iterRef)
le_result_t le_pathIter_GetParentSpecifier(le_pathIter_Ref_t iterRef, char *bufferPtr, size_t bufferSize)
le_result_t le_pathIter_GetCurrentNode(le_pathIter_Ref_t iterRef, char *bufferPtr, size_t bufferSize)
le_result_t le_pathIter_GoToStart(le_pathIter_Ref_t iterRef)
le_result_t le_pathIter_GoToNext(le_pathIter_Ref_t iterRef)
le_result_t le_pathIter_GetSeparator(le_pathIter_Ref_t iterRef, char *bufferPtr, size_t bufferSize)
struct le_pathIter_t * le_pathIter_Ref_t
Definition: le_pathIter.h:160
le_result_t le_pathIter_Append(le_pathIter_Ref_t iterRef, const char *pathStr)
le_pathIter_Ref_t le_pathIter_CreateForUnix(const char *pathPtr)
le_pathIter_Ref_t le_pathIter_Clone(le_pathIter_Ref_t originalRef)
le_result_t le_pathIter_GoToPrev(le_pathIter_Ref_t iterRef)