aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ); }