summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2008-10-08 16:17:26 +0000
committerMike Buland <eichlan@xagasoft.com>2008-10-08 16:17:26 +0000
commit3f1c8998166466245aee2860197fb4908e55f1a2 (patch)
treeb6d148679bbd87125f03cb723d5b59969b90c733
parent5883662909051e99093514483c32e2539a3cf850 (diff)
downloadlibbu++-3f1c8998166466245aee2860197fb4908e55f1a2.tar.gz
libbu++-3f1c8998166466245aee2860197fb4908e55f1a2.tar.bz2
libbu++-3f1c8998166466245aee2860197fb4908e55f1a2.tar.xz
libbu++-3f1c8998166466245aee2860197fb4908e55f1a2.zip
Ok...corrected a problem with new block allocation in nids, and it no longer
goes into an infinite loop while doing certain kinds of read. Also, it zeros out new blocks to make things easier to cope with in the hex editor, it'll probably also compress better. I also fixed Bu::MemBuf so that you can now write to arbitrary places mid-stream.
-rw-r--r--src/membuf.cpp26
-rw-r--r--src/membuf.h5
-rw-r--r--src/nids.cpp115
-rw-r--r--src/nids.h14
-rw-r--r--src/nidsstream.cpp40
-rw-r--r--src/tests/nids.cpp40
-rw-r--r--src/unit/membuf.cpp16
7 files changed, 185 insertions, 71 deletions
diff --git a/src/membuf.cpp b/src/membuf.cpp
index 6d850bf..e7c7ac8 100644
--- a/src/membuf.cpp
+++ b/src/membuf.cpp
@@ -41,9 +41,29 @@ size_t Bu::MemBuf::read( void *pBuf, size_t nBytes )
41 41
42size_t Bu::MemBuf::write( const void *pBuf, size_t nBytes ) 42size_t Bu::MemBuf::write( const void *pBuf, size_t nBytes )
43{ 43{
44 sBuf.append( (const char *)pBuf, nBytes ); 44 if( nPos == sBuf.getSize() )
45 nPos += nBytes; 45 {
46 return nBytes; 46 // Easiest, just append the data.
47 sBuf.append( (const char *)pBuf, nBytes );
48 nPos += nBytes;
49 return nBytes;
50 }
51 else
52 {
53 // Trickier, we must do this in two parts, overwrite, then append
54 // Frist, overwrite.
55 int iOver = sBuf.getSize() - nPos;
56 if( iOver > nBytes )
57 iOver = nBytes;
58 memcpy( sBuf.getStr()+nPos, pBuf, iOver );
59 // Then append
60 if( iOver < nBytes )
61 {
62 sBuf.append( ((const char *)pBuf)+iOver, nBytes-iOver );
63 }
64 nPos += nBytes;
65 return nBytes;
66 }
47} 67}
48 68
49long Bu::MemBuf::tell() 69long Bu::MemBuf::tell()
diff --git a/src/membuf.h b/src/membuf.h
index b728f38..15686e9 100644
--- a/src/membuf.h
+++ b/src/membuf.h
@@ -29,11 +29,6 @@ namespace Bu
29 virtual void close(); 29 virtual void close();
30 virtual size_t read( void *pBuf, size_t nBytes ); 30 virtual size_t read( void *pBuf, size_t nBytes );
31 31
32 /**
33 *@todo Allow writes at the current position, not just appending to
34 * the current buffer. This is a silly way to do it, but it covers all
35 * of our bases for now.
36 */
37 virtual size_t write( const void *pBuf, size_t nBytes ); 32 virtual size_t write( const void *pBuf, size_t nBytes );
38 using Stream::write; 33 using Stream::write;
39 virtual long tell(); 34 virtual long tell();
diff --git a/src/nids.cpp b/src/nids.cpp
index a6596a2..06895ac 100644
--- a/src/nids.cpp
+++ b/src/nids.cpp
@@ -1,3 +1,10 @@
1/*
2 * Copyright (C) 2007-2008 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
1#include "bu/nids.h" 8#include "bu/nids.h"
2#include "bu/stream.h" 9#include "bu/stream.h"
3#include "bu/nidsstream.h" 10#include "bu/nidsstream.h"
@@ -16,30 +23,6 @@ Bu::Nids::Nids( Bu::Stream &sStore ) :
16 iBlocks( 0 ), 23 iBlocks( 0 ),
17 iBlockStart( -1 ) 24 iBlockStart( -1 )
18{ 25{
19 printf("blockUnused = %u\n", blockUnused );
20 printf("Stream caps:\n"
21 " canRead: %s\n"
22 " canWrite: %s\n"
23 " isReadable: %s\n"
24 " isWritable: %s\n"
25 " isSeekable: %s\n"
26 " isBlocking: %s\n"
27 " isEOS: %s\n"
28 " isOpen: %s\n",
29 sStore.canRead()?"yes":"no",
30 sStore.canWrite()?"yes":"no",
31 sStore.isReadable()?"yes":"no",
32 sStore.isWritable()?"yes":"no",
33 sStore.isSeekable()?"yes":"no",
34 sStore.isBlocking()?"yes":"no",
35 sStore.isEOS()?"yes":"no",
36 sStore.isOpen()?"yes":"no"
37 );
38 printf("sizeof(Block) = %db\n", sizeof(Block) );
39 printf("Magic: %02X%02X%02X%02X\n",
40 NIDS_MAGIC_CODE[0], NIDS_MAGIC_CODE[1],
41 NIDS_MAGIC_CODE[2], NIDS_MAGIC_CODE[3]
42 );
43} 26}
44 27
45Bu::Nids::~Nids() 28Bu::Nids::~Nids()
@@ -49,6 +32,7 @@ Bu::Nids::~Nids()
49void Bu::Nids::initialize() 32void Bu::Nids::initialize()
50{ 33{
51 unsigned char buf[4]; 34 unsigned char buf[4];
35 int iUsed;
52 if( sStore.read( buf, 4 ) < 4 ) 36 if( sStore.read( buf, 4 ) < 4 )
53 throw NidsException("Input stream appears to be empty."); 37 throw NidsException("Input stream appears to be empty.");
54 if( memcmp( buf, NIDS_MAGIC_CODE, 4 ) ) 38 if( memcmp( buf, NIDS_MAGIC_CODE, 4 ) )
@@ -56,8 +40,31 @@ void Bu::Nids::initialize()
56 throw NidsException( 40 throw NidsException(
57 "Stream does not appear to be a valid NIDS format."); 41 "Stream does not appear to be a valid NIDS format.");
58 } 42 }
59 43 sStore.read( buf, 2 );
60 44 if( buf[0] != 0 )
45 throw NidsException(
46 "We can only handle version 0 for now.");
47 if( buf[1] != 4 )
48 throw NidsException(
49 "We can only handle 4-byte words at the moment.");
50 sStore.read( &iBlockSize, 4 );
51 sStore.read( &iBlocks, 4 );
52 sStore.read( &iUsed, 4 ); // number of used blocks...
53 sStore.seek( 7 ); // skip reserved space.
54 iBlockStart = sStore.tell();
55
56 //printf("%d blocks, %db each, %db block offset\n",
57 // iBlocks, iBlockSize, iBlockStart );
58
59 bsBlockUsed.setSize( iBlocks, true );
60 Block bTmp;
61 for( int j = 0; j < iBlocks; j++ )
62 {
63 sStore.seek( iBlockStart+iBlockSize*j );
64 sStore.read( &bTmp, sizeof(bTmp) );
65 if( bTmp.uFirstBlock != blockUnused )
66 bsBlockUsed.setBit( j );
67 }
61} 68}
62 69
63void Bu::Nids::initialize( int iBlockSize, int iPreAllocate ) 70void Bu::Nids::initialize( int iBlockSize, int iPreAllocate )
@@ -88,11 +95,11 @@ void Bu::Nids::initialize( int iBlockSize, int iPreAllocate )
88 this->iBlockSize = iBlockSize; 95 this->iBlockSize = iBlockSize;
89 this->iBlocks = iPreAllocate; 96 this->iBlocks = iPreAllocate;
90 this->iBlockStart = sStore.tell(); 97 this->iBlockStart = sStore.tell();
91 printf("iBlockStart = %d\n", this->iBlockStart ); 98 //printf("iBlockStart = %d\n", this->iBlockStart );
92 bsBlockUsed.setSize( iPreAllocate, true ); 99 bsBlockUsed.setSize( iPreAllocate, true );
93 100
94 printf("%d blocks, %db each, %db block offset\n", 101 //printf("%d blocks, %db each, %db block offset\n",
95 iBlocks, iBlockSize, iBlockStart ); 102 // iBlocks, iBlockSize, iBlockStart );
96 103
97 Block *block = (Block *)new char[iBlockSize]; 104 Block *block = (Block *)new char[iBlockSize];
98 memset( block, 0, iBlockSize ); 105 memset( block, 0, iBlockSize );
@@ -104,6 +111,26 @@ void Bu::Nids::initialize( int iBlockSize, int iPreAllocate )
104 delete[] (char *)block; 111 delete[] (char *)block;
105} 112}
106 113
114void Bu::Nids::initBlock( uint32_t uPos, uint32_t uFirstBlock,
115 uint32_t uPrevBlock, bool bNew )
116{
117 Block b = { uPos, blockUnused, uPrevBlock, 0, 0, { } };
118 if( uFirstBlock != blockUnused )
119 b.uFirstBlock = uFirstBlock;
120 bsBlockUsed.setBit( uPos );
121 sStore.setPos( iBlockStart+(iBlockSize*uPos) );
122 sStore.write( &b, sizeof(Block) );
123 if( bNew )
124 {
125 // It's a new one, at the end, write some zeros.
126 int iSize = iBlockSize-sizeof(Block);
127 char *buf = new char[iSize];
128 memset( buf, 0, iSize );
129 sStore.write( buf, iSize );
130 delete[] buf;
131 }
132}
133
107uint32_t Bu::Nids::createBlock( uint32_t uFirstBlock, uint32_t uPrevBlock, 134uint32_t Bu::Nids::createBlock( uint32_t uFirstBlock, uint32_t uPrevBlock,
108 int /*iPreAllocate*/ ) 135 int /*iPreAllocate*/ )
109{ 136{
@@ -111,16 +138,15 @@ uint32_t Bu::Nids::createBlock( uint32_t uFirstBlock, uint32_t uPrevBlock,
111 { 138 {
112 if( !bsBlockUsed.getBit( j ) ) 139 if( !bsBlockUsed.getBit( j ) )
113 { 140 {
114 Block b = { j, blockUnused, uPrevBlock, 0, 0, { } }; 141 initBlock( j, uFirstBlock, uPrevBlock );
115 if( uFirstBlock != blockUnused )
116 b.uFirstBlock = uFirstBlock;
117 bsBlockUsed.setBit( j );
118 sStore.setPos( iBlockStart+(iBlockSize*j) );
119 sStore.write( &b, sizeof(b) );
120 return j; 142 return j;
121 } 143 }
122 } 144 }
123 return blockUnused; 145 // Oh, we don't have any blocks left...allocate a new one.
146 iBlocks++;
147 bsBlockUsed.setSize( iBlocks, false );
148 initBlock( iBlocks-1, uFirstBlock, uPrevBlock, true );
149 return iBlocks-1;
124} 150}
125 151
126int Bu::Nids::createStream( int iPreAllocate ) 152int Bu::Nids::createStream( int iPreAllocate )
@@ -169,15 +195,22 @@ void Bu::Nids::updateStreamSize( uint32_t uIndex, uint32_t uSize )
169} 195}
170 196
171uint32_t Bu::Nids::getNextBlock( uint32_t uIndex, 197uint32_t Bu::Nids::getNextBlock( uint32_t uIndex,
172 struct Bu::Nids::Block *pBlock ) 198 struct Bu::Nids::Block *pBlock, bool bCreate )
173{ 199{
174 uint32_t uNew; 200 uint32_t uNew;
175 if( pBlock->uNextBlock == blockUnused ) 201 if( pBlock->uNextBlock == blockUnused )
176 { 202 {
177 uNew = createBlock( pBlock->uFirstBlock, uIndex ); 203 if( bCreate )
178 sStore.setPos( iBlockStart + (iBlockSize*uIndex)+1*4 ); 204 {
179 sStore.write( &uNew, 4 ); 205 uNew = createBlock( pBlock->uFirstBlock, uIndex );
180 getBlock( uNew, pBlock ); 206 sStore.setPos( iBlockStart + (iBlockSize*uIndex)+1*4 );
207 sStore.write( &uNew, 4 );
208 getBlock( uNew, pBlock );
209 }
210 else
211 {
212 throw Bu::NidsException("Reached end of stream.");
213 }
181 } 214 }
182 else 215 else
183 { 216 {
diff --git a/src/nids.h b/src/nids.h
index cdefdcb..d297fa1 100644
--- a/src/nids.h
+++ b/src/nids.h
@@ -1,3 +1,10 @@
1/*
2 * Copyright (C) 2007-2008 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
1#ifndef BU_NIDS_H 8#ifndef BU_NIDS_H
2#define BU_NIDS_H 9#define BU_NIDS_H
3 10
@@ -75,12 +82,17 @@ namespace Bu
75 blockUnused = 0xFFFFFFFFUL 82 blockUnused = 0xFFFFFFFFUL
76 }; 83 };
77 84
85 void initBlock( uint32_t uPos, uint32_t uFirstBlock,
86 uint32_t uPrevBlock, bool bNew=false );
78 uint32_t createBlock( uint32_t uFirstBlock, uint32_t uPrevBlock, 87 uint32_t createBlock( uint32_t uFirstBlock, uint32_t uPrevBlock,
79 int iPreAllocate=1 ); 88 int iPreAllocate=1 );
80 void getBlock( uint32_t uIndex, struct Nids::Block *pBlock ); 89 void getBlock( uint32_t uIndex, struct Nids::Block *pBlock );
81 void setBlock( uint32_t uIndex, struct Nids::Block *pBlock ); 90 void setBlock( uint32_t uIndex, struct Nids::Block *pBlock );
82 void updateStreamSize( uint32_t uIndex, uint32_t uSize ); 91 void updateStreamSize( uint32_t uIndex, uint32_t uSize );
83 uint32_t getNextBlock( uint32_t uIndex, struct Nids::Block *pBlock ); 92 uint32_t getNextBlock( uint32_t uIndex, struct Nids::Block *pBlock,
93 bool bCreate=true);
94
95 // Block allocation routines
84 Block *newBlock(); 96 Block *newBlock();
85 void deleteBlock( Block *pBlock ); 97 void deleteBlock( Block *pBlock );
86 98
diff --git a/src/nidsstream.cpp b/src/nidsstream.cpp
index 740dc1f..4f692c6 100644
--- a/src/nidsstream.cpp
+++ b/src/nidsstream.cpp
@@ -9,7 +9,7 @@ Bu::NidsStream::NidsStream( Nids &rNids, uint32_t uStream ) :
9 uBlockSize( rNids.iBlockSize-sizeof(Nids::Block) ), 9 uBlockSize( rNids.iBlockSize-sizeof(Nids::Block) ),
10 uPos( 0 ) 10 uPos( 0 )
11{ 11{
12 printf("NidsStream::allocated\n"); 12 //printf("NidsStream::allocated\n");
13 pCurBlock = rNids.newBlock(); 13 pCurBlock = rNids.newBlock();
14 rNids.getBlock( uStream, pCurBlock ); 14 rNids.getBlock( uStream, pCurBlock );
15 uSize = pCurBlock->uBytesUsed; 15 uSize = pCurBlock->uBytesUsed;
@@ -34,6 +34,7 @@ Bu::NidsStream::NidsStream( const Bu::NidsStream &rSrc ) :
34 34
35Bu::NidsStream::~NidsStream() 35Bu::NidsStream::~NidsStream()
36{ 36{
37 //printf("Destroying stream?\n");
37 rNids.updateStreamSize( uStream, uSize ); 38 rNids.updateStreamSize( uStream, uSize );
38 rNids.deleteBlock( pCurBlock ); 39 rNids.deleteBlock( pCurBlock );
39} 40}
@@ -47,20 +48,35 @@ size_t Bu::NidsStream::read( void *pBuf, size_t nBytes )
47 if( uPos%uBlockSize+nBytes < uBlockSize ) 48 if( uPos%uBlockSize+nBytes < uBlockSize )
48 { 49 {
49 size_t iRead = nBytes; 50 size_t iRead = nBytes;
50 if( iRead > pCurBlock->uBytesUsed ) 51 if( iRead > pCurBlock->uBytesUsed-(uPos%uBlockSize) )
51 iRead = pCurBlock->uBytesUsed; 52 iRead = pCurBlock->uBytesUsed-(uPos%uBlockSize);
52 memcpy( pBuf, pCurBlock->pData+(uPos%uBlockSize), iRead ); 53 memcpy( pBuf, pCurBlock->pData+(uPos%uBlockSize), iRead );
53 uPos += nBytes; 54 uPos += iRead;
54 printf("a: block %u = %ub (%ub total)\n", 55 //printf("a: block %u = %ub (%ub total)\n",
55 uCurBlock, pCurBlock->uBytesUsed, uSize ); 56 // uCurBlock, pCurBlock->uBytesUsed, uSize );
56 return iRead; 57 return iRead;
57 } 58 }
58 else 59 else
59 { 60 {
60 //size_t iTotal = 0; 61 size_t nTotal = 0;
61 for(;;) 62 for(;;)
62 { 63 {
63 64 uint32_t iRead = nBytes;
65 if( iRead > uBlockSize-(uPos%uBlockSize) )
66 iRead = uBlockSize-(uPos%uBlockSize);
67 if( iRead > pCurBlock->uBytesUsed-(uPos%uBlockSize) )
68 iRead = pCurBlock->uBytesUsed-(uPos%uBlockSize);
69 memcpy( ((char *)pBuf)+nTotal,
70 pCurBlock->pData+(uPos%uBlockSize), iRead );
71 uPos += iRead;
72 nBytes -= iRead;
73 nTotal += iRead;
74 //printf("r: block %u = %ub/%ub (%ub total)\n",
75 // uCurBlock, iRead, pCurBlock->uBytesUsed, uSize );
76 if( nBytes == 0 || uPos == uSize )
77 return nTotal;
78 if( nTotal%uBlockSize == 0 )
79 uCurBlock = rNids.getNextBlock( uCurBlock, pCurBlock, false );
64 } 80 }
65 } 81 }
66 return 0; 82 return 0;
@@ -75,8 +91,8 @@ size_t Bu::NidsStream::write( const void *pBuf, size_t nBytes )
75 rNids.setBlock( uCurBlock, pCurBlock ); 91 rNids.setBlock( uCurBlock, pCurBlock );
76 uPos += nBytes; 92 uPos += nBytes;
77 uSize += nBytes; 93 uSize += nBytes;
78 printf("a: block %u = %ub (%ub total)\n", 94 //printf("a: block %u = %ub (%ub total)\n",
79 uCurBlock, pCurBlock->uBytesUsed, uSize ); 95 // uCurBlock, pCurBlock->uBytesUsed, uSize );
80 return nBytes; 96 return nBytes;
81 } 97 }
82 else 98 else
@@ -95,8 +111,8 @@ size_t Bu::NidsStream::write( const void *pBuf, size_t nBytes )
95 uPos += uNow; 111 uPos += uNow;
96 nTotal += uNow; 112 nTotal += uNow;
97 nBytes -= uNow; 113 nBytes -= uNow;
98 printf("b: block %u = %ub (%ub total)\n", 114 //printf("b: block %u = %ub (%ub total)\n",
99 uCurBlock, pCurBlock->uBytesUsed, uSize ); 115 // uCurBlock, pCurBlock->uBytesUsed, uSize );
100 if( nBytes == 0 ) 116 if( nBytes == 0 )
101 return nTotal; 117 return nTotal;
102 if( pCurBlock->uBytesUsed == uBlockSize ) 118 if( pCurBlock->uBytesUsed == uBlockSize )
diff --git a/src/tests/nids.cpp b/src/tests/nids.cpp
index f50fde5..d531280 100644
--- a/src/tests/nids.cpp
+++ b/src/tests/nids.cpp
@@ -4,22 +4,44 @@
4 4
5int main( int argc, char *argv[] ) 5int main( int argc, char *argv[] )
6{ 6{
7 if( argc < 2 ) 7 if( argc < 3 )
8 { 8 {
9 printf("usage: %s <output>\n\n", argv[0] ); 9 printf("usage: %s [r|w] <output>\n\n", argv[0] );
10 return 1; 10 return 1;
11 } 11 }
12 12
13 Bu::File fOut( argv[1], Bu::File::ReadWrite ); 13 if( argv[1][0] == 'w' )
14 Bu::Nids n( fOut ); 14 {
15 Bu::File fOut( argv[2],
16 Bu::File::ReadWrite|Bu::File::Create|Bu::File::Truncate );
17 Bu::Nids n( fOut );
15 18
16// n.initialize( 120, 5 ); 19 n.initialize( 120, 1 );
20 Bu::NidsStream s = n.openStream( n.createStream() );
17 21
18 Bu::NidsStream s = n.openStream( n.createStream() ); 22 Bu::FString sBuf( 350 );
23 memset( sBuf.getStr(), 'a', 350 );
24 s.write( sBuf );
25 }
26 else if( argv[1][0] == 'r' )
27 {
28 Bu::File fOut( argv[2], Bu::File::Read );
29 Bu::Nids n( fOut );
19 30
20// Bu::FString sBuf( 350 ); 31 Bu::NidsStream s = n.openStream( 0 );
21// memset( sBuf.getStr(), 'a', 350 ); 32 char buf[75];
22// s.write( sBuf ); 33 for( int j = 0; j < 3; j++ )
34 {
35 int iRead = s.read( buf, 75 );
36 fwrite( buf, 1, iRead, stdout );
37 printf("\n(read %d chars)\n", iRead );
38 }
39 printf("Position: %ld\n", s.tell() );
40 }
41 else
42 {
43 printf("r or w, those are your choices.\n");
44 }
23 45
24 return 0; 46 return 0;
25} 47}
diff --git a/src/unit/membuf.cpp b/src/unit/membuf.cpp
index 3aebc4d..dc02aa3 100644
--- a/src/unit/membuf.cpp
+++ b/src/unit/membuf.cpp
@@ -15,6 +15,7 @@ public:
15 { 15 {
16 setName("MemBuf"); 16 setName("MemBuf");
17 addTest( Unit::testWriteRead01 ); 17 addTest( Unit::testWriteRead01 );
18 addTest( Unit::testOverwrite1 );
18 } 19 }
19 20
20 virtual ~Unit() 21 virtual ~Unit()
@@ -39,6 +40,21 @@ public:
39 unitTest( mb.read( buf, 7 ) == 3 ); 40 unitTest( mb.read( buf, 7 ) == 3 );
40 unitTest( !strncmp( buf, "eFG", 3 ) ); 41 unitTest( !strncmp( buf, "eFG", 3 ) );
41 } 42 }
43
44 void testOverwrite1()
45 {
46 Bu::MemBuf mb;
47 unitTest( mb.write("0123456789") == 10 );
48 mb.setPos( 4 );
49 unitTest( mb.write("-5-") == 3 );
50 mb.setPos( 9 );
51 mb.write("Hey!!!");
52 unitTest( mb.tell() == 15 );
53 char buf[50];
54 mb.setPos( 0 );
55 buf[mb.read( buf, 50 )] = '\0';
56 unitTest( !strcmp( buf, "0123-5-78Hey!!!" ) );
57 }
42}; 58};
43 59
44int main( int argc, char *argv[] ){ return Unit().run( argc, argv ); } 60int main( int argc, char *argv[] ){ return Unit().run( argc, argv ); }