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)
296 void TreeNodeManipulator::SetName( const char* name )
298 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
302 void TreeNodeManipulator::SetSubstitution( bool b )
304 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
305 mNode->mSubstituion = b;
308 TreeNode* TreeNodeManipulator::GetParent() const
310 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
311 return NULL == mNode ? NULL : mNode->mParent;
314 const TreeNode* TreeNodeManipulator::GetChild(const std::string& name) const
316 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
317 return NULL == mNode ? NULL : mNode->GetChild(name);
320 void TreeNodeManipulator::SetString( const char* string )
322 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
323 SetType(TreeNode::STRING);
324 mNode->mStringValue = string;
327 void TreeNodeManipulator::SetInteger( int i )
329 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
330 SetType(TreeNode::INTEGER);
331 mNode->mIntValue = i;
334 void TreeNodeManipulator::SetFloat( float f )
336 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
337 SetType(TreeNode::FLOAT);
338 mNode->mFloatValue = f;
341 void TreeNodeManipulator::SetBoolean( bool b )
343 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
344 SetType(TreeNode::BOOLEAN);
345 mNode->mIntValue = b == true ? 1 : 0;
348 void TreeNodeManipulator::Write(std::ostream& output, int indent) const
350 DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
351 DoWrite(mNode, output, 0, indent, false);
354 void TreeNodeManipulator::DoWrite(const TreeNode *value, std::ostream& output, int level, int indentWidth, bool groupChildren) const
356 DALI_ASSERT_DEBUG(value && "Operation on NULL JSON node");
360 Indent(output, level, indentWidth);
363 if (value->GetName())
365 output << "\"" << value->GetName() << "\":";
368 switch(value->GetType())
370 case TreeNode::IS_NULL:
373 if(NULL != value->mNextSibling)
383 case TreeNode::OBJECT:
384 case TreeNode::ARRAY:
386 bool groupMyChildren = false;
388 if( TreeNode::ARRAY == value->GetType() &&
389 ( TreeNode::INTEGER == value->mFirstChild->GetType() ||
390 TreeNode::FLOAT == value->mFirstChild->GetType() ) )
392 groupMyChildren = true;
395 if( value->GetType() == TreeNode::OBJECT)
398 Indent(output, level, indentWidth);
403 if( !groupMyChildren )
406 Indent(output, level, indentWidth);
411 if( groupMyChildren )
420 for (TreeNode::ConstIterator it = value->CBegin(); it != value->CEnd(); ++it)
422 DoWrite( &((*it).second), output, level+1, indentWidth, groupMyChildren );
425 if( !groupMyChildren )
427 Indent(output, level, indentWidth);
430 if( value->GetType() == TreeNode::OBJECT )
439 if( NULL != value->mNextSibling )
449 groupChildren = false;
452 case TreeNode::STRING:
454 std::string escapedString = EscapeQuotes(value->GetString());
455 output << "\"" << escapedString << "\"";
456 if(NULL != value->mNextSibling)
471 case TreeNode::INTEGER:
473 output << value->GetInteger();
474 if(NULL != value->mNextSibling)
489 case TreeNode::FLOAT:
491 output.setf( std::ios::floatfield );
492 output << value->GetFloat();
493 output.unsetf( std::ios::floatfield );
494 if(NULL != value->mNextSibling)
509 case TreeNode::BOOLEAN:
511 if( value->GetInteger() )
520 if(NULL != value->mNextSibling)
540 const TreeNode* FindIt(const std::string& childName, const TreeNode* node)
542 DALI_ASSERT_DEBUG(node);
544 const TreeNode* found = NULL;
548 if( NULL != (found = node->GetChild(childName)) )
554 for(TreeNode::ConstIterator iter = node->CBegin(); iter != node->CEnd(); ++iter)
556 if( NULL != (found = FindIt(childName, &((*iter).second)) ) )
566 char *CopyString( const char *fromString, VectorCharIter& iter, const VectorCharIter& sentinel)
568 DALI_ASSERT_DEBUG(fromString);
569 DALI_ASSERT_DEBUG(iter != sentinel);
571 char *start= &(*iter);
572 const char *ptr = fromString;
578 DALI_ASSERT_DEBUG(iter != sentinel);
588 } // namespace internal
590 } // namespace Toolkit