aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.h1
-rw-r--r--src/config.h2
-rw-r--r--src/extratypes.h17
-rw-r--r--src/membuf.cpp18
-rw-r--r--src/membuf.h17
-rw-r--r--src/stdstream.cpp14
-rw-r--r--src/stdstream.h14
-rw-r--r--src/stream.cpp2
-rw-r--r--src/stream.h42
-rw-r--r--src/tcpsocket.cpp40
-rw-r--r--src/tcpsocket.h23
11 files changed, 128 insertions, 62 deletions
diff --git a/src/client.h b/src/client.h
index 096df2f..98b31f7 100644
--- a/src/client.h
+++ b/src/client.h
@@ -10,6 +10,7 @@
10 10
11#include <stdint.h> 11#include <stdint.h>
12 12
13#include "bu/config.h"
13#include "bu/fstring.h" 14#include "bu/fstring.h"
14#include "bu/queuebuf.h" 15#include "bu/queuebuf.h"
15 16
diff --git a/src/config.h b/src/config.h
index ad4991e..3a19a1f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -15,4 +15,6 @@
15#include "bu/compat/osx.h" 15#include "bu/compat/osx.h"
16#include "bu/compat/linux.h" 16#include "bu/compat/linux.h"
17 17
18#include "bu/extratypes.h"
19
18#endif 20#endif
diff --git a/src/extratypes.h b/src/extratypes.h
new file mode 100644
index 0000000..bc32dcd
--- /dev/null
+++ b/src/extratypes.h
@@ -0,0 +1,17 @@
1#ifndef EXTRA_TYPES_H
2#define EXTRA_TYPES_H
3
4#include "bu/config.h"
5
6namespace Bu
7{
8#ifdef USE_64BIT_IO
9 typedef int64_t size;
10 typedef uint64_t usize;
11#else
12 typedef int32_t size;
13 typedef uint32_t usize;
14#endif
15};
16
17#endif
diff --git a/src/membuf.cpp b/src/membuf.cpp
index b822641..1a6bf9a 100644
--- a/src/membuf.cpp
+++ b/src/membuf.cpp
@@ -28,9 +28,9 @@ void Bu::MemBuf::close()
28{ 28{
29} 29}
30 30
31size_t Bu::MemBuf::read( void *pBuf, size_t nBytes ) 31size Bu::MemBuf::read( void *pBuf, size nBytes )
32{ 32{
33 if( (size_t)sBuf.getSize()-(size_t)nPos < nBytes ) 33 if( (size)sBuf.getSize()-(size)nPos < nBytes )
34 nBytes = sBuf.getSize()-nPos; 34 nBytes = sBuf.getSize()-nPos;
35 35
36 memcpy( pBuf, sBuf.getStr()+nPos, nBytes ); 36 memcpy( pBuf, sBuf.getStr()+nPos, nBytes );
@@ -39,7 +39,7 @@ size_t Bu::MemBuf::read( void *pBuf, size_t nBytes )
39 return nBytes; 39 return nBytes;
40} 40}
41 41
42size_t Bu::MemBuf::write( const void *pBuf, size_t nBytes ) 42size Bu::MemBuf::write( const void *pBuf, size nBytes )
43{ 43{
44 if( nPos == sBuf.getSize() ) 44 if( nPos == sBuf.getSize() )
45 { 45 {
@@ -52,7 +52,7 @@ size_t Bu::MemBuf::write( const void *pBuf, size_t nBytes )
52 { 52 {
53 // Trickier, we must do this in two parts, overwrite, then append 53 // Trickier, we must do this in two parts, overwrite, then append
54 // Frist, overwrite. 54 // Frist, overwrite.
55 size_t iOver = sBuf.getSize() - nPos; 55 size iOver = sBuf.getSize() - nPos;
56 if( iOver > nBytes ) 56 if( iOver > nBytes )
57 iOver = nBytes; 57 iOver = nBytes;
58 memcpy( sBuf.getStr()+nPos, pBuf, iOver ); 58 memcpy( sBuf.getStr()+nPos, pBuf, iOver );
@@ -66,26 +66,26 @@ size_t Bu::MemBuf::write( const void *pBuf, size_t nBytes )
66 } 66 }
67} 67}
68 68
69long Bu::MemBuf::tell() 69size Bu::MemBuf::tell()
70{ 70{
71 return nPos; 71 return nPos;
72} 72}
73 73
74void Bu::MemBuf::seek( long offset ) 74void Bu::MemBuf::seek( size offset )
75{ 75{
76 nPos += offset; 76 nPos += offset;
77 if( nPos < 0 ) nPos = 0; 77 if( nPos < 0 ) nPos = 0;
78 else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); 78 else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize();
79} 79}
80 80
81void Bu::MemBuf::setPos( long pos ) 81void Bu::MemBuf::setPos( size pos )
82{ 82{
83 nPos = pos; 83 nPos = pos;
84 if( nPos < 0 ) nPos = 0; 84 if( nPos < 0 ) nPos = 0;
85 else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize(); 85 else if( nPos > sBuf.getSize() ) nPos = sBuf.getSize();
86} 86}
87 87
88void Bu::MemBuf::setPosEnd( long pos ) 88void Bu::MemBuf::setPosEnd( size pos )
89{ 89{
90 nPos = sBuf.getSize()-pos; 90 nPos = sBuf.getSize()-pos;
91 if( nPos < 0 ) nPos = 0; 91 if( nPos < 0 ) nPos = 0;
@@ -140,7 +140,7 @@ void Bu::MemBuf::setBlocking( bool )
140{ 140{
141} 141}
142 142
143void Bu::MemBuf::setSize( long iSize ) 143void Bu::MemBuf::setSize( size iSize )
144{ 144{
145 if( iSize < 0 ) 145 if( iSize < 0 )
146 iSize = 0; 146 iSize = 0;
diff --git a/src/membuf.h b/src/membuf.h
index 9e406c1..a75aca1 100644
--- a/src/membuf.h
+++ b/src/membuf.h
@@ -10,6 +10,7 @@
10 10
11#include <stdint.h> 11#include <stdint.h>
12 12
13#include "bu/config.h"
13#include "bu/stream.h" 14#include "bu/stream.h"
14#include "bu/fstring.h" 15#include "bu/fstring.h"
15 16
@@ -27,14 +28,14 @@ namespace Bu
27 virtual ~MemBuf(); 28 virtual ~MemBuf();
28 29
29 virtual void close(); 30 virtual void close();
30 virtual size_t read( void *pBuf, size_t nBytes ); 31 virtual size read( void *pBuf, size iBytes );
31 32
32 virtual size_t write( const void *pBuf, size_t nBytes ); 33 virtual size write( const void *pBuf, size iBytes );
33 using Stream::write; 34 using Stream::write;
34 virtual long tell(); 35 virtual size tell();
35 virtual void seek( long offset ); 36 virtual void seek( size offset );
36 virtual void setPos( long pos ); 37 virtual void setPos( size pos );
37 virtual void setPosEnd( long pos ); 38 virtual void setPosEnd( size pos );
38 virtual bool isEos(); 39 virtual bool isEos();
39 virtual bool isOpen(); 40 virtual bool isOpen();
40 virtual void flush(); 41 virtual void flush();
@@ -45,14 +46,14 @@ namespace Bu
45 virtual bool isSeekable(); 46 virtual bool isSeekable();
46 virtual bool isBlocking(); 47 virtual bool isBlocking();
47 virtual void setBlocking( bool bBlocking=true ); 48 virtual void setBlocking( bool bBlocking=true );
48 virtual void setSize( long iSize ); 49 virtual void setSize( size iSize );
49 50
50 Bu::FString &getString(); 51 Bu::FString &getString();
51 void setString( const Bu::FString &sNewData ); 52 void setString( const Bu::FString &sNewData );
52 53
53 private: 54 private:
54 Bu::FString sBuf; 55 Bu::FString sBuf;
55 long nPos; 56 size nPos;
56 }; 57 };
57} 58}
58 59
diff --git a/src/stdstream.cpp b/src/stdstream.cpp
index 32ddec4..64ca1cd 100644
--- a/src/stdstream.cpp
+++ b/src/stdstream.cpp
@@ -20,30 +20,30 @@ void Bu::StdStream::close()
20{ 20{
21} 21}
22 22
23size_t Bu::StdStream::read( void *pBuf, size_t nBytes ) 23Bu::size Bu::StdStream::read( void *pBuf, Bu::size nBytes )
24{ 24{
25 return fread( pBuf, 1, nBytes, stdin ); 25 return fread( pBuf, 1, nBytes, stdin );
26} 26}
27 27
28size_t Bu::StdStream::write( const void *pBuf, size_t nBytes ) 28Bu::size Bu::StdStream::write( const void *pBuf, Bu::size nBytes )
29{ 29{
30 return fwrite( pBuf, 1, nBytes, stdout ); 30 return fwrite( pBuf, 1, nBytes, stdout );
31} 31}
32 32
33long Bu::StdStream::tell() 33Bu::size Bu::StdStream::tell()
34{ 34{
35 return 0; 35 return 0;
36} 36}
37 37
38void Bu::StdStream::seek( long ) 38void Bu::StdStream::seek( Bu::size )
39{ 39{
40} 40}
41 41
42void Bu::StdStream::setPos( long ) 42void Bu::StdStream::setPos( Bu::size )
43{ 43{
44} 44}
45 45
46void Bu::StdStream::setPosEnd( long ) 46void Bu::StdStream::setPosEnd( Bu::size )
47{ 47{
48} 48}
49 49
@@ -96,7 +96,7 @@ void Bu::StdStream::setBlocking( bool )
96{ 96{
97} 97}
98 98
99void Bu::StdStream::setSize( long ) 99void Bu::StdStream::setSize( Bu::size )
100{ 100{
101} 101}
102 102
diff --git a/src/stdstream.h b/src/stdstream.h
index 4efeece..c500dfc 100644
--- a/src/stdstream.h
+++ b/src/stdstream.h
@@ -23,13 +23,13 @@ namespace Bu
23 virtual ~StdStream(); 23 virtual ~StdStream();
24 24
25 virtual void close(); 25 virtual void close();
26 virtual size_t read( void *pBuf, size_t nBytes ); 26 virtual size read( void *pBuf, size nBytes );
27 virtual size_t write( const void *pBuf, size_t nBytes ); 27 virtual size write( const void *pBuf, size nBytes );
28 using Stream::write; 28 using Stream::write;
29 virtual long tell(); 29 virtual size tell();
30 virtual void seek( long offset ); 30 virtual void seek( size offset );
31 virtual void setPos( long pos ); 31 virtual void setPos( size pos );
32 virtual void setPosEnd( long pos ); 32 virtual void setPosEnd( size pos );
33 virtual bool isEos(); 33 virtual bool isEos();
34 virtual bool isOpen(); 34 virtual bool isOpen();
35 virtual void flush(); 35 virtual void flush();
@@ -40,7 +40,7 @@ namespace Bu
40 virtual bool isSeekable(); 40 virtual bool isSeekable();
41 virtual bool isBlocking(); 41 virtual bool isBlocking();
42 virtual void setBlocking( bool bBlocking=true ); 42 virtual void setBlocking( bool bBlocking=true );
43 virtual void setSize( long iSize ); 43 virtual void setSize( size iSize );
44 }; 44 };
45} 45}
46 46
diff --git a/src/stream.cpp b/src/stream.cpp
index 0e05cad..f13d33a 100644
--- a/src/stream.cpp
+++ b/src/stream.cpp
@@ -30,7 +30,7 @@ Bu::FString Bu::Stream::readLine()
30 } 30 }
31} 31}
32 32
33size_t Bu::Stream::write( const Bu::FString &sBuf ) 33Bu::size Bu::Stream::write( const Bu::FString &sBuf )
34{ 34{
35 return write( sBuf.getStr(), sBuf.getSize() ); 35 return write( sBuf.getStr(), sBuf.getSize() );
36} 36}
diff --git a/src/stream.h b/src/stream.h
index 0ea5560..e7db7af 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -8,6 +8,8 @@
8#ifndef BU_STREAM_H 8#ifndef BU_STREAM_H
9#define BU_STREAM_H 9#define BU_STREAM_H
10 10
11#include "bu/config.h"
12
11#include <stdint.h> 13#include <stdint.h>
12#include <stdio.h> 14#include <stdio.h>
13 15
@@ -43,7 +45,7 @@ namespace Bu
43 *@param nBytes (size_t) Max data to read. 45 *@param nBytes (size_t) Max data to read.
44 *@returns (size_t) Amount of data read. 46 *@returns (size_t) Amount of data read.
45 */ 47 */
46 virtual size_t read( void *pBuf, size_t nBytes ) = 0; 48 virtual size read( void *pBuf, size iBytes ) = 0;
47 49
48 /** 50 /**
49 * Attempts to read a complete line from the stream. This will stop 51 * Attempts to read a complete line from the stream. This will stop
@@ -59,33 +61,33 @@ namespace Bu
59 *@param nBytes (size_t) Amount of data to write from pBuf. 61 *@param nBytes (size_t) Amount of data to write from pBuf.
60 *@returns (size_t) Amount of data actually written. 62 *@returns (size_t) Amount of data actually written.
61 */ 63 */
62 virtual size_t write( const void *pBuf, size_t nBytes ) = 0; 64 virtual size write( const void *pBuf, size iBytes ) = 0;
63 65
64 virtual size_t write( const Bu::FString &sBuf ); 66 virtual size write( const Bu::FString &sBuf );
65 67
66 /** 68 /**
67 * Get the current position in the stream. 69 * Get the current position in the stream.
68 *@returns (long) The current position in the stream. 70 *@returns (long) The current position in the stream.
69 */ 71 */
70 virtual long tell() = 0; 72 virtual size tell() = 0;
71 73
72 /** 74 /**
73 * Seek to a position in the stream relative to the current position. 75 * Seek to a position in the stream relative to the current position.
74 *@param offset (long) Offset from current position to seek to. 76 *@param offset (long) Offset from current position to seek to.
75 */ 77 */
76 virtual void seek( long offset ) = 0; 78 virtual void seek( size offset ) = 0;
77 79
78 /** 80 /**
79 * Set position in the stream relative to the start of the stream. 81 * Set position in the stream relative to the start of the stream.
80 *@param pos (long) The position. 82 *@param pos (long) The position.
81 */ 83 */
82 virtual void setPos( long pos ) = 0; 84 virtual void setPos( size pos ) = 0;
83 85
84 /** 86 /**
85 * Set position in the stream relative to the end of the stream. 87 * Set position in the stream relative to the end of the stream.
86 *@param pos (long) The position. 88 *@param pos (long) The position.
87 */ 89 */
88 virtual void setPosEnd( long pos ) = 0; 90 virtual void setPosEnd( size pos ) = 0;
89 91
90 /** 92 /**
91 * Are we at the end of the stream? 93 * Are we at the end of the stream?
@@ -158,10 +160,32 @@ namespace Bu
158 * removed from the end of the stream, but the content of the added 160 * removed from the end of the stream, but the content of the added
159 * data is undefined. 161 * data is undefined.
160 */ 162 */
161 virtual void setSize( long iSize ) = 0; 163 virtual void setSize( size iSize ) = 0;
164
165 /**
166 * Returns the size of the stream if the stream can have a size. For
167 * streams that do not (sockets, pipes, etc.) this should throw an
168 * unsupported exception.
169 */
170 virtual size getSize() const = 0;
162 171
163 public: // Filters 172 /**
173 * Returns the block-size of the stream, if it has one. This should
174 * throw an unsupported exception. In some cases the block size
175 * returned will not represent quite the same thing, for example,
176 * sockets will return their MTU, while files will return the
177 * filesystem's block size, and memory buffers will throw an exception.
178 */
179 virtual size getBlockSize() const = 0;
164 180
181 /**
182 * If possible, this returns a string that can be used to describe how
183 * to access the open stream. Not all streams support this, such as
184 * MemBuf, but for files it may give you a path to a file, for a socket
185 * it may give you an ip address, etc. If it isn't supported, an empty
186 * string may be returned.
187 */
188 virtual Bu::FString getLocation() const = 0;
165 189
166 private: 190 private:
167 191
diff --git a/src/tcpsocket.cpp b/src/tcpsocket.cpp
index bbd9cf5..22acdf7 100644
--- a/src/tcpsocket.cpp
+++ b/src/tcpsocket.cpp
@@ -149,7 +149,7 @@ void Bu::TcpSocket::close()
149 bActive = false; 149 bActive = false;
150} 150}
151 151
152size_t Bu::TcpSocket::read( void *pBuf, size_t nBytes ) 152Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes )
153{ 153{
154 fd_set rfds; 154 fd_set rfds;
155 FD_ZERO(&rfds); 155 FD_ZERO(&rfds);
@@ -195,11 +195,11 @@ size_t Bu::TcpSocket::read( void *pBuf, size_t nBytes )
195 return 0; 195 return 0;
196} 196}
197 197
198size_t Bu::TcpSocket::read( void *pBuf, size_t nBytes, 198Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes,
199 uint32_t nSec, uint32_t nUSec ) 199 uint32_t nSec, uint32_t nUSec )
200{ 200{
201 struct timeval tv; 201 struct timeval tv;
202 size_t nRead = 0; 202 Bu::size nRead = 0;
203 203
204 fd_set rfds; 204 fd_set rfds;
205 FD_ZERO(&rfds); 205 FD_ZERO(&rfds);
@@ -239,7 +239,7 @@ size_t Bu::TcpSocket::read( void *pBuf, size_t nBytes,
239 return nRead; 239 return nRead;
240} 240}
241 241
242size_t Bu::TcpSocket::write( const void *pBuf, size_t nBytes ) 242Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes )
243{ 243{
244//#ifdef WIN32 244//#ifdef WIN32
245 int nWrote = TEMP_FAILURE_RETRY( 245 int nWrote = TEMP_FAILURE_RETRY(
@@ -261,10 +261,10 @@ size_t Bu::TcpSocket::write( const void *pBuf, size_t nBytes )
261 return nWrote; 261 return nWrote;
262} 262}
263 263
264size_t Bu::TcpSocket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uint32_t nUSec ) 264Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec )
265{ 265{
266 struct timeval tv; 266 struct timeval tv;
267 size_t nWrote = 0; 267 Bu::size nWrote = 0;
268 268
269 fd_set wfds; 269 fd_set wfds;
270 FD_ZERO(&wfds); 270 FD_ZERO(&wfds);
@@ -304,22 +304,22 @@ size_t Bu::TcpSocket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uin
304 return nWrote; 304 return nWrote;
305} 305}
306 306
307long Bu::TcpSocket::tell() 307Bu::size Bu::TcpSocket::tell()
308{ 308{
309 throw UnsupportedException(); 309 throw UnsupportedException();
310} 310}
311 311
312void Bu::TcpSocket::seek( long ) 312void Bu::TcpSocket::seek( Bu::size )
313{ 313{
314 throw UnsupportedException(); 314 throw UnsupportedException();
315} 315}
316 316
317void Bu::TcpSocket::setPos( long ) 317void Bu::TcpSocket::setPos( Bu::size )
318{ 318{
319 throw UnsupportedException(); 319 throw UnsupportedException();
320} 320}
321 321
322void Bu::TcpSocket::setPosEnd( long ) 322void Bu::TcpSocket::setPosEnd( Bu::size )
323{ 323{
324 throw UnsupportedException(); 324 throw UnsupportedException();
325} 325}
@@ -401,7 +401,7 @@ void Bu::TcpSocket::setBlocking( bool bBlocking )
401 fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); 401 fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK );
402 } 402 }
403#else 403#else
404 u_long iMode; 404 u_Bu::size iMode;
405 if( bBlocking ) 405 if( bBlocking )
406 iMode = 0; 406 iMode = 0;
407 else 407 else
@@ -416,7 +416,7 @@ void Bu::TcpSocket::setBlocking( bool bBlocking )
416#endif 416#endif
417} 417}
418 418
419void Bu::TcpSocket::setSize( long ) 419void Bu::TcpSocket::setSize( Bu::size )
420{ 420{
421} 421}
422 422
@@ -436,6 +436,8 @@ void Bu::TcpSocket::setAddress()
436 addr.sin_family = AF_INET; 436 addr.sin_family = AF_INET;
437 bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); 437 bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len );
438 sAddress = bu_inet_ntoa( addr.sin_addr ); 438 sAddress = bu_inet_ntoa( addr.sin_addr );
439
440 printf("%d\n", IP_MTU );
439} 441}
440 442
441Bu::FString Bu::TcpSocket::getAddress() const 443Bu::FString Bu::TcpSocket::getAddress() const
@@ -448,3 +450,17 @@ Bu::TcpSocket::operator int() const
448 return nTcpSocket; 450 return nTcpSocket;
449} 451}
450 452
453Bu::size Bu::TcpSocket::getSize() const
454{
455 throw UnsupportedException();
456}
457
458Bu::size Bu::TcpSocket::getBlockSize() const
459{
460
461}
462
463Bu::FString Bu::TcpSocket::getLocation() const
464{
465}
466
diff --git a/src/tcpsocket.h b/src/tcpsocket.h
index 3361e84..8543ad0 100644
--- a/src/tcpsocket.h
+++ b/src/tcpsocket.h
@@ -10,6 +10,7 @@
10 10
11#include <stdint.h> 11#include <stdint.h>
12 12
13#include "bu/config.h"
13#include "bu/stream.h" 14#include "bu/stream.h"
14#include "bu/fstring.h" 15#include "bu/fstring.h"
15#include "bu/exceptionbase.h" 16#include "bu/exceptionbase.h"
@@ -66,18 +67,18 @@ namespace Bu
66 67
67 virtual void close(); 68 virtual void close();
68 //virtual void read(); 69 //virtual void read();
69 virtual size_t read( void *pBuf, size_t nBytes ); 70 virtual size read( void *pBuf, size nBytes );
70 virtual size_t read( void *pBuf, size_t nBytes, 71 virtual size read( void *pBuf, size nBytes,
71 uint32_t nSec, uint32_t nUSec=0 ); 72 uint32_t nSec, uint32_t nUSec=0 );
72 virtual size_t write( const void *pBuf, size_t nBytes ); 73 virtual size write( const void *pBuf, size nBytes );
73 virtual size_t write( const void *pBuf, size_t nBytes, 74 virtual size write( const void *pBuf, size nBytes,
74 uint32_t nSec, uint32_t nUSec=0 ); 75 uint32_t nSec, uint32_t nUSec=0 );
75 using Stream::write; 76 using Stream::write;
76 77
77 virtual long tell(); 78 virtual size tell();
78 virtual void seek( long offset ); 79 virtual void seek( size offset );
79 virtual void setPos( long pos ); 80 virtual void setPos( size pos );
80 virtual void setPosEnd( long pos ); 81 virtual void setPosEnd( size pos );
81 virtual bool isEos(); 82 virtual bool isEos();
82 virtual bool isOpen(); 83 virtual bool isOpen();
83 84
@@ -93,11 +94,15 @@ namespace Bu
93 virtual bool isBlocking(); 94 virtual bool isBlocking();
94 virtual void setBlocking( bool bBlocking=true ); 95 virtual void setBlocking( bool bBlocking=true );
95 96
96 virtual void setSize( long iSize ); 97 virtual void setSize( size iSize );
97 98
98 Bu::FString getAddress() const; 99 Bu::FString getAddress() const;
99 operator int() const; 100 operator int() const;
100 101
102 virtual size getSize() const;
103 virtual size getBlockSize() const;
104 virtual Bu::FString getLocation() const;
105
101 private: 106 private:
102 void setAddress(); 107 void setAddress();
103 108