1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Scoped.h"
16 * On architectures that are little endian and that support unaligned reads,
17 * we can use direct type, but on others, we want to have a special class
18 * to handle conversion and alignment issues.
20 #if !defined(DEBUG) && (defined(__i386__) || defined(__x86_64__))
21 typedef uint16_t le_uint16
;
22 typedef uint32_t le_uint32
;
26 * Template that allows to find an unsigned int type from a (computed) bit size
28 template <int s
> struct UInt
{ };
29 template <> struct UInt
<16> { typedef uint16_t Type
; };
30 template <> struct UInt
<32> { typedef uint32_t Type
; };
33 * Template to access 2 n-bit sized words as a 2*n-bit sized word, doing
34 * conversion from little endian and avoiding alignment issues.
40 typedef typename UInt
<16 * sizeof(T
)>::Type Type
;
44 return (b
<< (sizeof(T
) * 8)) | a
;
47 const le_to_cpu
& operator =(const Type
&v
)
49 a
= v
& ((1 << (sizeof(T
) * 8)) - 1);
50 b
= v
>> (sizeof(T
) * 8);
55 le_to_cpu(const Type
&v
)
60 const le_to_cpu
& operator +=(const Type
&v
)
62 return operator =(operator Type() + v
);
65 const le_to_cpu
& operator ++(int)
67 return operator =(operator Type() + 1);
77 typedef le_to_cpu
<unsigned char> le_uint16
;
78 typedef le_to_cpu
<le_uint16
> le_uint32
;
83 * AutoCloseFD is a RAII wrapper for POSIX file descriptors
85 struct AutoCloseFDTraits
88 static int empty() { return -1; }
89 static void release(int fd
) { if (fd
!= -1) close(fd
); }
91 typedef mozilla::Scoped
<AutoCloseFDTraits
> AutoCloseFD
;
94 * AutoCloseFILE is a RAII wrapper for POSIX streams
96 struct AutoCloseFILETraits
99 static FILE *empty() { return nullptr; }
100 static void release(FILE *f
) { if (f
) fclose(f
); }
102 typedef mozilla::Scoped
<AutoCloseFILETraits
> AutoCloseFILE
;
105 * Page alignment helpers
107 static inline size_t PageSize()
112 static inline uintptr_t AlignedPtr(uintptr_t ptr
, size_t alignment
)
114 return ptr
& ~(alignment
- 1);
117 template <typename T
>
118 static inline T
*AlignedPtr(T
*ptr
, size_t alignment
)
120 return reinterpret_cast<T
*>(
121 AlignedPtr(reinterpret_cast<uintptr_t>(ptr
), alignment
));
124 template <typename T
>
125 static inline T
PageAlignedPtr(T ptr
)
127 return AlignedPtr(ptr
, PageSize());
130 static inline uintptr_t AlignedEndPtr(uintptr_t ptr
, size_t alignment
)
132 return AlignedPtr(ptr
+ alignment
- 1, alignment
);
135 template <typename T
>
136 static inline T
*AlignedEndPtr(T
*ptr
, size_t alignment
)
138 return reinterpret_cast<T
*>(
139 AlignedEndPtr(reinterpret_cast<uintptr_t>(ptr
), alignment
));
142 template <typename T
>
143 static inline T
PageAlignedEndPtr(T ptr
)
145 return AlignedEndPtr(ptr
, PageSize());
148 static inline size_t AlignedSize(size_t size
, size_t alignment
)
150 return (size
+ alignment
- 1) & ~(alignment
- 1);
153 static inline size_t PageAlignedSize(size_t size
)
155 return AlignedSize(size
, PageSize());
158 static inline bool IsAlignedPtr(uintptr_t ptr
, size_t alignment
)
160 return ptr
% alignment
== 0;
163 template <typename T
>
164 static inline bool IsAlignedPtr(T
*ptr
, size_t alignment
)
166 return IsAlignedPtr(reinterpret_cast<uintptr_t>(ptr
), alignment
);
169 template <typename T
>
170 static inline bool IsPageAlignedPtr(T ptr
)
172 return IsAlignedPtr(ptr
, PageSize());
175 static inline bool IsAlignedSize(size_t size
, size_t alignment
)
177 return size
% alignment
== 0;
180 static inline bool IsPageAlignedSize(size_t size
)
182 return IsAlignedSize(size
, PageSize());
185 static inline size_t PageNumber(size_t size
)
187 return (size
+ PageSize() - 1) / PageSize();
191 * MemoryRange stores a pointer, size pair.
196 MemoryRange(void *buf
, size_t length
): buf(buf
), length(length
) { }
198 void Assign(void *b
, size_t len
) {
203 void Assign(const MemoryRange
& other
) {
205 length
= other
.length
;
213 operator void *() const
218 operator unsigned char *() const
220 return reinterpret_cast<unsigned char *>(buf
);
223 bool operator ==(void *ptr
) const {
227 bool operator ==(unsigned char *ptr
) const {
231 void *operator +(off_t offset
) const
233 return reinterpret_cast<char *>(buf
) + offset
;
237 * Returns whether the given address is within the mapped range
239 bool Contains(void *ptr
) const
241 return (ptr
>= buf
) && (ptr
< reinterpret_cast<char *>(buf
) + length
);
245 * Returns the length of the mapped range
247 size_t GetLength() const
252 static MemoryRange
mmap(void *addr
, size_t length
, int prot
, int flags
,
253 int fd
, off_t offset
) {
254 return MemoryRange(::mmap(addr
, length
, prot
, flags
, fd
, offset
), length
);
263 * MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
264 * a simple void * or unsigned char *.
266 * It is defined as a derivative of a template that allows to use a
267 * different unmapping strategy.
269 template <typename T
>
270 class GenericMappedPtr
: public MemoryRange
273 GenericMappedPtr(void *buf
, size_t length
): MemoryRange(buf
, length
) { }
274 GenericMappedPtr(const MemoryRange
& other
): MemoryRange(other
) { }
275 GenericMappedPtr(): MemoryRange(MAP_FAILED
, 0) { }
277 void Assign(void *b
, size_t len
) {
278 if (get() != MAP_FAILED
)
279 static_cast<T
*>(this)->munmap(get(), GetLength());
280 MemoryRange::Assign(b
, len
);
283 void Assign(const MemoryRange
& other
) {
284 Assign(other
.get(), other
.GetLength());
289 if (get() != MAP_FAILED
)
290 static_cast<T
*>(this)->munmap(get(), GetLength());
295 struct MappedPtr
: public GenericMappedPtr
<MappedPtr
>
297 MappedPtr(void *buf
, size_t length
)
298 : GenericMappedPtr
<MappedPtr
>(buf
, length
) { }
299 MappedPtr(const MemoryRange
& other
)
300 : GenericMappedPtr
<MappedPtr
>(other
) { }
301 MappedPtr(): GenericMappedPtr
<MappedPtr
>() { }
304 friend class GenericMappedPtr
<MappedPtr
>;
305 void munmap(void *buf
, size_t length
)
307 ::munmap(buf
, length
);
312 * UnsizedArray is a way to access raw arrays of data in memory.
315 * UnsizedArray<S> a(buf);
316 * UnsizedArray<S> b; b.Init(buf);
318 * This is roughly equivalent to
319 * const S *a = reinterpret_cast<const S *>(buf);
320 * const S *b = nullptr; b = reinterpret_cast<const S *>(buf);
322 * An UnsizedArray has no known length, and it's up to the caller to make
323 * sure the accessed memory is mapped and makes sense.
325 template <typename T
>
329 typedef size_t idx_t
;
332 * Constructors and Initializers
334 UnsizedArray(): contents(nullptr) { }
335 UnsizedArray(const void *buf
): contents(reinterpret_cast<const T
*>(buf
)) { }
337 void Init(const void *buf
)
339 MOZ_ASSERT(contents
== nullptr);
340 contents
= reinterpret_cast<const T
*>(buf
);
344 * Returns the nth element of the array
346 const T
&operator[](const idx_t index
) const
348 MOZ_ASSERT(contents
);
349 return contents
[index
];
352 operator const T
*() const
357 * Returns whether the array points somewhere
359 operator bool() const
361 return contents
!= nullptr;
368 * Array, like UnsizedArray, is a way to access raw arrays of data in memory.
369 * Unlike UnsizedArray, it has a known length, and is enumerable with an
373 * Array<S> a(buf, len);
374 * UnsizedArray<S> b; b.Init(buf, len);
376 * In the above examples, len is the number of elements in the array. It is
377 * also possible to initialize an Array with the buffer size:
379 * Array<S> c; c.InitSize(buf, size);
381 * It is also possible to initialize an Array in two steps, only providing
382 * one data at a time:
386 * d.Init(len); // or d.InitSize(size);
389 template <typename T
>
390 class Array
: public UnsizedArray
<T
>
393 typedef typename UnsizedArray
<T
>::idx_t idx_t
;
396 * Constructors and Initializers
398 Array(): UnsizedArray
<T
>(), length(0) { }
399 Array(const void *buf
, const idx_t length
)
400 : UnsizedArray
<T
>(buf
), length(length
) { }
402 void Init(const void *buf
)
404 UnsizedArray
<T
>::Init(buf
);
407 void Init(const idx_t len
)
409 MOZ_ASSERT(length
== 0);
413 void InitSize(const idx_t size
)
415 Init(size
/ sizeof(T
));
418 void Init(const void *buf
, const idx_t len
)
420 UnsizedArray
<T
>::Init(buf
);
424 void InitSize(const void *buf
, const idx_t size
)
426 UnsizedArray
<T
>::Init(buf
);
431 * Returns the nth element of the array
433 const T
&operator[](const idx_t index
) const
435 MOZ_ASSERT(index
< length
);
436 MOZ_ASSERT(operator bool());
437 return UnsizedArray
<T
>::operator[](index
);
441 * Returns the number of elements in the array
443 idx_t
numElements() const
449 * Returns whether the array points somewhere and has at least one element.
451 operator bool() const
453 return (length
> 0) && UnsizedArray
<T
>::operator bool();
457 * Iterator for an Array. Use is similar to that of STL const_iterators:
460 * Array<S> a(buf, len);
461 * for (Array<S>::iterator it = a.begin(); it < a.end(); ++it) {
462 * // Do something with *it.
468 iterator(): item(nullptr) { }
470 const T
&operator *() const
475 const T
*operator ->() const
480 iterator
&operator ++()
486 bool operator<(const iterator
&other
) const
488 return item
< other
.item
;
491 friend class Array
<T
>;
492 iterator(const T
&item
): item(&item
) { }
499 * Returns an iterator pointing at the beginning of the Array
501 iterator
begin() const {
503 return iterator(UnsizedArray
<T
>::operator[](0));
508 * Returns an iterator pointing past the end of the Array
510 iterator
end() const {
512 return iterator(UnsizedArray
<T
>::operator[](length
));
517 * Reverse iterator for an Array. Use is similar to that of STL
518 * const_reverse_iterators:
521 * Array<S> a(buf, len);
522 * for (Array<S>::reverse_iterator it = a.rbegin(); it < a.rend(); ++it) {
523 * // Do something with *it.
526 class reverse_iterator
529 reverse_iterator(): item(nullptr) { }
531 const T
&operator *() const
537 const T
*operator ->() const
542 reverse_iterator
&operator ++()
548 bool operator<(const reverse_iterator
&other
) const
550 return item
> other
.item
;
553 friend class Array
<T
>;
554 reverse_iterator(const T
&item
): item(&item
) { }
561 * Returns a reverse iterator pointing at the end of the Array
563 reverse_iterator
rbegin() const {
565 return reverse_iterator(UnsizedArray
<T
>::operator[](length
));
566 return reverse_iterator();
570 * Returns a reverse iterator pointing past the beginning of the Array
572 reverse_iterator
rend() const {
574 return reverse_iterator(UnsizedArray
<T
>::operator[](0));
575 return reverse_iterator();
582 * Transforms a pointer-to-function to a pointer-to-object pointing at the
585 template <typename T
>
586 void *FunctionPtr(T func
)