- def tokens(self):
- return self._tokens
-
- def tokens_for_range(self, range_start, range_size):
- resp = [self._stream_name]
- return_all_tokens = False
- block_start = 0
- token_bytes_skipped = 0
- for locator in self.data_locators:
- sizehint = re.search(r'\+(\d+)', locator)
- if not sizehint:
- return_all_tokens = True
- if return_all_tokens:
- resp += [locator]
- next
- blocksize = int(sizehint.group(0))
- if range_start + range_size <= block_start:
- break
- if range_start < block_start + blocksize:
- resp += [locator]
- else:
- token_bytes_skipped += blocksize
- block_start += blocksize
- for f in self.files:
- if ((f[0] < range_start + range_size)
- and
- (f[0] + f[1] > range_start)
- and
- f[1] > 0):
- resp += ["%d:%d:%s" % (f[0] - token_bytes_skipped, f[1], f[2])]
- return resp
-
- LOCATOR = 0
- BLOCKSIZE = 1
- CHUNKOFFSET = 2
- CHUNKSIZE = 3
-
- def locators_and_ranges(self, range_start, range_size):
- '''returns list of [block locator, blocksize, chunk offset, chunk size] that satisfies the range'''
- print 'locators_and_ranges', range_start, range_size
- resp = []
- return_all_tokens = False
- range_start = long(range_start)
- range_size = long(range_size)
- range_end = range_start + range_size
- block_start = 0L
- for locator in self.data_locators:
- sizehint = re.search(r'[0-9a-f]{32}\+(\d+)', locator)
- if not sizehint:
- raise Exception("Manifest must include block sizes to be normalized")
- block_size = long(sizehint.group(1))
- block_end = block_start + block_size
- if range_end < block_start:
- # range ends before this block starts, so don't look at any more locators
- break
- if range_start > block_end:
- # range starts after this block ends, so go to next block
- next
- elif range_start >= block_start and range_end <= block_end:
- # range starts and ends in this block
- resp.append([locator, block_size, range_start - block_start, range_size])
- elif range_start >= block_start:
- # range starts in this block
- resp.append([locator, block_size, range_start - block_start, block_end - range_start])
- elif range_start < block_start and range_end > block_end:
- # range starts in a previous block and extends to further blocks
- resp.append([locator, block_size, 0L, block_size])
- elif range_start < block_start and range_end <= block_end:
- # range starts in a previous block and ends in this block
- resp.append([locator, block_size, 0L, range_end - block_start])
- block_start = block_end
- return resp
+ # parse stream
+ for tok in tokens:
+ if debug: print 'tok', tok
+ if self._stream_name is None:
+ self._stream_name = tok.replace('\\040', ' ')
+ continue
+
+ s = re.match(r'^[0-9a-f]{32}\+(\d+)(\+\S+)*$', tok)
+ if s:
+ blocksize = long(s.group(1))
+ self._data_locators.append(Range(tok, streamoffset, blocksize, 0))
+ streamoffset += blocksize
+ continue
+
+ s = re.search(r'^(\d+):(\d+):(\S+)', tok)
+ if s:
+ pos = long(s.group(1))
+ size = long(s.group(2))
+ name = s.group(3).replace('\\040', ' ')
+ if name not in self._files:
+ self._files[name] = StreamFileReader(self, [Range(pos, 0, size, 0)], name)
+ else:
+ filereader = self._files[name]
+ filereader.segments.append(Range(pos, filereader.size(), size))
+ continue
+
+ raise errors.SyntaxError("Invalid manifest format")