module FileOp; /* coded by gogamza 2007.07.24 http://www.freesearch.pe.kr */ import std.stream; import std.system; import std.utf; import std.stdio; uint toBigEnd(uint hostlong){ ubyte[4] retbyte; // 현재의 머신이 리틀엔디언이라면 if(endian == Endian.LittleEndian){ // little -> big retbyte[length - 4] = hostlong >> 24; retbyte[length - 3] = hostlong >> 16; retbyte[length - 2] = hostlong >> 8; retbyte[length - 1] = hostlong; //retbyte를 uint*로 캐스팅, 레퍼런스값을 취한다. return *cast(uint*)&retbyte[0]; }else return hostlong; } alias toBigEnd toLittleEnd; class FileStream : FileOperate{ private: public: this(char[] name, FileMode mode){ super(name, mode); } void writeByte(byte one) in{ }out{ }body{ super.write(one); } void writeBytes(byte[] aByte) in{ }out{ }body{ super.write(aByte); } void writeInt(uint nNum) in{ assert( nNum >= 0 ); }out{ }body{ uint i = toBigEnd(nNum); byte* temp = cast(byte*)&i; byte[] temp2nd = temp[0 .. i.sizeof]; super.write(temp2nd); } // lower byte 부터 쓴다. void writeVInt(uint nNum) in{ assert( nNum >= 0 ); }out{ }body{ while( (nNum & ~0x7F) != 0){ this.writeByte((nNum & 0x7F) | 0x80); nNum >>= 7; } this.writeByte(nNum); } void writeVLong(ulong nNum) in{ assert( nNum >= 0 ); }out{ }body{ while( (nNum & ~0x7F) != 0){ this.writeByte((nNum & 0x7F) | 0x80); nNum >>= 7; } this.writeByte(nNum); } void writeLong(ulong nNum) in{ assert( nNum >= 0); }out{ }body{ this.writeInt( (nNum >> 32) & 0xFFFFFFFF ); this.writeInt( nNum & 0xFFFFFFFF ); } //반드시 utf-8로 써야한다. void writeString(char[] strData) in{ assert(strData.length > 0); }out{ }body{ this.writeVInt(strData.length); //char[] strUTF8 = toUTF8(strData); this.write(cast(byte[])strData); } ulong getFilePointer() in{ }out{ }body{ return this.tell(); } byte readByte() in{ }out{ }body{ return this.read(1)[0]; } byte[] readBytes(int nLen) in{ }out{ }body{ return this.read(nLen); } uint readInt() in{ }out(result){ }body{ return toLittleEnd( *(cast(uint*)this.read(4).ptr) ); } //낮은 바이트부터 체킹 uint readVInt() in{ }out(result){ }body{ byte b = this.readByte(); uint i = b & 0x7F; int shift = 7; while((b & 0x80) != 0){ b = this.readByte(); i |= (b & 0x7F) << shift; shift += 7; } return i; } ulong readLong() in{ }out(result){ assert( is(result == ulong) ); }body{ return ( this.readInt() << 32 | (this.readInt() & 0xFFFFFFFFUL) ); } ulong readVLong() in{ }out{ }body{ byte b = this.readByte(); ulong i = b & 0x7F; int shift = 7; while((b & 0x80) != 0){ b = this.readByte(); i |= (b & 0x7F) << shift; shift += 7; } return i; } char[] readChars(int length) in{ }out{ }body{ return cast(char[])this.readBytes(length); } /* char[] buffer; for(int i = 0; i < length; i++){ byte b = this.readByte()[0]; if((b & 0x80) == 0){ char temp = b & 0x7F; //buffer ~= toUTF8(new char[](temp)); writefln(temp); buffer ~= temp; }else if( (b & 0xE0) != 0xE0 ){ char[] temp = new char[2]; temp[0] = b; temp[1] = this.readByte()[0]; buffer ~= temp; int a = (((b & 0x1F) << 6)|(this.readByte()[0] & 0x3F)); char* temp = cast(char*)&a; char[] temp2nd = temp[0 .. 2]; buffer ~= temp2nd; }else{ char[] temp = new char[3]; temp[0] = b; temp[1] = this.readByte()[0]; temp[2] = this.readByte()[0]; int a = ((b & 0x0f) << 12) | ((this.readByte()[0] & 0x3F) << 6) | (this.readByte()[0] & 0x3F); char* temp = cast(char*)&a; char[] temp2nd = temp[0 .. 3]; buffer ~= temp2nd; } } return buffer; } */ char[] readString() in{ }out{ }body{ uint nLen = this.readVInt(); return this.readChars(nLen); } } class FileOperate { private: File file; ulong position; public: this(char[] name, FileMode mode){ this.file = new File(name, mode); this.position = 0; } void close(){ this.file.close(); } void seek(long pos){ this.position = pos; this.file.seekSet(pos); } ulong seekEnd(long offset){ this.position = this.file.seekEnd(offset); return this.position; } ulong tell(){ return this.position; } byte[] read(int nLen){ ulong p = this.file.position(); if( p != this.position) this.seek(this.position); byte[] buffer = new byte[nLen]; this.file.readExact(cast(byte*)buffer, nLen); this.position += nLen; return buffer; } void write(byte[] bData){ ulong p = this.file.position(); if(p != this.position) this.seek(this.position); this.file.writeExact(cast(byte*)bData, bData.length); this.position += bData.length; } void write(byte Data){ ulong p = this.file.position(); if(p != this.position) this.seek(this.position); this.file.write(Data); this.position += Data.sizeof; } File getFile(){ return this.file; } bool isSeekable(ulong position){ return (this.file.size() > position); } bool isReadable(){ return this.file.readable; } bool isWritable(){ return this.file.writeable; } } /* void main(){ FileStream fp = new FileStream("test", FileMode.Out | FileMode.In); fp.writeString("abcdefghijklmnr고감자입니다."); fp.seek(0); char[] a = fp.readString(); writefln(a); fp.close(); //writefln("%x", b); // FileStream fp1 = new FileStream("test", FileMode.In); char[] a = fp1.readString(); writefln(a); fp1.close(); } */