//-------------------------------------------------------------------------------------------------- le_result_t ni_GoToNextSibling ( ni_IteratorRef_t iteratorRef ///< The iterator object to access. ) //-------------------------------------------------------------------------------------------------- { // If the current node exists, then look to it for a sibling node. Otherwise, a non-existant // node can not have siblings. if (iteratorRef->currentNodeRef != NULL) { tdb_NodeRef_t newNodeRef = tdb_GetNextActiveSiblingNode(iteratorRef->currentNodeRef); if (newNodeRef == NULL) { return LE_NOT_FOUND; } // Looks like we found a new node, so replace the node name at the end of the path. iteratorRef->currentNodeRef = newNodeRef; char namePtr[MAX_NODE_NAME] = { 0 }; tdb_GetNodeName(newNodeRef, namePtr, MAX_NODE_NAME); if (le_pathIter_GoToEnd(iteratorRef->pathIterRef) != LE_NOT_FOUND) { le_pathIter_Truncate(iteratorRef->pathIterRef); } le_pathIter_Append(iteratorRef->pathIterRef, namePtr); return LE_OK; } return LE_NOT_FOUND; }
//-------------------------------------------------------------------------------------------------- le_result_t ni_GoToParent ( ni_IteratorRef_t iteratorRef ///< The iterator object to access. ) //-------------------------------------------------------------------------------------------------- { // Update our path. if (le_pathIter_Append(iteratorRef->pathIterRef, "..") == LE_UNDERFLOW) { // Looks like there are no more parents in the chain. return LE_NOT_FOUND; } // Now, if we have a current node, just get it's parent node. Otherwise make an attempt to see // if the requested parent node exists. if (iteratorRef->currentNodeRef != NULL) { iteratorRef->currentNodeRef = tdb_GetNodeParent(iteratorRef->currentNodeRef); LE_ASSERT(iteratorRef->currentNodeRef != NULL); } else { // Make an attempt to get the new current node. iteratorRef->currentNodeRef = ni_GetNode(iteratorRef, ""); } return LE_OK; }
//-------------------------------------------------------------------------------------------------- le_result_t ni_GoToFirstChild ( ni_IteratorRef_t iteratorRef ///< The iterator object to access. ) //-------------------------------------------------------------------------------------------------- { if (iteratorRef->currentNodeRef != NULL) { tdb_NodeRef_t newNodeRef = tdb_GetFirstActiveChildNode(iteratorRef->currentNodeRef); if (newNodeRef == NULL) { return LE_NOT_FOUND; } iteratorRef->currentNodeRef = newNodeRef; char namePtr[MAX_NODE_NAME] = { 0 }; tdb_GetNodeName(newNodeRef, namePtr, MAX_NODE_NAME); le_pathIter_Append(iteratorRef->pathIterRef, namePtr); return LE_OK; } return LE_NOT_FOUND; }
//-------------------------------------------------------------------------------------------------- le_result_t ni_GoToFirstChild ( ni_IteratorRef_t iteratorRef ///< [IN] The iterator object to access. ) //-------------------------------------------------------------------------------------------------- { if (iteratorRef->currentNodeRef != NULL) { tdb_NodeRef_t newNodeRef = tdb_GetFirstActiveChildNode(iteratorRef->currentNodeRef); if (newNodeRef == NULL) { return LE_NOT_FOUND; } iteratorRef->currentNodeRef = newNodeRef; char name[LE_CFG_NAME_LEN_BYTES] = ""; tdb_GetNodeName(newNodeRef, name, sizeof(name)); le_pathIter_Append(iteratorRef->pathIterRef, name); return LE_OK; } return LE_NOT_FOUND; }
//-------------------------------------------------------------------------------------------------- tdb_NodeRef_t ni_GetNode ( ni_IteratorRef_t iteratorRef, ///< The iterator object to access. const char* subPathPtr ///< Optional, can be used to specify a node relative to the ///< current one. ) //-------------------------------------------------------------------------------------------------- { // Check to see if we have a current node. If we do, then attempt to traverse from our current // node, to the requested sub-node. If the new path is NULL or empty, then we'll just end up // getting our current node. if (iteratorRef->currentNodeRef != NULL) { le_pathIter_Ref_t newPathRef = le_pathIter_CreateForUnix(subPathPtr); tdb_NodeRef_t nodeRef = tdb_GetNode(iteratorRef->currentNodeRef, newPathRef); le_pathIter_Delete(newPathRef); return nodeRef; } // Ok, the iterator doesn't have a current node. So, copy iterator's existing path, and append // the new sub path to the existing path. Once that's done, attempt to find the requested node // in the tree. If the node still can not be found, return NULL. le_pathIter_Ref_t newPathRef = le_pathIter_Clone(iteratorRef->pathIterRef); tdb_NodeRef_t nodeRef = NULL; le_result_t result = LE_OK; if (subPathPtr != NULL) { result = le_pathIter_Append(newPathRef, subPathPtr); } // Make sure that the append was successful. If it is, get the node. if (result == LE_OVERFLOW) { tu_TerminateClient(iteratorRef->sessionRef, "Specified path too large."); } else if (result == LE_UNDERFLOW) { tu_TerminateClient(iteratorRef->sessionRef, "Specified path attempts to iterate below root."); } else { nodeRef = tdb_GetNode(tdb_GetRootNode(iteratorRef->treeRef), newPathRef); } le_pathIter_Delete(newPathRef); return nodeRef; }
//-------------------------------------------------------------------------------------------------- static le_result_t CloneAndAppendPath ( ni_IteratorRef_t iteratorRef, ///< [IN] The iterator to read. const char* subPathPtr, ///< [IN] Optionally, a sub-path to traverse to. le_pathIter_Ref_t* newPathIterRefPtr ///< [OUT] Pointer to a to-be newly created ref. Must be ///< NULL on entry! ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(*newPathIterRefPtr == NULL); le_pathIter_Ref_t newPathRef = le_pathIter_Clone(iteratorRef->pathIterRef); le_result_t result = LE_OK; if (subPathPtr != NULL) { result = le_pathIter_Append(newPathRef, subPathPtr); } if (result != LE_OK) { char* terminateMessage; switch (result) { case LE_OVERFLOW: terminateMessage = "Specified path too large."; break; case LE_UNDERFLOW: terminateMessage = "Specified path attempts to iterate below root."; break; default: terminateMessage = "Unexpected error while appending path."; break; } iteratorRef->isTerminated = true; tu_TerminateConfigClient(iteratorRef->sessionRef, terminateMessage); le_pathIter_Delete(newPathRef); return result; } *newPathIterRefPtr = newPathRef; return result; }
//-------------------------------------------------------------------------------------------------- le_result_t ni_GetPathForNode ( ni_IteratorRef_t iteratorRef, ///< The iterator object to access. const char* subPathPtr, ///< Optional, can be used to specify a node relative to the ///< current one. char* destBufferPtr, ///< The buffer to copy string data into. size_t bufferMax ///< The maximum size of the string buffer. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(iteratorRef != NULL); LE_ASSERT(destBufferPtr != NULL); LE_ASSERT(bufferMax > 0); // Check to see if they're looking for a path to a node relative to the current one. if ( (subPathPtr != NULL) && (strcmp(subPathPtr, "") != 0)) { // Build up a new path based on the existing path. le_pathIter_Ref_t newPathRef = le_pathIter_Clone(iteratorRef->pathIterRef); le_result_t result = le_pathIter_Append(newPathRef, subPathPtr); if (result == LE_OVERFLOW) { tu_TerminateClient(iteratorRef->sessionRef, "Specified path too large."); } else if (result == LE_UNDERFLOW) { tu_TerminateClient(iteratorRef->sessionRef, "Specified path attempts to iterate below root."); } else { result = le_pathIter_GetPath(newPathRef, destBufferPtr, bufferMax); } le_pathIter_Delete(newPathRef); return result; } // Simply return the current path. return le_pathIter_GetPath(iteratorRef->pathIterRef, destBufferPtr, bufferMax); }
//-------------------------------------------------------------------------------------------------- le_result_t ni_GoToNode ( ni_IteratorRef_t iteratorRef, ///< The iterator object to access. const char* newPathPtr ///< Path to the new location in the tree to jump to. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(iteratorRef != NULL); LE_ASSERT(le_pathIter_IsAbsolute(iteratorRef->pathIterRef) == true); le_result_t result = le_pathIter_Append(iteratorRef->pathIterRef, newPathPtr); if (result == LE_OK) { tdb_TreeRef_t treeRef = iteratorRef->treeRef; iteratorRef->currentNodeRef = tdb_GetNode(tdb_GetRootNode(treeRef), iteratorRef->pathIterRef); } return result; }
static void TestUnixStyleAppends(void) { LE_INFO("======== Test Unix Style Appends."); { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/b/c/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/b/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../../x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../../../x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../../../../x/y/z") == LE_UNDERFLOW); LE_TEST(TestPath(iteratorRef, "/")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../../../x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "../../../../x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "../x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "/x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "/x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c"); LE_TEST(le_pathIter_Append(iteratorRef, "./x/y/z") == LE_OK); LE_TEST(TestPath(iteratorRef, "a/b/c/x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(""); LE_TEST(le_pathIter_Append(iteratorRef, "./x/y/./z") == LE_OK); LE_TEST(TestPath(iteratorRef, "./x/y/z")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(""); LE_TEST(le_pathIter_Append(iteratorRef, "/a//path/to/a///some/../place") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/to/a/place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_Create("", "::", "^^", "__"); LE_TEST(le_pathIter_Append(iteratorRef, "__::a::::path::to::__::a::some::^^::place") == LE_OK); LE_TEST(TestPath(iteratorRef, "__::a::path::to::a::place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_Create("::", "::", "^^", "__"); LE_TEST(le_pathIter_Append(iteratorRef, "__::a::::path::to::__::a::some::^^::place") == LE_OK); LE_TEST(TestPath(iteratorRef, "::a::path::to::a::place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_Create("", "/", NULL, NULL); LE_TEST(le_pathIter_Append(iteratorRef, "/a//path/./to/a///some/../place") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/./to/a/some/../place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(""); LE_TEST(le_pathIter_Append(iteratorRef, "../../../a//path/") == LE_OK); LE_TEST(TestPath(iteratorRef, "../../../a/path")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(""); LE_TEST(le_pathIter_Append(iteratorRef, "/a//path/to/a///some/../place") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/to/a/place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); LE_TEST(le_pathIter_GoToStart(iteratorRef) == LE_OK); LE_TEST(le_pathIter_GoToNext(iteratorRef) == LE_OK); LE_TEST(le_pathIter_GoToNext(iteratorRef) == LE_OK); LE_TEST(le_pathIter_GoToNext(iteratorRef) == LE_OK); le_pathIter_Truncate(iteratorRef); LE_TEST(le_pathIter_Append(iteratorRef, "nowhere") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/to/nowhere")); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix(""); LE_TEST(le_pathIter_Append(iteratorRef, "/a//path/to/a///some/../place") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/to/a/place")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); LE_TEST(le_pathIter_Append(iteratorRef, "../../nowhere") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/path/to/nowhere")); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c"); LE_TEST(TestPath(iteratorRef, "/a/b/c")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/b")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/b/c/"); LE_TEST(TestPath(iteratorRef, "/a/b/c")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "/a/b")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c"); LE_TEST(TestPath(iteratorRef, "a/b/c")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "a/b")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/b/c/"); LE_TEST(TestPath(iteratorRef, "a/b/c")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "a/b")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a"); LE_TEST(TestPath(iteratorRef, "/a")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "/")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("/a/"); LE_TEST(TestPath(iteratorRef, "/a")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "/")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == true); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a"); LE_TEST(TestPath(iteratorRef, "a")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } { le_pathIter_Ref_t iteratorRef = le_pathIter_CreateForUnix("a/"); LE_TEST(TestPath(iteratorRef, "a")); LE_TEST(le_pathIter_Append(iteratorRef, "..") == LE_OK); LE_TEST(TestPath(iteratorRef, "")); LE_TEST(le_pathIter_IsAbsolute(iteratorRef) == false); le_pathIter_Delete(iteratorRef); } }
//-------------------------------------------------------------------------------------------------- le_result_t ni_SetNodeName ( ni_IteratorRef_t iteratorRef, ///< [IN] The iterator object to access. const char* pathPtr, ///< [IN] Optional path to another node in the tree. const char* namePtr ///< [IN] The new name to use. ) //-------------------------------------------------------------------------------------------------- { // Try to get or create the requested node. If the optional sub-path results in a new path that // overflows, then the node get will fail. tdb_NodeRef_t nodeRef = ni_TryCreateNode(iteratorRef, pathPtr); le_result_t result = LE_OK; if (nodeRef) { // Ok, the existing path is ok. Cache the existing node name, in case we have to revert it // later, then set the new name. We may have to revert the name later, because, while the // new name itself may be ok. The name may actually be too long for the path limit. char oldName[LE_CFG_NAME_LEN_BYTES] = ""; LE_ASSERT(tdb_GetNodeName(nodeRef, oldName, sizeof(oldName)) == LE_OK); result = tdb_SetNodeName(nodeRef, namePtr); if (result == LE_OK) { // The new name passed validation, now we have to make sure that the full path to the // node is still ok. So, first we have to check, was a relative path used. if (strcmp(pathPtr, "") == 0) { // Looks like the caller was using the iterator's current node. So, remove the old // name from the end of the iterator's current path, and append the new name. If // this fails, it's because the new absolute path is too long, so name change fails, // and we have to revert the changes. LE_ASSERT(le_pathIter_Append(iteratorRef->pathIterRef, "..") == LE_OK); result = le_pathIter_Append(iteratorRef->pathIterRef, namePtr); if (result != LE_OK) { LE_ASSERT(le_pathIter_Append(iteratorRef->pathIterRef, oldName) == LE_OK); } } else { // The user is accessing a node relative to the iterator's current node. So, we // need too build up a new path and validate that the new name still fits within our // limits. The new path ref is for validation only and can be safely discarded once // the check is complete. le_pathIter_Ref_t newPathRef = le_pathIter_Clone(iteratorRef->pathIterRef); result = le_pathIter_Append(newPathRef, pathPtr); if (result == LE_OK) { LE_ASSERT(le_pathIter_Append(newPathRef, "..") == LE_OK); result = le_pathIter_Append(newPathRef, namePtr); } le_pathIter_Delete(newPathRef); } // If we got to this point and everything is ok, then we know that the name set was ok, // and that the resultant path with the new name is also ok. So, make sure that this // node exists in the next commit. Otherwise, revert the node to it's old name and // report the error to the caller. if (result == LE_OK) { tdb_EnsureExists(nodeRef); } else { LE_ASSERT(tdb_SetNodeName(nodeRef, oldName) == LE_OK); } } } return result; }