aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-10-16 16:09:02 +0000
committerMike Buland <eichlan@xagasoft.com>2009-10-16 16:09:02 +0000
commitbf53de3dfa4db68627f2935e6b2144835604df3a (patch)
treee5e50c0b0e7df827dcdc8a162f1ff5fb61ac3277
parent96b07a22f5392f5d7f821f5743deb3d64bd94e89 (diff)
downloadlibbu++-bf53de3dfa4db68627f2935e6b2144835604df3a.tar.gz
libbu++-bf53de3dfa4db68627f2935e6b2144835604df3a.tar.bz2
libbu++-bf53de3dfa4db68627f2935e6b2144835604df3a.tar.xz
libbu++-bf53de3dfa4db68627f2935e6b2144835604df3a.zip
Finally added the substream class, and added getByPath (for properties) and
getChildByPath (for groups) to the TafGroup class.
-rw-r--r--src/list.h62
-rw-r--r--src/substream.cpp109
-rw-r--r--src/substream.h63
-rw-r--r--src/tafgroup.cpp37
-rw-r--r--src/tafgroup.h5
-rw-r--r--src/unit/substream.unit52
-rw-r--r--src/unit/taf.unit10
7 files changed, 333 insertions, 5 deletions
diff --git a/src/list.h b/src/list.h
index c587c1a..d8c5a4a 100644
--- a/src/list.h
+++ b/src/list.h
@@ -178,11 +178,11 @@ namespace Bu
178 178
179 /** 179 /**
180 * Linked list template container. This class is similar to the stl list 180 * Linked list template container. This class is similar to the stl list
181 * class except for a few minor changes. First, it doesn't mimic a stack or 181 * class except for a few minor changes. First, when const, all
182 * queue, use the Stack or Queue clasess for that. Second, when const, all 182 * members are only accessable const. Second, erasing a location does not
183 * members are only accessable const. Third, erasing a location does not 183 * invalidate the iterator used, it simply points to the next valid
184 * invalidate the iterator, it simply points to the next valid location, or 184 * location, or end() if there are no more. Other iterators pointing to
185 * end() if there are no more. 185 * the deleted record will, of course, no longer be valid.
186 * 186 *
187 *@param value (typename) The type of data to store in your list 187 *@param value (typename) The type of data to store in your list
188 *@param valuealloc (typename) Memory Allocator for your value type 188 *@param valuealloc (typename) Memory Allocator for your value type
@@ -506,6 +506,32 @@ namespace Bu
506 return *this; 506 return *this;
507 } 507 }
508 508
509 iterator operator+( int iDelta )
510 {
511 iterator ret( *this );
512 for( int j = 0; j < iDelta; j++ )
513 {
514 if( ret.pLink == NULL )
515 throw Bu::ExceptionBase(
516 "Attempt to iterate past begining of list.");
517 ret.pLink = ret.pLink->pNext;
518 }
519 return ret;
520 }
521
522 iterator operator-( int iDelta )
523 {
524 iterator ret( *this );
525 for( int j = 0; j < iDelta; j++ )
526 {
527 if( ret.pLink == NULL )
528 throw Bu::ExceptionBase(
529 "Attempt to iterate past begining of list.");
530 ret.pLink = ret.pLink->pPrev;
531 }
532 return ret;
533 }
534
509 operator bool() 535 operator bool()
510 { 536 {
511 return pLink != NULL; 537 return pLink != NULL;
@@ -619,6 +645,32 @@ namespace Bu
619 return *this; 645 return *this;
620 } 646 }
621 647
648 const_iterator operator+( int iDelta )
649 {
650 const_iterator ret( *this );
651 for( int j = 0; j < iDelta; j++ )
652 {
653 if( ret.pLink == NULL )
654 throw Bu::ExceptionBase(
655 "Attempt to iterate past begining of list.");
656 ret.pLink = ret.pLink->pNext;
657 }
658 return ret;
659 }
660
661 const_iterator operator-( int iDelta )
662 {
663 const_iterator ret( *this );
664 for( int j = 0; j < iDelta; j++ )
665 {
666 if( ret.pLink == NULL )
667 throw Bu::ExceptionBase(
668 "Attempt to iterate past begining of list.");
669 ret.pLink = ret.pLink->pPrev;
670 }
671 return ret;
672 }
673
622 const_iterator &operator=( const iterator &oth ) 674 const_iterator &operator=( const iterator &oth )
623 { 675 {
624 pLink = oth.pLink; 676 pLink = oth.pLink;
diff --git a/src/substream.cpp b/src/substream.cpp
new file mode 100644
index 0000000..ddb31b4
--- /dev/null
+++ b/src/substream.cpp
@@ -0,0 +1,109 @@
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
8#include "bu/substream.h"
9
10Bu::SubStream::SubStream( Bu::Stream &rNext, long iSize ) :
11 Bu::Filter( rNext ),
12 iStart( 0 ),
13 iPos( 0 ),
14 iSize( iSize )
15{
16 iStart = rNext.tell();
17}
18
19Bu::SubStream::~SubStream()
20{
21}
22
23size_t Bu::SubStream::read( void *pBuf, size_t nBytes )
24{
25 if( (long)nBytes > iSize-iPos )
26 nBytes = iSize-iPos;
27 nBytes = rNext.read( pBuf, nBytes );
28 iPos += nBytes;
29 return nBytes;
30}
31
32size_t Bu::SubStream::write( const void *pBuf, size_t nBytes )
33{
34 if( (long)nBytes > iSize-iPos )
35 nBytes = iSize-iPos;
36 nBytes = rNext.write( pBuf, nBytes );
37 iPos += nBytes;
38 return nBytes;
39}
40
41void Bu::SubStream::start()
42{
43 // doesn't mean anything...
44}
45
46size_t Bu::SubStream::stop()
47{
48 // doesn't mean anything...
49 return 0;
50}
51
52void Bu::SubStream::close()
53{
54 // don't do anything? maybe...
55}
56
57long Bu::SubStream::tell()
58{
59 return iPos;
60}
61
62void Bu::SubStream::seek( long offset )
63{
64 if( iPos+offset < 0 )
65 offset = -iPos;
66 else if( iPos+offset > iSize )
67 offset = iSize-iPos;
68 rNext.seek( offset );
69 iPos += offset;
70}
71
72void Bu::SubStream::setPos( long pos )
73{
74 if( pos < 0 )
75 pos = 0;
76 else if( pos > iSize )
77 pos = iSize;
78 iPos = pos;
79 pos += iStart;
80 rNext.setPos( pos );
81}
82
83void Bu::SubStream::setPosEnd( long pos )
84{
85 if( iSize-pos < 0 )
86 pos = 0;
87 else if( iSize-pos > iSize )
88 pos = iSize;
89 else
90 pos = iSize-pos;
91 iPos = pos;
92 rNext.setPos( iStart+pos );
93}
94
95bool Bu::SubStream::isEos()
96{
97 return rNext.isEos() || iPos == iSize;
98}
99
100bool Bu::SubStream::canRead()
101{
102 return rNext.canRead() && (iPos < iSize);
103}
104
105bool Bu::SubStream::canWrite()
106{
107 return rNext.canWrite() && (iPos < iSize);
108}
109
diff --git a/src/substream.h b/src/substream.h
new file mode 100644
index 0000000..5218493
--- /dev/null
+++ b/src/substream.h
@@ -0,0 +1,63 @@
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
8#ifndef BU_SUB_STREAM_H
9#define BU_SUB_STREAM_H
10
11#include "bu/filter.h"
12
13namespace Bu
14{
15 /**
16 * Creates a sub-stream of a given stream. This allows you to read and
17 * write safely to a section of another stream, keeping all data within
18 * the given bounds. The substream acts exactly like a top level stream
19 * when you reach the bounds of either the containing stream or the
20 * artificial bounds of the substream, except that unlike many stream types,
21 * when writing you cannot move beyond the bounds of the substream. Reads,
22 * on the other hand, work exactly the same way, returning less data than
23 * requested when the end of the stream is reached.
24 *
25 * The substream always begins at the current position in the base stream,
26 * if you would like to skip some data first, simply seek.
27 *
28 * The substream class is safe to use with all blocking and non-blocking
29 * base streams, including sockets, however it can have unpredictable
30 * results when used on a buffering stream that may read more data than
31 * requested in order to complete a request such as the buffer or bzip2
32 * filters.
33 */
34 class SubStream : public Bu::Filter
35 {
36 public:
37 SubStream( Bu::Stream &rNext, long iSize );
38 virtual ~SubStream();
39
40 virtual size_t read( void *pBuf, size_t nBytes );
41 virtual size_t write( const void *pBuf, size_t nBytes );
42 using Bu::Stream::write;
43
44 virtual void start();
45 virtual size_t stop();
46 virtual void close();
47 virtual long tell();
48 virtual void seek( long offset );
49 virtual void setPos( long pos );
50 virtual void setPosEnd( long pos );
51 virtual bool isEos();
52
53 virtual bool canRead();
54 virtual bool canWrite();
55
56 protected:
57 long iStart;
58 long iPos;
59 long iSize;
60 };
61};
62
63#endif
diff --git a/src/tafgroup.cpp b/src/tafgroup.cpp
index 1837bd8..9440912 100644
--- a/src/tafgroup.cpp
+++ b/src/tafgroup.cpp
@@ -162,3 +162,40 @@ const Bu::FString &Bu::TafGroup::getProperty( const Bu::FString &sName,
162 } 162 }
163} 163}
164 164
165const Bu::TafGroup *Bu::TafGroup::getChildByPath(
166 const Bu::FString &sPath ) const
167{
168 return getChildByPath( sPath.split('/') );
169}
170
171const Bu::TafGroup *Bu::TafGroup::getChildByPath( Bu::StrList lPath ) const
172{
173 const Bu::TafGroup *cur = this;
174
175 for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ )
176 {
177 cur = cur->getChild( *i );
178 }
179
180 return cur;
181}
182
183const Bu::FString &Bu::TafGroup::getByPath( const Bu::FString &sPath ) const
184{
185 return getByPath( sPath.split('/') );
186}
187
188const Bu::FString &Bu::TafGroup::getByPath( Bu::StrList lPath ) const
189{
190 const Bu::TafGroup *cur = this;
191
192 for( Bu::StrList::const_iterator i = lPath.begin(); i; i++ )
193 {
194 if( !(i+1) )
195 break;
196 cur = cur->getChild( *i );
197 }
198
199 return cur->getProperty( lPath.last() );
200}
201
diff --git a/src/tafgroup.h b/src/tafgroup.h
index 6a50d11..f2df669 100644
--- a/src/tafgroup.h
+++ b/src/tafgroup.h
@@ -16,6 +16,7 @@
16 16
17namespace Bu 17namespace Bu
18{ 18{
19 typedef Bu::List<Bu::FString> StrList;
19 class TafProperty; 20 class TafProperty;
20 class TafComment; 21 class TafComment;
21 /** 22 /**
@@ -53,6 +54,10 @@ namespace Bu
53 TafProperty *addProperty( 54 TafProperty *addProperty(
54 const Bu::FString &sName, const Bu::FString &sValue ); 55 const Bu::FString &sName, const Bu::FString &sValue );
55 const NodeList &getChildren() const; 56 const NodeList &getChildren() const;
57 const TafGroup *getChildByPath( const Bu::FString &sPath ) const;
58 const TafGroup *getChildByPath( StrList lPath ) const;
59 const Bu::FString &getByPath( const Bu::FString &sPath ) const;
60 const Bu::FString &getByPath( StrList lPath ) const;
56 61
57 private: 62 private:
58 Bu::FString sName; 63 Bu::FString sName;
diff --git a/src/unit/substream.unit b/src/unit/substream.unit
new file mode 100644
index 0000000..ef6c70b
--- /dev/null
+++ b/src/unit/substream.unit
@@ -0,0 +1,52 @@
1// vim: syntax=cpp
2/*
3 * Copyright (C) 2007-2008 Xagasoft, All rights reserved.
4 *
5 * This file is part of the libbu++ library and is released under the
6 * terms of the license contained in the file LICENSE.
7 */
8
9#include "bu/membuf.h"
10#include "bu/substream.h"
11
12{=Init}
13
14{%testRead01}
15{
16 Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz");
17 mb.seek( 4 );
18 Bu::SubStream ss( mb, 10 );
19 unitTest( ss.readLine() == "efghijklmn" );
20}
21
22{%testRead02}
23{
24 Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz");
25 mb.seek( 4 );
26 Bu::SubStream ss( mb, 10 );
27 char buf[8];
28 size_t iRead = ss.read( buf, 8 );
29 unitTest( iRead == 8 );
30 unitTest( strncmp( buf, "efghijkl", 8 ) == 0 );
31 unitTest( !ss.isEos() );
32 iRead = ss.read( buf, 8 );
33 unitTest( iRead == 2 );
34 unitTest( strncmp( buf, "mn", 2 ) == 0 );
35 unitTest( ss.isEos() );
36}
37
38{%testRead03}
39{
40 Bu::MemBuf mb("abcdefghijklmnopqrstuvwxyz");
41 mb.seek( 20 );
42 Bu::SubStream ss( mb, 10 );
43 char buf[8];
44 size_t iRead = ss.read( buf, 8 );
45 unitTest( iRead == 6 );
46 unitTest( strncmp( buf, "uvwxyz", 6 ) == 0 );
47 unitTest( ss.isEos() );
48 iRead = ss.read( buf, 8 );
49 unitTest( iRead == 0 );
50 unitTest( ss.isEos() );
51}
52
diff --git a/src/unit/taf.unit b/src/unit/taf.unit
index eeddd53..a9329fe 100644
--- a/src/unit/taf.unit
+++ b/src/unit/taf.unit
@@ -109,3 +109,13 @@
109 // Woot 109 // Woot
110 } 110 }
111} 111}
112
113{%bypath1}
114{
115 Bu::MemBuf mb("{outer: \"Hello=\" {inner: {final: test=hi} } }");
116 Bu::TafReader tr( mb );
117 const Bu::TafGroup *g = tr.readGroup();
118 unitTest( g->getChildByPath("inner/final")->getProperty("test") == "hi" );
119 unitTest( g->getByPath("inner/final/test") == "hi" );
120}
121