Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit984ee2d

Browse files
committed
Work on#6
Still need to figure out what error Python raises when a request for anmmap exceeds the platform limits, then we can close this one
1 parentf57c5e2 commit984ee2d

File tree

2 files changed

+215
-11
lines changed

2 files changed

+215
-11
lines changed

‎compoundfiles/mmap.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/usr/bin/env python
2+
# vim: set et sw=4 sts=4 fileencoding=utf-8:
3+
#
4+
# A library for reading Microsoft's OLE Compound Document format
5+
# Copyright (c) 2014 Dave Hughes <dave@waveform.org.uk>
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
25+
from __future__import (
26+
unicode_literals,
27+
absolute_import,
28+
print_function,
29+
division,
30+
)
31+
str=type('')
32+
try:
33+
range=xrange
34+
exceptNameError:
35+
pass
36+
37+
importio
38+
importthreading
39+
40+
41+
classFakeMemoryMap(object):
42+
"""
43+
Provides an mmap-style interface for streams without a file descriptor.
44+
45+
The :class:`FakeMemoryMap` class can be used to emulate a memory-mapped
46+
file in cases where a seekable file-like object is provided that doesn't
47+
have a file descriptor (e.g. in-memory streams), or where a file descriptor
48+
exists but "real" mmap cannot be used for other reasons (e.g.
49+
>2Gb files on a 32-bit OS).
50+
51+
The emulated mapping is thread-safe, read-only, but obviously will be
52+
considerably slower than using a "real" mmap. All methods of a real
53+
read-only mmap are emulated (:meth:`find`, :meth:`read_byte`,
54+
:meth:`close`, etc.) so instances can be used as drop-in replacements.
55+
56+
Currently the emulation only covers the entire file (it cannot be limited
57+
to a sub-range of the file as with real mmap).
58+
"""
59+
60+
def__init__(self,f):
61+
self._lock=threading.Lock()
62+
self._file=f
63+
withself._lock:
64+
f.seek(0,io.SEEK_END)
65+
self._size=f.tell()
66+
f.seek(0)
67+
68+
def_read_only(self):
69+
raiseTypeError('fake mmap is read-only')
70+
71+
def__len__(self):
72+
returnself._size
73+
74+
def__getitem__(self,key):
75+
withself._lock:
76+
save_pos=self._file.tell()
77+
try:
78+
ifnotisinstance(key,slice):
79+
ifkey<0:
80+
key+=self._size
81+
ifnot (0<=key<self._size):
82+
raiseIndexError('fake mmap index out of range')
83+
key=slice(key,key+1,1)
84+
step=1ifkey.stepisNoneelsekey.step
85+
ifstep>0:
86+
start=min(self._size,max(0, (
87+
0ifkey.startisNoneelse
88+
key.start+self._sizeifkey.start<0else
89+
key.start
90+
)))
91+
stop=min(self._size,max(0, (
92+
self._sizeifkey.stopisNoneelse
93+
key.stop+self._sizeifkey.stop<0else
94+
key.stop
95+
)))
96+
self._file.seek(start)
97+
returnself._file.read(stop-start)[::step]
98+
elifstep<0:
99+
start=min(self._size,max(0, (
100+
-1ifkey.stopisNoneelse
101+
key.stop+self._sizeifkey.stop<0else
102+
key.stop
103+
)+1))
104+
stop=min(self._size,max(0, (
105+
self._size-1ifkey.startisNoneelse
106+
key.start+self._sizeifkey.start<0else
107+
key.start
108+
)+1))
109+
self._file.seek(start)
110+
return''.join(reversed(self._file.read(stop-start)))[::-step]
111+
else:
112+
raiseValueError('slice step cannot be zero')
113+
finally:
114+
self._file.seek(save_pos)
115+
116+
def__contains__(self,value):
117+
returnself.find(value)!=-1
118+
119+
def__setitem__(self,index,value):
120+
self._read_only()
121+
122+
defclose(self):
123+
pass
124+
125+
deffind(self,string,start=None,end=None):
126+
# XXX Naive find; replace with Boyer-Moore?
127+
l=len(string)
128+
start=min(self._size,max(0,
129+
0ifstartisNoneelse
130+
self._size+startifstart<0else
131+
start
132+
))
133+
end=min(self._size,max(0,
134+
self._sizeifendisNoneelse
135+
self._size+stopifstop<0else
136+
stop
137+
))
138+
foriinrange(start,end-l):
139+
ifself[i:i+l]==string:
140+
returni
141+
return-1
142+
143+
defflush(self,offset=None,size=None):
144+
self._read_only()
145+
146+
defmove(self,dest,src,count):
147+
self._read_only()
148+
149+
defread(self,num):
150+
withself._lock:
151+
returnself._file.read(num)
152+
153+
defread_byte(self):
154+
# XXX Beyond EOF = ValueError
155+
withself._lock:
156+
returnself._file.read(1)
157+
158+
defreadline(self):
159+
withself._lock:
160+
returnself._file.readline()
161+
162+
defresize(self):
163+
self._read_only()
164+
165+
defrfind(self,string,start=None,end=None):
166+
# XXX Naive find; replace with Boyer-Moore?
167+
l=len(string)
168+
start=min(self._size,max(0,
169+
self._size-1ifstartisNoneelse
170+
self._size+startifstart<0else
171+
start
172+
))
173+
stop=min(self._size,max(0,
174+
-1ifendisNoneelse
175+
self._size+endifend<0else
176+
end
177+
))
178+
foriinrange(start-l,end,-1):
179+
ifself[i:i+l]==string:
180+
returni
181+
return-1
182+
183+
defseek(self,pos,whence=io.SEEK_SET):
184+
withself._lock:
185+
self._file.seek(pos,whence)
186+
returnself._file.tell()
187+
188+
defsize(self):
189+
returnself._size
190+
191+
deftell(self):
192+
withself._lock:
193+
returnself._file.tell()
194+
195+
defwrite(self,string):
196+
self._read_only()
197+
198+
defwrite_byte(self,byte):
199+
self._read_only()
200+

‎compoundfiles/reader.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
CompoundFileMasterSectorWarning,
5757
CompoundFileNormalSectorWarning,
5858
)
59+
from .mmapimportFakeMemoryMap
5960
from .entitiesimportCompoundFileEntity
6061
from .streamsimport (
6162
CompoundFileNormalStream,
@@ -170,25 +171,28 @@ def __init__(self, filename_or_obj):
170171
ifisinstance(filename_or_obj, (str,bytes)):
171172
self._opened=True
172173
self._file=io.open(filename_or_obj,'rb')
174+
self._mmap=mmap.mmap(self._file.fileno(),0,access=mmap.ACCESS_READ)
173175
else:
176+
self._opened=False
177+
self._file=filename_or_obj
174178
try:
175-
filename_or_obj.fileno()
179+
fd=filename_or_obj.fileno()
176180
except (IOError,AttributeError):
177-
# It's a file-like object without a valid file descriptor;copy
178-
#its content to a spooled temp fileanduse that for mmap
181+
# It's a file-like object without a valid file descriptor;use
182+
#our fake mmap class (if it supports seekandtell)
179183
try:
180-
filename_or_obj.seek(0)
184+
self._file.seek(0)
185+
self._file.tell()
181186
except (IOError,AttributeError):
182-
raiseIOError('filename_or_obj must support seek() or fileno()')
183-
self._opened=True
184-
self._file=tempfile.SpooledTemporaryFile()
185-
shutil.copyfileobj(filename_or_obj,self._file)
187+
raiseIOError(
188+
'filename_or_obj must support fileno(), '
189+
'or seek() and tell()')
190+
else:
191+
self._mmap=FakeMemoryMap(filename_or_obj)
186192
else:
187193
# It's a file-like object with a valid file descriptor; just
188194
# reference the object and mmap it
189-
self._opened=False
190-
self._file=filename_or_obj
191-
self._mmap=mmap.mmap(self._file.fileno(),0,access=mmap.ACCESS_READ)
195+
self._mmap=mmap.mmap(fd,0,access=mmap.ACCESS_READ)
192196

193197
self._master_fat=None
194198
self._normal_fat=None

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp