Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #6599 > unrolled thread
| Started by | jakash3 <jakashthree@gmail.com> |
|---|---|
| First post | 2011-06-10 19:54 -0700 |
| Last post | 2011-06-12 14:43 +0000 |
| Articles | 8 — 4 participants |
Back to article view | Back to comp.lang.c++
I/O abstract class suggestions jakash3 <jakashthree@gmail.com> - 2011-06-10 19:54 -0700
Re: I/O abstract class suggestions Ian Collins <ian-news@hotmail.com> - 2011-06-11 14:59 +1200
Re: I/O abstract class suggestions jakash3 <jakashthree@gmail.com> - 2011-06-10 20:03 -0700
Re: I/O abstract class suggestions Ian Collins <ian-news@hotmail.com> - 2011-06-11 16:04 +1200
Re: I/O abstract class suggestions Paavo Helde <myfirstname@osa.pri.ee> - 2011-06-11 04:06 -0500
Re: I/O abstract class suggestions jakash3 <jakashthree@gmail.com> - 2011-06-11 12:35 -0700
Re: I/O abstract class suggestions Paavo Helde <myfirstname@osa.pri.ee> - 2011-06-18 06:35 -0500
Re: I/O abstract class suggestions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-06-12 14:43 +0000
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-06-10 19:54 -0700 |
| Subject | I/O abstract class suggestions |
| Message-ID | <4e58c83a-eefa-4231-8e7d-506632e14a5f@f31g2000pri.googlegroups.com> |
I've made In and Out abstract base classes which I plan to have File,
Socket, and Console classes base some of their methods on. These
interfaces will have method names like those from the C library as
well as formatted insertion and extraction streams. Please give
feedback and suggestions on how I can add to or improve this
interface.
class In {
public:
virtual int getc() = 0;
virtual char* gets(char* s, int size) = 0;
virtual int scanf(const char* format, ...) = 0;
virtual size_t read(void* ptr, size_t size, size_t nmemb) = 0;
virtual In& operator>> (bool& val) = 0;
virtual In& operator>> (short& val) = 0;
virtual In& operator>> (unsigned short& val) = 0;
virtual In& operator>> (int& val) = 0;
virtual In& operator>> (unsigned int& val) = 0;
virtual In& operator>> (long& val) = 0;
virtual In& operator>> (unsigned long& val) = 0;
virtual In& operator>> (float& val) = 0;
virtual In& operator>> (double& val) = 0;
virtual In& operator>> (long double& val) = 0;
virtual In& operator>> (const void*& val) = 0;
virtual In& operator>> (char& c) = 0;
virtual In& operator>> (signed char& c) = 0;
virtual In& operator>> (unsigned char& c) = 0;
virtual In& operator>> (char*& s) = 0;
virtual In& operator>> (String& s) = 0;
virtual In& operator>> (Charp& s) = 0;
};
class Out {
public:
virtual int putc(int c) = 0;
virtual int puts(const char* s) = 0;
virtual int printf(const char* format, ...) = 0;
virtual size_t write(const void* ptr, size_t size, size_t nmemb) = 0;
virtual Out& operator<< (bool val) = 0;
virtual Out& operator<< (short val) = 0;
virtual Out& operator<< (unsigned short val) = 0;
virtual Out& operator<< (int val) = 0;
virtual Out& operator<< (unsigned int val) = 0;
virtual Out& operator<< (long val) = 0;
virtual Out& operator<< (unsigned long val) = 0;
virtual Out& operator<< (float val) = 0;
virtual Out& operator<< (double val) = 0;
virtual Out& operator<< (long double val) = 0;
virtual Out& operator<< (const void* val) = 0;
virtual Out& operator<< (char c) = 0;
virtual Out& operator<< (signed char c) = 0;
virtual Out& operator<< (unsigned char c) = 0;
virtual Out& operator<< (const char* s) = 0;
virtual Out& operator<< (String s) = 0;
virtual Out& operator<< (Charp s) = 0;
};
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-06-11 14:59 +1200 |
| Message-ID | <95g402FnkjU2@mid.individual.net> |
| In reply to | #6599 |
On 06/11/11 02:54 PM, jakash3 wrote: > I've made In and Out abstract base classes which I plan to have File, > Socket, and Console classes base some of their methods on. These > interfaces will have method names like those from the C library as > well as formatted insertion and extraction streams. Please give > feedback and suggestions on how I can add to or improve this > interface. Why don't you keen the standard iostream objects and create specialised streambuf objects? The streambuf is where the low level, device specific IO operations are located. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-06-10 20:03 -0700 |
| Message-ID | <2bf4596b-162a-492d-b5e9-77c5fc528cb5@e17g2000prj.googlegroups.com> |
| In reply to | #6600 |
On Jun 10, 7:59 pm, Ian Collins <ian-n...@hotmail.com> wrote: > Why don't you keen the standard iostream objects and create specialised > streambuf objects? The streambuf is where the low level, device > specific IO operations are located. > > -- > Ian Collins You may have a good point, but I'm not very familiar with the C++ library. Well, I guess you could say that I like to reinvent the wheel.
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-06-11 16:04 +1200 |
| Message-ID | <95g7qdFnkjU3@mid.individual.net> |
| In reply to | #6601 |
On 06/11/11 03:03 PM, jakash3 wrote: > On Jun 10, 7:59 pm, Ian Collins<ian-n...@hotmail.com> wrote: > >> Why don't you keen the standard iostream objects and create specialised >> streambuf objects? The streambuf is where the low level, device >> specific IO operations are located. > > You may have a good point, but I'm not very familiar with the C++ > library. Well, I guess you could say that I like to reinvent the > wheel. The streambuf is designed to be derived from, it has appropriate virtual methods (underflow, overflow and sync give you most of what's needed) to support specialisation. Implementing a streambuf to read from a file descriptor is a great learning exercise. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-06-11 04:06 -0500 |
| Message-ID | <Xns9F017B2CC7C3Bmyfirstnameosapriee@216.196.109.131> |
| In reply to | #6599 |
jakash3 <jakashthree@gmail.com> wrote in
news:4e58c83a-eefa-4231-8e7d-506632e14a5f@f31g2000pri.googlegroups.com:
> I've made In and Out abstract base classes which I plan to have File,
> Socket, and Console classes base some of their methods on. These
> interfaces will have method names like those from the C library as
> well as formatted insertion and extraction streams. Please give
> feedback and suggestions on how I can add to or improve this
> interface.
Let's assume you seriously want to reinvent the wheel and create your own
replacement for std::istream/std::ostream facility. See also boost.format
library for conversions and formatting.
There are several facets to this task:
- transportation of bits from/to different places (like socket, memory-
mapped file, etc.)
- converting the data to/from C++ variables
- formatting the data in the external file
- adjustments of formatting according to locale settings
- for text I/O, the charset choice (Unicode, ISO-Latin-1 etc).
- for text I/O, the encoding of the charset (UTF-8, UTF-16, UTF-32
etc).
All these tasks are to some extent orthogonal and should ideally be
expressed by some orthogonal means. The std::*stream facility uses run-
time polymorphism (mostly virtual functions in the streambuf classes) for
the first, static polymorphism (overloads and templates) for the second,
and special manipulator objects for the third. The C printf/scanf
interface brings the converting and formatting aspects more closely
together in the same format codes. For both, locale settings are
controlled by separate functions working 'behind the scenes'. Charset and
encoding are a mess and provided by a mix of locale and templating
(wchar_t vs. char etc). One can certainly do better than the current
std:: solution, but I'm afraid this is not an easy task.
Now let's see how this all works with your proposed interface:
- it is not consistent in that it provides raw I/O (read, getc) in the
same footing to formatted I/O functions. IMO it would be better to have
this functionality in separate classes.
- if you plan to use inheritance for supporting different I/O sources,
then the formatted I/O functions should most probably remain the same, so
they should not be virtual. Probably they should be templated instead.
- the ellipsis style functions (printf, scanf) are not type-safe and
can cause lots of problems at run-time. In C++ one can do much better,
see e.g. boost.format library.
- there are no means of controlling the exact formatting (e.g. printing
an integer in hexadecimal or octal notation). The std::stream
manipulators are not a very good solution as their scope is not really
expressed in the source code. The printf-style format codes are better in
that sense, but are harder to make type-safe.
- there are no means of controlling the locale-specific behavior. IMO
it should be explicit in the interface, too bad that it is hidden in the
interface.
- charsets and their encoding are not even touched, as far as I can
see.
- for C-style functions there are specific C-style deficiences, see
below:
> class In {
> public:
> virtual int getc() = 0;
> virtual char* gets(char* s, int size) = 0;
This should work with std::string instead of char (or std::wstring?
std::basic_string?)
> virtual int scanf(const char* format, ...) = 0;
This is really unsafe.
> virtual size_t read(void* ptr, size_t size, size_t nmemb) = 0;
This should probably work with std::vector instead of void*.
> virtual In& operator>> (bool& val) = 0;
> virtual In& operator>> (short& val) = 0;
> virtual In& operator>> (unsigned short& val) = 0;
> virtual In& operator>> (int& val) = 0;
> virtual In& operator>> (unsigned int& val) = 0;
> virtual In& operator>> (long& val) = 0;
> virtual In& operator>> (unsigned long& val) = 0;
> virtual In& operator>> (float& val) = 0;
> virtual In& operator>> (double& val) = 0;
> virtual In& operator>> (long double& val) = 0;
> virtual In& operator>> (const void*& val) = 0;
> virtual In& operator>> (char& c) = 0;
> virtual In& operator>> (signed char& c) = 0;
> virtual In& operator>> (unsigned char& c) = 0;
> virtual In& operator>> (char*& s) = 0;
> virtual In& operator>> (String& s) = 0;
> virtual In& operator>> (Charp& s) = 0;
As said, these belong to another interface, should be non-virtual and
templated instead:
template<typename T> In& operator>>(T& val);
In my experience, most files are not textual, so all these bells and
whistles wasted on the on-the-fly textual formatting and conversions are
not really worth it IMO. Maybe you really want to create some hierarchy
of binary I/O classes instead, this would be a much easier task.
Cheers
Paavo
[toc] | [prev] | [next] | [standalone]
| From | jakash3 <jakashthree@gmail.com> |
|---|---|
| Date | 2011-06-11 12:35 -0700 |
| Message-ID | <6f1c7196-a197-4bd5-9b71-822ff52f980f@z4g2000prk.googlegroups.com> |
| In reply to | #6610 |
@Paavo Helde I'm actually a student still learning and you brought up very good points. I never thought about specific output formatting options and locales. Perhaps I should include methods to set the options for string and number output for streams or maybe even create variations on the class in different namespaces for different locales. Btw I forgot to mention that String and Charp types referenced in this class are a string class and character pointer class respectively. Charp can be treated like a regular character pointer except there would be an option to automatically call free to the character pointer upon destruction. My String class will return it's internal character pointer when casted as a char ptr or passed to a function that expects one.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <myfirstname@osa.pri.ee> |
|---|---|
| Date | 2011-06-18 06:35 -0500 |
| Message-ID | <Xns9F08945FCC481myfirstnameosapriee@216.196.109.131> |
| In reply to | #6627 |
jakash3 <jakashthree@gmail.com> wrote in news:6f1c7196-a197-4bd5-9b71- 822ff52f980f@z4g2000prk.googlegroups.com: > @Paavo Helde I'm actually a student still learning and you brought up > very good points. I never thought about specific output formatting > options and locales. Perhaps I should include methods to set the > options for string and number output for streams or maybe even create > variations on the class in different namespaces for different locales. > Btw I forgot to mention that String and Charp types referenced in this > class are a string class and character pointer class respectively. > Charp can be treated like a regular character pointer except there > would be an option to automatically call free to the character pointer > upon destruction. So what is the purpose of existence of the Charp class? A string class like std::string does about the same except it additionally stores the length of the string. A char* wrapper would be useful quite rarely, for example if you receive a lot of char* pointers from a C-style library, which need to be passed again to some C-style library working with char* interfaces. But in that case the pointers would be probably released with some library-specific release function, so hardcoding free() would be a mistake. The point is that for working with strings one often needs to know its length. With char* interfaces one is forced to recalculate the length over and over again, which can easily ruin any perceived performance benefits of char* over a std::string-like class. Also, supporting two different string classes in the code is a headache. > My String class will return it's internal character > pointer when casted as a char ptr or passed to a function that expects > one. Not a good idea. MS tried this with their CString class and it is generally accepted this was a mistake. Their own compiler now emits warnings whenever a CString is implicitly converted to a const char* pointer. If this is your own fun project, then of course there is nothing wrong with reinventing the string classes and learning from the mistakes. If you are doing this for something more serious, then I strongly suggest to ditch your own string and stream classes and go with std::string and iostreams. There are a few quirks this way as well, but the end result will most probably be better than whatever you can invent by yourself. Note that for advanced usage of standard strings and streams you need to learn quite a bit about std::basic_string and std::basic_streambuf class templates. hth Paavo
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2011-06-12 14:43 +0000 |
| Message-ID | <slrniv9k51.gtj.grahn+nntp@frailea.sa.invalid> |
| In reply to | #6610 |
On Sat, 2011-06-11, Paavo Helde wrote: > jakash3 <jakashthree@gmail.com> wrote in > news:4e58c83a-eefa-4231-8e7d-506632e14a5f@f31g2000pri.googlegroups.com: > >> I've made In and Out abstract base classes which I plan to have File, >> Socket, and Console classes base some of their methods on. These >> interfaces will have method names like those from the C library as >> well as formatted insertion and extraction streams. Please give >> feedback and suggestions on how I can add to or improve this >> interface. ... > In my experience, most files are not textual, so all these bells and > whistles wasted on the on-the-fly textual formatting and conversions are > not really worth it IMO. That varies with your environment, I think. I'm on Unix, and most file formats there are text. If you design your own, you normally choose text. Many popular networking protocol are too (since he mentioned sockets). /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web