staf4ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +58 -0
- data/ext/extconf.rb +19 -0
- data/ext/staf4ruby_ext.c +270 -0
- data/lib/staf4ruby.rb +564 -0
- data/test/test.rb +662 -0
- data/test/test_helper.rb +12 -0
- metadata +52 -0
data/lib/staf4ruby.rb
ADDED
@@ -0,0 +1,564 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
##############################################################################
|
3
|
+
# Copyright (c) 2013 Spectra Logic corp
|
4
|
+
# All rights reserved. This program and the accompanying materials
|
5
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
6
|
+
# which accompanies this distribution, and is available at
|
7
|
+
# http://www.eclipse.org/legal/epl-v10.html
|
8
|
+
##############################################################################
|
9
|
+
|
10
|
+
|
11
|
+
$:.unshift File.dirname(File.expand_path(__FILE__))
|
12
|
+
require 'staf4ruby_ext'
|
13
|
+
|
14
|
+
# STAF bindings for Ruby
|
15
|
+
|
16
|
+
|
17
|
+
module Staf
|
18
|
+
class STAFException < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
class STAFResult
|
22
|
+
Ok = 0
|
23
|
+
InvalidAPI = 1
|
24
|
+
UnknownService = 2
|
25
|
+
InvalidHandle = 3
|
26
|
+
HandleAlreadyExists = 4
|
27
|
+
HandleDoesNotExist = 5
|
28
|
+
UnknownError = 6
|
29
|
+
InvalidRequestString = 7
|
30
|
+
InvalidServiceResult = 8
|
31
|
+
REXXError = 9
|
32
|
+
BaseOSError = 10
|
33
|
+
ProcessAlreadyComplete = 11
|
34
|
+
ProcessNotComplete = 12
|
35
|
+
VariableDoesNotExist = 13
|
36
|
+
UnResolvableString = 14
|
37
|
+
InvalidResolveString = 15
|
38
|
+
NoPathToMachine = 16
|
39
|
+
FileOpenError = 17
|
40
|
+
FileReadError = 18
|
41
|
+
FileWriteError = 19
|
42
|
+
FileDeleteError = 20
|
43
|
+
STAFNotRunning = 21
|
44
|
+
CommunicationError = 22
|
45
|
+
TrusteeDoesNotExist = 23
|
46
|
+
InvalidTrustLevel = 24
|
47
|
+
AccessDenied = 25
|
48
|
+
STAFRegistrationError = 26
|
49
|
+
ServiceConfigurationError = 27
|
50
|
+
QueueFull = 28
|
51
|
+
NoQueueElement = 29
|
52
|
+
NotifieeDoesNotExist = 30
|
53
|
+
InvalidAPILevel = 31
|
54
|
+
ServiceNotUnregisterable = 32
|
55
|
+
ServiceNotAvailable = 33
|
56
|
+
SemaphoreDoesNotExist = 34
|
57
|
+
NotSemaphoreOwner = 35
|
58
|
+
SemaphoreHasPendingRequests = 36
|
59
|
+
Timeout = 37
|
60
|
+
JavaError = 38
|
61
|
+
ConverterError = 39
|
62
|
+
MoveError = 40
|
63
|
+
InvalidObject = 41
|
64
|
+
InvalidParm = 42
|
65
|
+
RequestNumberNotFound = 43
|
66
|
+
InvalidAsynchOption = 44
|
67
|
+
RequestNotComplete = 45
|
68
|
+
ProcessAuthenticationDenied = 46
|
69
|
+
InvalidValue = 47
|
70
|
+
DoesNotExist = 48
|
71
|
+
AlreadyExists = 49
|
72
|
+
DirectoryNotEmpty = 50
|
73
|
+
DirectoryCopyError = 51
|
74
|
+
DiagnosticsNotEnabled = 52
|
75
|
+
HandleAuthenticationDenied = 53
|
76
|
+
HandleAlreadyAuthenticated = 54
|
77
|
+
InvalidSTAFVersion = 55
|
78
|
+
RequestCancelled = 56
|
79
|
+
CreateThreadError = 57
|
80
|
+
MaximumSizeExceeded = 58
|
81
|
+
MaximumHandlesExceeded = 59
|
82
|
+
NotRequester = 60
|
83
|
+
|
84
|
+
attr_reader :rc, :result, :resultContext, :resultObj
|
85
|
+
|
86
|
+
def initialize(rc, result, doUnmarshallResult)
|
87
|
+
@rc = rc
|
88
|
+
@result = result
|
89
|
+
if doUnmarshallResult
|
90
|
+
@resultContext = Staf::unmarshall(@result)
|
91
|
+
@resultObj = @resultContext.rootObject
|
92
|
+
else
|
93
|
+
@resultContext = nil
|
94
|
+
@resultObj = nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class STAFHandle
|
100
|
+
# STAFHandle types
|
101
|
+
|
102
|
+
Standard = 0
|
103
|
+
Static = 1
|
104
|
+
|
105
|
+
# Modes for submit call
|
106
|
+
|
107
|
+
Synchronous = 0
|
108
|
+
FireAndForget = 1
|
109
|
+
Queue = 2
|
110
|
+
Retain = 3
|
111
|
+
QueueRetain = 4
|
112
|
+
|
113
|
+
attr_reader :doUnmarshallResult
|
114
|
+
attr_reader :handleType
|
115
|
+
|
116
|
+
def initialize(handleNameOrNumber, handleType = Standard)
|
117
|
+
@handleType = handleType
|
118
|
+
@doUnmarshallResult = true
|
119
|
+
|
120
|
+
if (handleType == Standard)
|
121
|
+
if (not handleNameOrNumber.is_a? String)
|
122
|
+
raise TypeError.new('A string is required if using standard handle type')
|
123
|
+
end
|
124
|
+
rc, @handle = Staf::register(handleNameOrNumber)
|
125
|
+
if rc != STAFResult::Ok
|
126
|
+
raise STAFException.new(rc)
|
127
|
+
end
|
128
|
+
else
|
129
|
+
if (not handleNameOrNumber.is_a? Integer)
|
130
|
+
raise TypeError.new('An integer is required if using static handle type')
|
131
|
+
end
|
132
|
+
@handle = handleNameOrNumber
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Set the doUnmarshallResult attribute. For compatibility with the Python
|
137
|
+
# bindings, accept other-than-boolean values and check their truthiness.
|
138
|
+
def setDoUnmarshallResult(value)
|
139
|
+
if value.is_a? Fixnum
|
140
|
+
@doUnmarshallResult = (value != 0)
|
141
|
+
elsif value.is_a? String
|
142
|
+
@doUnmarshallResult = (value != "")
|
143
|
+
else
|
144
|
+
@doUnmarshallResult = value
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def submit(location, service, request, mode = Synchronous)
|
149
|
+
rc, result = Staf::submit(@handle, mode, location, service, request)
|
150
|
+
STAFResult.new(rc, result, @doUnmarshallResult)
|
151
|
+
end
|
152
|
+
|
153
|
+
def unregister()
|
154
|
+
if (@handleType == Standard)
|
155
|
+
rc = Staf::unregister(@handle)
|
156
|
+
if (rc != STAFResult::Ok)
|
157
|
+
raise STAFException.new(rc)
|
158
|
+
end
|
159
|
+
@handle = 0
|
160
|
+
end
|
161
|
+
0
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
# Marshalling constants
|
167
|
+
UNMARSHALLING_DEFAULTS = 0
|
168
|
+
IGNORE_INDIRECT_OBJECTS = 1
|
169
|
+
MARSHALLED_DATA_MARKER = '@SDT/'
|
170
|
+
NONE_MARKER = '@SDT/$0:0:'
|
171
|
+
SCALAR_MARKER = '@SDT/$'
|
172
|
+
SCALAR_MARKER_REGEX = '@SDT/\$' # Version of LIST_MARKER for regexes
|
173
|
+
SCALAR_STRING_MARKER = '@SDT/$S'
|
174
|
+
LIST_MARKER = '@SDT/['
|
175
|
+
LIST_MARKER_REGEX = '@SDT/\[' # Version of LIST_MARKER for regexes
|
176
|
+
MAP_MARKER = '@SDT/{'
|
177
|
+
MC_INSTANCE_MARKER = '@SDT/%'
|
178
|
+
CONTEXT_MARKER = '@SDT/*'
|
179
|
+
CONTEXT_MARKER_REGEX = '@SDT/\*'
|
180
|
+
|
181
|
+
|
182
|
+
class STAFMapClassDefinition
|
183
|
+
attr_reader :mapClassDef
|
184
|
+
|
185
|
+
def initialize(name = nil, mapClassDef = nil)
|
186
|
+
# @mapClassDef[keys] is an array of key=>value pairs. It would seem to
|
187
|
+
# be more useful to just make it a hash of key=>value pairs, but this is
|
188
|
+
# how the python bindings do it. It's not completely equivalent, because
|
189
|
+
# this way preserves order and allows for duplicate keys.
|
190
|
+
if mapClassDef.nil? and name.nil?
|
191
|
+
@mapClassDef = {"name" => "", "keys" => []}
|
192
|
+
elsif not name.nil?
|
193
|
+
@mapClassDef = {"name" => name, 'keys' => []}
|
194
|
+
else
|
195
|
+
@mapClassDef = mapClassDef
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def createInstance
|
200
|
+
{"staf-map-class-name" => @mapClassDef["name"]}
|
201
|
+
end
|
202
|
+
|
203
|
+
def addKey(keyName, displayName = nil)
|
204
|
+
theKey = {"key" => keyName}
|
205
|
+
if displayName
|
206
|
+
theKey['display-name'] = displayName
|
207
|
+
end
|
208
|
+
@mapClassDef["keys"] << theKey
|
209
|
+
end
|
210
|
+
|
211
|
+
def setKeyProperty(keyName, property, value)
|
212
|
+
@mapClassDef['keys'].each do |key|
|
213
|
+
if key['key'] == keyName
|
214
|
+
key[property] = value
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def keys
|
220
|
+
@mapClassDef["keys"]
|
221
|
+
end
|
222
|
+
|
223
|
+
def name
|
224
|
+
@mapClassDef["name"]
|
225
|
+
end
|
226
|
+
|
227
|
+
# def to_s
|
228
|
+
# formatObject @mapClassDef
|
229
|
+
# end
|
230
|
+
#
|
231
|
+
# def inspect
|
232
|
+
# to_s
|
233
|
+
# end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
class STAFMarshallingContext
|
238
|
+
attr_accessor :rootObject
|
239
|
+
attr_reader :mapClassMap
|
240
|
+
|
241
|
+
def initialize(obj=nil, mapClassMap=nil)
|
242
|
+
if mapClassMap.nil?
|
243
|
+
@mapClassMap = {}
|
244
|
+
else
|
245
|
+
@mapClassMap = mapClassMap
|
246
|
+
end
|
247
|
+
@rootObject = obj
|
248
|
+
end
|
249
|
+
|
250
|
+
def isMarshalledData(someData)
|
251
|
+
Staf::isMarshalledData(someData)
|
252
|
+
end
|
253
|
+
|
254
|
+
def getMapClassDefinition(mapClassName)
|
255
|
+
STAFMapClassDefinition.new(nil, @mapClassMap[mapClassName])
|
256
|
+
end
|
257
|
+
|
258
|
+
def getPrimaryObject
|
259
|
+
if @mapClassMap.size == 0
|
260
|
+
@rootObject
|
261
|
+
else
|
262
|
+
self
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def hasMapClassDefinition(mapClassName)
|
267
|
+
@mapClassMap.keys.include? mapClassName
|
268
|
+
end
|
269
|
+
|
270
|
+
def marshall
|
271
|
+
Staf::marshall(self, self)
|
272
|
+
end
|
273
|
+
|
274
|
+
def mapClassDefinitionIterator
|
275
|
+
@mapClassMap.keys
|
276
|
+
end
|
277
|
+
|
278
|
+
def setMapClassDefinition(mapClassDef)
|
279
|
+
@mapClassMap[mapClassDef.name()] = mapClassDef.mapClassDef
|
280
|
+
end
|
281
|
+
|
282
|
+
# def to_s
|
283
|
+
# formatObject(@rootObject, self)
|
284
|
+
# end
|
285
|
+
|
286
|
+
# def inspect
|
287
|
+
# to_s
|
288
|
+
# end
|
289
|
+
end
|
290
|
+
|
291
|
+
def self.isMarshalledData(someData)
|
292
|
+
someData =~ /\A@SDT\//
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.marshall(object, context=nil)
|
296
|
+
# General Marshalling function
|
297
|
+
|
298
|
+
return NONE_MARKER if object.nil?
|
299
|
+
if object.is_a? Array
|
300
|
+
listData = object.collect do |item|
|
301
|
+
marshall(item, context)
|
302
|
+
end.join
|
303
|
+
return "#{LIST_MARKER}#{object.size}:#{listData.size}:#{listData}"
|
304
|
+
elsif object.is_a? Hash
|
305
|
+
# If a staf-map-class-name key exists in the map, make sure that
|
306
|
+
# it's map class definition is provided in the marshalling context.
|
307
|
+
# If it's not, then treat the map as a plain map object.
|
308
|
+
isMapClass = false
|
309
|
+
mapClassName = ""
|
310
|
+
if not context.nil? and context.is_a? STAFMarshallingContext and \
|
311
|
+
object.has_key?('staf-map-class-name')
|
312
|
+
mapClassName = object['staf-map-class-name']
|
313
|
+
if context.hasMapClassDefinition(mapClassName)
|
314
|
+
isMapClass = true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
if isMapClass
|
319
|
+
mapClass = context.getMapClassDefinition(mapClassName)
|
320
|
+
mapData = ":#{mapClassName.size}:#{mapClassName}"
|
321
|
+
mapData << mapClass.keys.collect do |key|
|
322
|
+
marshall(object[key['key']], context)
|
323
|
+
end.join
|
324
|
+
return "#{MC_INSTANCE_MARKER}:#{mapData.size}:#{mapData}"
|
325
|
+
else
|
326
|
+
mapData = object.keys.collect do |key|
|
327
|
+
":#{key.to_s.size}:#{key.to_s}#{marshall(object[key], context)}"
|
328
|
+
end.join
|
329
|
+
return "#{MAP_MARKER}:#{mapData.size}:#{mapData}"
|
330
|
+
end
|
331
|
+
elsif object.is_a? STAFMarshallingContext
|
332
|
+
if object.mapClassMap.keys.size == 0
|
333
|
+
return marshall(object.rootObject, context)
|
334
|
+
else
|
335
|
+
contextMap = { 'map-class-map' => object.mapClassMap}
|
336
|
+
# Note: We can't simply put the root object as a map key like
|
337
|
+
# "root-object" and then marshall the whole map, as in
|
338
|
+
# the unmarshalling routines, we need to be able to
|
339
|
+
# unmarshall the root object in the context of the
|
340
|
+
# map-class-map.
|
341
|
+
mcData = (marshall(contextMap, context) +
|
342
|
+
marshall(object.rootObject, object))
|
343
|
+
return "#{CONTEXT_MARKER}:#{mcData.size}:#{mcData}"
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
return "#{SCALAR_STRING_MARKER}:#{object.to_s.size}:#{object.to_s}"
|
348
|
+
end
|
349
|
+
|
350
|
+
|
351
|
+
# General unmarshalling function
|
352
|
+
# Unmarshalls the input data string and returns a marshalling context.
|
353
|
+
# Unlike the Python version, this function does not catch exceptions
|
354
|
+
|
355
|
+
def self.unmarshall(data, context = nil, flags = UNMARSHALLING_DEFAULTS)
|
356
|
+
# TODO: implement me
|
357
|
+
if context.nil?
|
358
|
+
context = STAFMarshallingContext.new
|
359
|
+
end
|
360
|
+
|
361
|
+
if data =~ /\A#{NONE_MARKER}/
|
362
|
+
return STAFMarshallingContext.new
|
363
|
+
elsif data =~ /\A#{SCALAR_MARKER_REGEX}/
|
364
|
+
# @SDT/$S:<string length>:<String>
|
365
|
+
colonIndex = data.index(":", SCALAR_MARKER.size)
|
366
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
367
|
+
dataIndex = colonIndex + 1
|
368
|
+
colonIndex = data.index(':', dataIndex)
|
369
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
370
|
+
stringLength = data[dataIndex..colonIndex - 1].to_i
|
371
|
+
dataIndex = colonIndex + 1
|
372
|
+
if stringLength != (data.size - dataIndex)
|
373
|
+
return STAFMarshallingContext.new(data)
|
374
|
+
end
|
375
|
+
theString = data[dataIndex..-1]
|
376
|
+
if (theString =~ /\A#{MARSHALLED_DATA_MARKER}/) and \
|
377
|
+
((flags & IGNORE_INDIRECT_OBJECTS) != IGNORE_INDIRECT_OBJECTS)
|
378
|
+
return unmarshall(theString, context, flags)
|
379
|
+
else
|
380
|
+
return STAFMarshallingContext.new(theString)
|
381
|
+
end
|
382
|
+
elsif data =~ /\A#{LIST_MARKER_REGEX}/
|
383
|
+
# @SDT/[<number-of-items>:<array-length>:<SDT-Any-1>...<SDT-Any-n>
|
384
|
+
# Get number-of-items in the list
|
385
|
+
colonIndex = data.index(":", LIST_MARKER.size)
|
386
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
387
|
+
numItems = data[LIST_MARKER.size..colonIndex - 1].to_i
|
388
|
+
# Get array length
|
389
|
+
dataIndex = colonIndex + 1
|
390
|
+
colonIndex = data.index(":", dataIndex)
|
391
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
392
|
+
arrayLength = data[dataIndex..colonIndex-1].to_i
|
393
|
+
dataIndex = colonIndex + 1
|
394
|
+
if arrayLength != data.size - dataIndex
|
395
|
+
return STAFMarshallingContext.new(data)
|
396
|
+
end
|
397
|
+
|
398
|
+
# Create an array for the data
|
399
|
+
myArray = []
|
400
|
+
for i in (1..numItems).to_a
|
401
|
+
# Get the next item in the list and unmarshall it and add it
|
402
|
+
# to the list
|
403
|
+
colonIndex1 = data.index(":", dataIndex)
|
404
|
+
return STAFMarshallingContext.new(data) unless colonIndex1
|
405
|
+
colonIndex2 = data.index(":", colonIndex1 + 1)
|
406
|
+
return STAFMarshallingContext.new(data) unless colonIndex2
|
407
|
+
itemLength = data[colonIndex1 + 1..colonIndex2 - 1].to_i
|
408
|
+
myArray << (unmarshall(data[dataIndex..colonIndex2 + itemLength],
|
409
|
+
context, flags).getPrimaryObject)
|
410
|
+
dataIndex = colonIndex2 + itemLength + 1
|
411
|
+
end
|
412
|
+
return STAFMarshallingContext.new(myArray)
|
413
|
+
elsif data =~ /\A#{MAP_MARKER}/
|
414
|
+
# @SDT/{:<map-length>::<key-1-length>:<key-1><SDT-Any>
|
415
|
+
# ...
|
416
|
+
# :<key-n-length>:<key-1><SDT-Any>
|
417
|
+
|
418
|
+
# Get map-length
|
419
|
+
colonIndex = data.index(":", MAP_MARKER.size)
|
420
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
421
|
+
dataIndex = colonIndex + 1
|
422
|
+
colonIndex = data.index(":", dataIndex)
|
423
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
424
|
+
mapLength = data[dataIndex..colonIndex].to_i
|
425
|
+
dataIndex = colonIndex + 1
|
426
|
+
if mapLength != data.size - dataIndex
|
427
|
+
return STAFMarshallingContext.new(data)
|
428
|
+
end
|
429
|
+
|
430
|
+
# Create the hash of data
|
431
|
+
myhash = {}
|
432
|
+
while dataIndex < data.size
|
433
|
+
# Get the key first
|
434
|
+
keyColonIndex1 = data.index(":", dataIndex)
|
435
|
+
return STAFMarshallingContext.new(data) unless keyColonIndex1
|
436
|
+
keyColonIndex2 = data.index(":", keyColonIndex1 + 1)
|
437
|
+
return STAFMarshallingContext.new(data) unless keyColonIndex2
|
438
|
+
keyLength = data[keyColonIndex1 + 1..keyColonIndex2 - 1].to_i
|
439
|
+
key = data[keyColonIndex2 + 1..keyColonIndex2 + keyLength]
|
440
|
+
dataIndex = keyColonIndex2 + 1 + keyLength
|
441
|
+
|
442
|
+
# Now, get the object
|
443
|
+
colonIndex1 = data.index(":", dataIndex)
|
444
|
+
return STAFMarshallingContext.new(data) unless colonIndex1
|
445
|
+
colonIndex2 = data.index(":", colonIndex1 + 1)
|
446
|
+
return STAFMarshallingcontext.new(data) unless colonIndex2
|
447
|
+
itemLength = data[colonIndex1 + 1..colonIndex2-1].to_i
|
448
|
+
myhash[key] = unmarshall(data[dataIndex..colonIndex2 + itemLength],
|
449
|
+
context, flags).getPrimaryObject
|
450
|
+
dataIndex = colonIndex2 + itemLength + 1
|
451
|
+
end
|
452
|
+
return STAFMarshallingContext.new(myhash)
|
453
|
+
elsif data =~ /\A#{MC_INSTANCE_MARKER}/
|
454
|
+
# @SDT/%:<map-class-instance-length>::<map-class-name-length>:
|
455
|
+
# <map-class-name><SDT-Any-value-1>...<SDT-Any-value-n>
|
456
|
+
|
457
|
+
# Get the map-class-instance-length
|
458
|
+
colonIndex = data.index(":", MC_INSTANCE_MARKER.size)
|
459
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
460
|
+
dataIndex = colonIndex + 1
|
461
|
+
colonIndex = data.index(":", dataIndex)
|
462
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
463
|
+
mapClassInstanceLength = data[dataIndex .. colonIndex - 1].to_i
|
464
|
+
dataIndex = colonIndex + 1
|
465
|
+
if mapClassInstanceLength != data.size - dataIndex
|
466
|
+
return STAFMarshallingContext.new(data)
|
467
|
+
end
|
468
|
+
|
469
|
+
# get map-class-name-length
|
470
|
+
colonIndex = data.index(":", dataIndex)
|
471
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
472
|
+
dataIndex = colonIndex + 1
|
473
|
+
colonIndex = data.index(":", dataIndex)
|
474
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
475
|
+
mapClassNameLength = data[dataIndex .. colonIndex - 1].to_i
|
476
|
+
|
477
|
+
# Get map-class-name
|
478
|
+
dataIndex = colonIndex + 1
|
479
|
+
mapClassName = data[dataIndex .. dataIndex + mapClassNameLength - 1]
|
480
|
+
dataIndex = dataIndex + mapClassNameLength
|
481
|
+
|
482
|
+
# Create a hash and add the staf-map-class-name key and value to the hash
|
483
|
+
myHash = {'staf-map-class-name' => mapClassName}
|
484
|
+
|
485
|
+
# Unmarshall all of the actual keys and add to the map
|
486
|
+
mapClass = context.getMapClassDefinition(mapClassName)
|
487
|
+
keys = mapClass.keys
|
488
|
+
keyIndex = 0
|
489
|
+
|
490
|
+
while dataIndex < data.size
|
491
|
+
colonIndex = data.index(":", dataIndex)
|
492
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
493
|
+
colonIndex2 = data.index(":", colonIndex + 1)
|
494
|
+
return STAFMarshallingContext.new(data) unless colonIndex2
|
495
|
+
itemLength = data[colonIndex + 1 .. colonIndex2].to_i
|
496
|
+
myHash[keys[keyIndex]['key']] = unmarshall(
|
497
|
+
data[dataIndex .. colonIndex2 + itemLength],
|
498
|
+
context, flags).getPrimaryObject
|
499
|
+
dataIndex = colonIndex2 + itemLength + 1
|
500
|
+
keyIndex += 1
|
501
|
+
end
|
502
|
+
|
503
|
+
return STAFMarshallingContext.new(myHash)
|
504
|
+
|
505
|
+
elsif data =~ /\A#{CONTEXT_MARKER_REGEX}/
|
506
|
+
# @SDT/*:<context-length>:
|
507
|
+
# @SDT/{:<mapClassLength>:<mapClassData><rootObject>
|
508
|
+
|
509
|
+
# Get context-length
|
510
|
+
colonIndex = data.index(":", CONTEXT_MARKER.size)
|
511
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
512
|
+
contextIndex = data.index(":", colonIndex + 1)
|
513
|
+
return STAFMarshallingContext.new(data) unless contextIndex
|
514
|
+
contextLength = data[colonIndex + 1 .. contextIndex - 1].to_i
|
515
|
+
contextIndex += 1
|
516
|
+
if contextLength != data.size - contextIndex
|
517
|
+
return STAFMarshallingContext.new(data)
|
518
|
+
end
|
519
|
+
|
520
|
+
# Get mapClassLength
|
521
|
+
colonIndex = data.index(":", contextIndex)
|
522
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
523
|
+
mapIndex = contextIndex
|
524
|
+
mapDataIndex = data.index(":", colonIndex + 1)
|
525
|
+
return STAFMarshallingContext.new(data) unless mapDataIndex
|
526
|
+
mapLength = data[colonIndex + 1 .. mapDataIndex - 1].to_i
|
527
|
+
mapDataIndex += 1
|
528
|
+
|
529
|
+
if mapLength > data.size - mapDataIndex
|
530
|
+
return STAFMarshallingContext.new(data)
|
531
|
+
end
|
532
|
+
|
533
|
+
# Create a new marshalling context with the map classes and root object
|
534
|
+
contextMap = unmarshall(data[mapIndex..mapDataIndex + mapLength - 1],
|
535
|
+
context, flags).getPrimaryObject()
|
536
|
+
mapClassMap = contextMap['map-class-map']
|
537
|
+
newContext = STAFMarshallingContext.new(nil, mapClassMap)
|
538
|
+
colonIndex = data.index(":", mapDataIndex + mapLength)
|
539
|
+
return STAFMarshallingContext.new(data) unless colonIndex
|
540
|
+
rootObjIndex = mapDataIndex + mapLength
|
541
|
+
rootObjDataIndex = data.index(":", colonIndex + 1)
|
542
|
+
return STAFMarshallingContext.new(data) unless rootObjDataIndex
|
543
|
+
|
544
|
+
rootObjLength = data[colonIndex + 1 .. rootObjDataIndex - 1].to_i
|
545
|
+
rootObjDataIndex = rootObjDataIndex + 1
|
546
|
+
if rootObjLength > data.size - rootObjDataIndex
|
547
|
+
return STAFMarshallingContext.new(data)
|
548
|
+
end
|
549
|
+
|
550
|
+
newContext.rootObject = \
|
551
|
+
unmarshall(data[rootObjIndex .. rootObjDataIndex + rootObjLength - 1],
|
552
|
+
newContext, flags).getPrimaryObject()
|
553
|
+
|
554
|
+
return newContext
|
555
|
+
elsif data =~ /\A#{MARSHALLED_DATA_MARKER}/
|
556
|
+
return STAFMarshallingContext.new(data)
|
557
|
+
end
|
558
|
+
|
559
|
+
# Shouldn't get here
|
560
|
+
STAFMarshallingContext.new(data)
|
561
|
+
end
|
562
|
+
|
563
|
+
|
564
|
+
end
|