mirror of https://github.com/buggins/dlangui.git
264 lines
6.7 KiB
D
264 lines
6.7 KiB
D
/*
|
|
Copyright (c) 2014 Martin Cejp
|
|
|
|
Boost Software License - Version 1.0 - August 17th, 2003
|
|
|
|
Permission is hereby granted, free of charge, to any person or organization
|
|
obtaining a copy of the software and accompanying documentation covered by
|
|
this license (the "Software") to use, reproduce, display, distribute,
|
|
execute, and transmit the Software, and to prepare derivative works of the
|
|
Software, and to permit third-parties to whom the Software is furnished to
|
|
do so, all subject to the following:
|
|
|
|
The copyright notices in the Software and this entire statement, including
|
|
the above license grant, this restriction and the following disclaimer,
|
|
must be included in all copies of the Software, in whole or in part, and
|
|
all derivative works of the Software, unless such copies or derivative
|
|
works are solely in the form of machine-executable object code generated by
|
|
a source language processor.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG
|
|
//dlib.core.stream
|
|
module dimage.stream;
|
|
|
|
import std.bitmanip;
|
|
import std.stdint;
|
|
import std.conv;
|
|
|
|
//import dlib.core.memory;
|
|
|
|
alias StreamPos = uint64_t;
|
|
alias StreamSize = uint64_t;
|
|
alias StreamOffset = int64_t;
|
|
|
|
class SeekException : Exception
|
|
{
|
|
this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
|
|
{
|
|
super(msg, file, line, next);
|
|
}
|
|
}
|
|
|
|
/// Seekable
|
|
interface Seekable
|
|
{
|
|
// Won't throw on invalid position, may throw on a more serious error.
|
|
|
|
StreamPos getPosition() @property;
|
|
bool setPosition(StreamPos pos);
|
|
StreamSize size();
|
|
|
|
// Throw-on-error wrappers
|
|
|
|
final StreamPos position(StreamPos pos)
|
|
{
|
|
if (!setPosition(pos))
|
|
throw new SeekException("Cannot set Seekable position to " ~ pos.to!string);
|
|
|
|
return pos;
|
|
}
|
|
|
|
final StreamPos position()
|
|
{
|
|
return getPosition();
|
|
}
|
|
|
|
// TODO: Non-throwing version
|
|
final StreamPos seek(StreamOffset amount)
|
|
{
|
|
immutable StreamPos seekTo = getPosition() + amount;
|
|
|
|
if (!setPosition(seekTo))
|
|
throw new SeekException("Cannot set Seekable position to " ~ seekTo.to!string);
|
|
|
|
return seekTo;
|
|
}
|
|
}
|
|
|
|
/// Stream
|
|
interface Stream : Seekable
|
|
{
|
|
void close();
|
|
bool seekable();
|
|
}
|
|
|
|
interface InputStream : Stream
|
|
{
|
|
// Won't throw on EOF, may throw on a more serious error.
|
|
|
|
bool readable();
|
|
size_t readBytes(void* buffer, size_t count);
|
|
|
|
/// Read array.length elements into an pre-allocated array.
|
|
/// Returns: true if all elements were read, false otherwise
|
|
final bool fillArray(T)(T[] array)
|
|
{
|
|
immutable size_t len = array.length * T.sizeof;
|
|
return readBytes(array.ptr, len) == len;
|
|
}
|
|
|
|
/// Read an integer in little-endian encoding
|
|
final bool readLE(T)(T* value)
|
|
{
|
|
ubyte[T.sizeof] buffer;
|
|
|
|
if (readBytes(buffer.ptr, buffer.length) != buffer.length)
|
|
return false;
|
|
|
|
*value = littleEndianToNative!T(buffer);
|
|
return true;
|
|
}
|
|
|
|
/// Read an integer in big-endian encoding
|
|
final bool readBE(T)(T* value)
|
|
{
|
|
ubyte[T.sizeof] buffer;
|
|
|
|
if (readBytes(buffer.ptr, buffer.length) != buffer.length)
|
|
return false;
|
|
|
|
*value = bigEndianToNative!T(buffer);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
interface OutputStream : Stream
|
|
{
|
|
// Won't throw on full disk, may throw on a more serious error.
|
|
|
|
void flush();
|
|
bool writeable();
|
|
size_t writeBytes(const void* buffer, size_t count);
|
|
|
|
/// Write array.length elements from array.
|
|
/// Returns: true if all elements were written, false otherwise
|
|
final bool writeArray(T)(const T[] array)
|
|
{
|
|
immutable size_t len = array.length * T.sizeof;
|
|
return writeBytes(array.ptr, len) == len;
|
|
}
|
|
|
|
/// Write a string as zero-terminated
|
|
/// Returns: true on success, false otherwise
|
|
final bool writeStringz(string text)
|
|
{
|
|
ubyte[1] zero = [0];
|
|
|
|
return writeBytes(text.ptr, text.length)
|
|
&& writeBytes(zero.ptr, zero.length);
|
|
}
|
|
|
|
/// Write an integer in little-endian encoding
|
|
final bool writeLE(T)(const T value)
|
|
{
|
|
ubyte[T.sizeof] buffer = nativeToLittleEndian!T(value);
|
|
|
|
return writeBytes(buffer.ptr, buffer.length) == buffer.length;
|
|
}
|
|
|
|
/// Write an integer in big-endian encoding
|
|
final bool writeBE(T)(const T value)
|
|
{
|
|
ubyte[T.sizeof] buffer = nativeToBigEndian!T(value);
|
|
|
|
return writeBytes(buffer.ptr, buffer.length) == buffer.length;
|
|
}
|
|
}
|
|
|
|
interface IOStream : InputStream, OutputStream
|
|
{
|
|
}
|
|
|
|
StreamSize copyFromTo(InputStream input, OutputStream output)
|
|
{
|
|
ubyte[0x1000] buffer;
|
|
StreamSize total = 0;
|
|
|
|
while (input.readable)
|
|
{
|
|
size_t have = input.readBytes(buffer.ptr, buffer.length);
|
|
|
|
if (have == 0)
|
|
break;
|
|
|
|
output.writeBytes(buffer.ptr, have);
|
|
total += have;
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
// TODO: Move this?
|
|
// TODO: Add OutputStream methods
|
|
class ArrayStream : InputStream {
|
|
import std.algorithm;
|
|
|
|
this() {
|
|
}
|
|
|
|
this(ubyte[] data, size_t size) {
|
|
assert(size_ <= data.length);
|
|
|
|
this.size_ = size;
|
|
this.data = data;
|
|
}
|
|
|
|
override void close() {
|
|
this.pos = 0;
|
|
this.size_ = 0;
|
|
this.data = null;
|
|
}
|
|
|
|
override bool readable() {
|
|
return pos < size_;
|
|
}
|
|
|
|
override size_t readBytes(void* buffer, size_t count) {
|
|
import std.c.string;
|
|
|
|
count = min(count, size_ - pos);
|
|
|
|
// whoops, memcpy out of nowhere, can we do better than that?
|
|
memcpy(buffer, data.ptr + pos, count);
|
|
|
|
pos += count;
|
|
return count;
|
|
}
|
|
|
|
override bool seekable() {
|
|
return true;
|
|
}
|
|
|
|
override StreamPos getPosition() {
|
|
return pos;
|
|
}
|
|
|
|
override bool setPosition(StreamPos pos) {
|
|
if (pos > size_)
|
|
return false;
|
|
|
|
this.pos = cast(size_t)pos;
|
|
return true;
|
|
}
|
|
|
|
override StreamSize size() {
|
|
return size;
|
|
}
|
|
|
|
//mixin ManualModeImpl;
|
|
//mixin FreeImpl;
|
|
|
|
private:
|
|
size_t pos = 0, size_ = 0;
|
|
ubyte[] data; // data.length is capacity
|
|
}
|