-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathTreeRenameNode.c
More file actions
269 lines (240 loc) · 8.4 KB
/
Copy pathTreeRenameNode.c
File metadata and controls
269 lines (240 loc) · 8.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/*
Copyright (c) 2017, Massachusetts Institute of Technology All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*------------------------------------------------------------------------------
Name: TreeRenameNode
Type: C function
Author: Josh Stillerman
MIT Plasma Fusion Center
Date: 26-FEB-1988
Purpose: Rename a node in a tree.
------------------------------------------------------------------------------
Call sequence: status = TreeRenameNode(nid_ptr, newnamedsc_ptr)
------------------------------------------------------------------------------
Copyright (c) 1987
Property of Massachusetts Institute of Technology, Cambridge MA 02139.
This program cannot be copied or distributed in any form for non-MIT
use without specific written approval of MIT Plasma Fusion Center
Management.
---------------------------------------------------------------------------
Description:
This routine modifies the name of an existing node in a tree. It does NOT
move the node from its location in the tree.
+-----------------------------------------------------------------------------*/
#include "treeshrp.h"
#include <ctype.h>
#include <mdsdescrip.h>
#include <mdsplus/mdsconfig.h>
#include <ncidef.h>
#include <stdlib.h>
#include <string.h>
#include <treeshr.h>
#include <usagedef.h>
static int FixParentState(PINO_DATABASE *dblist, NODE *parent_ptr,
NODE *child_ptr);
extern int tree_set_parent_state(PINO_DATABASE *db, NODE *node,
unsigned int state);
extern void **TreeCtx();
int TreeRenameNode(int nid, char const *newname)
{
return _TreeRenameNode(*TreeCtx(), nid, newname);
}
int _TreeRenameNode(void *dbid, int nid, char const *newname)
{
PINO_DATABASE *dblist = (PINO_DATABASE *)dbid;
NID *nid_ptr = (NID *)&nid;
NODE *pptr, *nptr, *newnode, *oldnode_ptr;
char *newnode_name = 0;
int is_child;
int status;
char *upcase_name;
int i;
/*****************************************************
Make sure that the tree is open and OK and editable
*****************************************************/
if (!(IS_OPEN_FOR_EDIT(dblist)))
{
return TreeNOEDIT;
}
upcase_name = strdup(newname);
/**************************
Convert to upper case.
***************************/
for (i = 0; i < (int)strlen(newname); i++)
{
upcase_name[i] = (char)toupper(newname[i]);
}
upcase_name[i] = 0;
/****************************************************
make sure that the new node is not already there
***************************************************/
status = _TreeFindNode(dbid, upcase_name, &i);
if (STATUS_OK)
{
status = TreeALREADY_THERE;
goto cleanup;
}
/******************************************************
Make sure the new node's parent is in the tree
******************************************************/
status =
TreeFindParent(dblist, upcase_name, &newnode, &newnode_name, &is_child);
if (STATUS_NOT_OK)
return status;
/************************************************
Make sure that the node being renamed is not
an ancestor of the destination. (This check
insures that you are not renameing the node
off into space.)
************************************************/
oldnode_ptr = nid_to_node(dblist, (nid_ptr));
for (nptr = newnode; nptr; nptr = parent_of(dblist, nptr))
{
if (nptr == oldnode_ptr)
{
status = TreeINVPATH;
goto cleanup;
}
}
/************************************************
Make sure that a node with a non-STRUCTURE usage is
not being renamed into a son.
************************************************/
if (is_child)
{
if (oldnode_ptr->usage != TreeUSAGE_STRUCTURE)
{
status = TreeINVPATH;
goto cleanup;
}
}
/************************************************
OK so far so disconnect the old node
*************************************************/
pptr = parent_of(dblist, oldnode_ptr);
if (child_of(dblist, pptr) == oldnode_ptr)
{
if (oldnode_ptr->brother)
{
pptr->child = node_offset(brother_of(dblist, oldnode_ptr), pptr);
}
else
pptr->child = 0;
}
else
{
for (nptr = child_of(dblist, pptr);
nptr && (brother_of(dblist, nptr) != oldnode_ptr);
nptr = brother_of(dblist, nptr))
;
if (nptr)
{
if (oldnode_ptr->brother)
{
nptr->brother = node_offset(brother_of(dblist, oldnode_ptr), nptr);
}
else
nptr->brother = 0;
}
else if (member_of(pptr) == oldnode_ptr)
{
if (oldnode_ptr->brother)
{
pptr->member = node_offset(brother_of(dblist, oldnode_ptr), pptr);
}
else
pptr->member = 0;
}
else
{
for (nptr = member_of(pptr);
nptr && (brother_of(dblist, nptr) != oldnode_ptr);
nptr = brother_of(dblist, nptr))
;
if (nptr)
{
if (oldnode_ptr->brother)
{
nptr->brother = node_offset(brother_of(dblist, oldnode_ptr), nptr);
}
else
nptr->brother = 0;
}
else
{
status = TreeINVTREE;
goto cleanup;
}
}
}
/***********************************************
Next we must connect this node up to its new
destination.
***********************************************/
memcpy(oldnode_ptr->name, newnode_name, strlen(newnode_name));
if (strlen(newnode_name) < sizeof(oldnode_ptr->name))
memset(oldnode_ptr->name + strlen(newnode_name), 32,
sizeof(oldnode_ptr->name) - strlen(newnode_name));
if (is_child)
status = TreeInsertChild(newnode, oldnode_ptr,
dblist->tree_info->header->sort_children);
else
status = TreeInsertMember(newnode, oldnode_ptr,
dblist->tree_info->header->sort_members);
if (STATUS_OK)
status = FixParentState(dblist, newnode, oldnode_ptr);
if (STATUS_OK)
dblist->modified = 1;
cleanup:
free(upcase_name);
free(newnode_name);
return status;
}
static int FixParentState(PINO_DATABASE *dblist, NODE *parent_ptr,
NODE *child_ptr)
{
int status = 1;
NID parent_nid;
NID child_nid;
int parent_state;
int child_parent_state;
int retlen;
unsigned int child_flags;
NCI_ITM child_itm_list[] = {
{sizeof(unsigned int), NciGET_FLAGS, &child_flags, &retlen},
{0, NciEND_OF_LIST, 0, 0}};
node_to_nid(dblist, parent_ptr, (&parent_nid));
node_to_nid(dblist, child_ptr, (&child_nid));
/***************************************************
Note that parent_state and child_parent_state
are normal positive boolean logic but the bits
in the flag longword and the parent state argument
to SET_PARENT_STATE are negative boolean logic.
****************************************************/
parent_state = _TreeIsOn(dblist, nid_to_int(&parent_nid)) & 1;
status = _TreeGetNci(dblist, nid_to_int(&child_nid), child_itm_list);
if (STATUS_OK)
{
child_parent_state = ((child_flags & NciM_PARENT_STATE) == 0);
if (child_parent_state != parent_state)
status = tree_set_parent_state(dblist, child_ptr, !parent_state);
}
return status;
}