Add VariableNode which will replace our use of raw NSXMLElement.
[macgdbp.git] / Source / VariableNode.m
1 /*
2 * MacGDBp
3 * Copyright (c) 2010, Blue Static <http://www.bluestatic.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17 #import "VariableNode.h"
18
19 #import "AppDelegate.h"
20 #include "base64.h"
21
22 // Private Properties //////////////////////////////////////////////////////////
23
24 @interface VariableNode ()
25
26 @property (copy) NSString* name;
27 @property (copy) NSString* fullName;
28 @property (copy) NSString* className;
29 @property (copy) NSString* type;
30 @property (copy) NSString* value;
31 @property (retain) NSMutableArray* children;
32
33 // Takes an XML node and computes the value.
34 - (NSString*)decodeValueForNode:(NSXMLElement*)node;
35
36 @end
37
38 ////////////////////////////////////////////////////////////////////////////////
39
40 @implementation VariableNode
41
42 @synthesize name = name_;
43 @synthesize fullName = fullName_;
44 @synthesize className = className_;
45 @synthesize type = type_;
46 @synthesize value = value_;
47 @synthesize children = children_;
48 @synthesize childCount = childCount_;
49
50 - (id)initWithXMLNode:(NSXMLElement*)node
51 {
52 if (self = [super init]) {
53 self.name = [[node attributeForName:@"name"] stringValue];
54 self.fullName = [[node attributeForName:@"fullName"] stringValue];
55 self.className = [[node attributeForName:@"className"] stringValue];
56 self.type = [[node attributeForName:@"type"] stringValue];
57 self.value = [self decodeValueForNode:node];
58 self.children = [NSMutableArray array];
59 if ([node children]) {
60 [self setChildrenFromXMLChildren:[node children]];
61 }
62 childCount_ = [[[node attributeForName:@"numchildren"] stringValue] integerValue];
63 }
64 return self;
65 }
66
67 - (void)dealloc
68 {
69 self.name = nil;
70 self.fullName = nil;
71 self.className = nil;
72 self.type = nil;
73 self.value = nil;
74 self.children = nil;
75 [super dealloc];
76 }
77
78 - (void)setChildrenFromXMLChildren:(NSArray*)children
79 {
80 for (NSXMLElement* child in children) {
81 VariableNode* node = [[VariableNode alloc] initWithXMLNode:child];
82 [children_ addObject:[node autorelease]];
83 }
84 }
85
86 - (NSArray*)dynamicChildren
87 {
88 NSArray* children = self.children;
89 if (![self isLeaf] && [children count] < 1) {
90 // If this node has children but they haven't been loaded from the backend,
91 // request them asynchronously.
92 [[AppDelegate instance].debugger fetchProperty:self.fullName forNode:self];
93 }
94 return children;
95 }
96
97 - (BOOL)isLeaf
98 {
99 return (self.childCount == 0);
100 }
101
102 - (NSString*)displayType
103 {
104 if (self.className != nil) {
105 return [NSString stringWithFormat:@"%@ (%@)", self.className, self.type];
106 }
107 return self.type;
108 }
109
110 // Private /////////////////////////////////////////////////////////////////////
111
112 - (NSString*)decodeValueForNode:(NSXMLElement*)node
113 {
114 // Non-leaf nodes do not have a value:
115 // https://www.bluestatic.org/bugs/showreport.php?bugid=168
116 if (![self isLeaf]) {
117 return @"...";
118 }
119
120 // The value of the node is base64 encoded.
121 if ([[[node attributeForName:@"encoding"] stringValue] isEqualToString:@"base64"]) {
122 const char* str = [[node stringValue] UTF8String];
123 int strlen = [[node stringValue] length];
124
125 char* data;
126 size_t datalen;
127
128 if (!base64_decode_alloc(str, strlen, &data, &datalen))
129 NSLog(@"error in converting %@ from base64", self);
130
131 NSString* ret = nil;
132 if (data) {
133 ret = [NSString stringWithUTF8String:data];
134 free(data);
135 }
136
137 return ret;
138 }
139
140 // The value is just a normal string.
141 return [node stringValue];
142 }
143
144 @end