2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
25 #include <dali-toolkit/devel-api/builder/tree-node.h>
39 void Indent(std::ostream& o, int level, int indentWidth)
41 for (int i = 0; i < level*indentWidth; ++i)
47 std::string EscapeQuotes( const char* aString)
49 std::string escapedString;
50 int length = strlen(aString);
51 escapedString.reserve(length);
53 const char* end = aString+length;
54 for( const char* iter = aString; iter != end ; ++iter)
58 escapedString.push_back(*iter);
62 escapedString.append("\\\"");
68 } // anonymous namespace
70 TreeNodeManipulator::TreeNodeManipulator(TreeNode* node)
75 TreeNode* TreeNodeManipulator::NewTreeNode()
77 return new TreeNode();
80 void TreeNodeManipulator::ShallowCopy(const TreeNode* from, TreeNode* to)
82 DALI_ASSERT_DEBUG(from);
83 DALI_ASSERT_DEBUG(to);
87 to->mName = from->mName;
88 to->mType = from->mType;
89 to->mSubstituion = from->mSubstituion;
92 case TreeNode::INTEGER:
94 to->mIntValue = from->mIntValue;
99 to->mFloatValue = from->mFloatValue;
102 case TreeNode::STRING:
104 to->mStringValue = from->mStringValue;
107 case TreeNode::BOOLEAN:
109 to->mIntValue = from->mIntValue;
112 case TreeNode::IS_NULL:
113 case TreeNode::OBJECT:
114 case TreeNode::ARRAY:
123 void TreeNodeManipulator::MoveNodeStrings(VectorCharIter& start, const VectorCharIter& sentinel)
125 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
128 mNode->mName = CopyString(mNode->mName, start, sentinel);
131 if(TreeNode::STRING == mNode->mType)
133 mNode->mStringValue = CopyString(mNode->mStringValue, start, sentinel);
137 void TreeNodeManipulator::MoveStrings(VectorCharIter& start, const VectorCharIter& sentinel)
139 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
140 TreeNodeManipulator modify(mNode);
141 modify.MoveNodeStrings(start, sentinel);
142 RecurseMoveChildStrings(start, sentinel);
145 void TreeNodeManipulator::RecurseMoveChildStrings(VectorCharIter& start, const VectorCharIter& sentinel)
147 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
149 TreeNode* child = mNode->mFirstChild;
152 TreeNodeManipulator manipChild(child);
153 manipChild.MoveNodeStrings(start, sentinel);
154 child = child->mNextSibling;
157 child = mNode->mFirstChild;
160 TreeNodeManipulator manipChild(child);
161 manipChild.RecurseMoveChildStrings(start, sentinel);
162 child = child->mNextSibling;
166 void TreeNodeManipulator::RemoveChildren()
168 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
170 CollectNodes collector;
172 DepthFirst( mNode, collector );
174 for(CollectNodes::iterator iter = collector.nodes.begin(); iter != collector.nodes.end(); ++iter)
182 mNode->mFirstChild = NULL;
183 mNode->mLastChild = NULL;
186 TreeNode* TreeNodeManipulator::Copy(const TreeNode& tree, int& numberNodes, int& numberChars)
188 TreeNode* root = NewTreeNode();
190 ShallowCopy(&tree, root);
194 numberChars += std::strlen(tree.mName) + 1;
197 if(TreeNode::STRING == tree.mType)
199 numberChars += std::strlen(tree.mStringValue) + 1;
204 CopyChildren(&tree, root, numberNodes, numberChars);
209 void TreeNodeManipulator::CopyChildren(const TreeNode* from, TreeNode* to, int& numberNodes, int& numberChars)
211 DALI_ASSERT_DEBUG(from && "Operation on NULL JSON node");
212 DALI_ASSERT_DEBUG(to);
214 for( TreeNode::ConstIterator iter = from->CBegin(); iter != from->CEnd(); ++iter)
216 const TreeNode* child = &((*iter).second);
219 numberChars += std::strlen(child->mName) + 1;
222 if(TreeNode::STRING == child->mType)
224 numberChars += std::strlen(child->mStringValue) + 1;
227 TreeNode* newNode = NewTreeNode();
229 ShallowCopy(child, newNode);
231 TreeNodeManipulator modify(to);
233 modify.AddChild(newNode);
237 CopyChildren(child, newNode, numberNodes, numberChars);
241 TreeNode *TreeNodeManipulator::AddChild(TreeNode *rhs)
243 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
245 rhs->mParent = mNode;
246 if (mNode->mLastChild)
248 mNode->mLastChild = mNode->mLastChild->mNextSibling = rhs;
252 mNode->mFirstChild = mNode->mLastChild = rhs;
257 TreeNode::NodeType TreeNodeManipulator::GetType() const
259 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
261 return mNode->GetType();
264 size_t TreeNodeManipulator::Size() const
266 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
268 return mNode->Size();
271 void TreeNodeManipulator::SetType( TreeNode::NodeType type)
273 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
275 if( mNode->mType != type )
279 if( NULL != mNode->mFirstChild )
281 // value types have no children
282 bool removeChildren = ! (TreeNode::OBJECT == type || TreeNode::ARRAY == type);
284 // ie if swapping array for object
285 removeChildren = (removeChildren == true) ? true : type != mNode->mType;
287 // so remove any children
288 if( removeChildren && NULL != mNode->mFirstChild)
294 else if( TreeNode::ARRAY == mNode->mType )
296 if( mNode->mFirstChild != NULL )
298 TreeNode::NodeType type = mNode->mFirstChild->GetType();
300 if( TreeNode::FLOAT == type || TreeNode::INTEGER == type )
302 // Arrays of numbers should be replaced, not appended to.
309 void TreeNodeManipulator::SetName( const char* name )
311 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
315 void TreeNodeManipulator::SetSubstitution( bool b )
317 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
318 mNode->mSubstituion = b;
321 TreeNode* TreeNodeManipulator::GetParent() const
323 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
324 return NULL == mNode ? NULL : mNode->mParent;
327 const TreeNode* TreeNodeManipulator::GetChild(const std::string& name) const
329 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
330 return NULL == mNode ? NULL : mNode->GetChild(name);
333 void TreeNodeManipulator::SetString( const char* string )
335 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
336 SetType(TreeNode::STRING);
337 mNode->mStringValue = string;
340 void TreeNodeManipulator::SetInteger( int i )
342 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
343 SetType(TreeNode::INTEGER);
344 mNode->mIntValue = i;
347 void TreeNodeManipulator::SetFloat( float f )
349 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
350 SetType(TreeNode::FLOAT);
351 mNode->mFloatValue = f;
354 void TreeNodeManipulator::SetBoolean( bool b )
356 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
357 SetType(TreeNode::BOOLEAN);
358 mNode->mIntValue = b == true ? 1 : 0;
361 void TreeNodeManipulator::Write(std::ostream& output, int indent) const
363 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
364 DoWrite(mNode, output, 0, indent, false);
367 void TreeNodeManipulator::DoWrite(const TreeNode *value, std::ostream& output, int level, int indentWidth, bool groupChildren) const
369 DALI_ASSERT_DEBUG(value && "Operation on NULL JSON node");
373 Indent(output, level, indentWidth);
376 if (value->GetName())
378 output << "\"" << value->GetName() << "\":";
381 switch(value->GetType())
383 case TreeNode::IS_NULL:
386 if(NULL != value->mNextSibling)
396 case TreeNode::OBJECT:
397 case TreeNode::ARRAY:
399 bool groupMyChildren = false;
401 if( TreeNode::ARRAY == value->GetType() && value->mFirstChild &&
402 ( TreeNode::INTEGER == value->mFirstChild->GetType() ||
403 TreeNode::FLOAT == value->mFirstChild->GetType() ) )
405 groupMyChildren = true;
408 if( value->GetType() == TreeNode::OBJECT)
411 Indent(output, level, indentWidth);
416 if( !groupMyChildren )
419 Indent(output, level, indentWidth);
424 if( groupMyChildren )
433 for (TreeNode::ConstIterator it = value->CBegin(); it != value->CEnd(); ++it)
435 DoWrite( &((*it).second), output, level+1, indentWidth, groupMyChildren );
438 if( !groupMyChildren )
440 Indent(output, level, indentWidth);
443 if( value->GetType() == TreeNode::OBJECT )
452 if( NULL != value->mNextSibling )
462 groupChildren = false;
465 case TreeNode::STRING:
467 std::string escapedString = EscapeQuotes(value->GetString());
468 output << "\"" << escapedString << "\"";
469 if(NULL != value->mNextSibling)
484 case TreeNode::INTEGER:
486 output << value->GetInteger();
487 if(NULL != value->mNextSibling)
502 case TreeNode::FLOAT:
504 output.setf( std::ios::floatfield );
505 output << value->GetFloat();
506 output.unsetf( std::ios::floatfield );
507 if(NULL != value->mNextSibling)
522 case TreeNode::BOOLEAN:
524 if( value->GetInteger() )
533 if(NULL != value->mNextSibling)
553 const TreeNode* FindIt(const std::string& childName, const TreeNode* node)
555 DALI_ASSERT_DEBUG(node);
557 const TreeNode* found = NULL;
561 if( NULL != (found = node->GetChild(childName)) )
567 for(TreeNode::ConstIterator iter = node->CBegin(); iter != node->CEnd(); ++iter)
569 if( NULL != (found = FindIt(childName, &((*iter).second)) ) )
579 char *CopyString( const char *fromString, VectorCharIter& iter, const VectorCharIter& sentinel)
581 DALI_ASSERT_DEBUG(fromString);
582 DALI_ASSERT_DEBUG(iter != sentinel);
584 char *start= &(*iter);
585 const char *ptr = fromString;
591 DALI_ASSERT_DEBUG(iter != sentinel);
601 } // namespace internal
603 } // namespace Toolkit