How Best to Keep Function From Closing File? - c++

So, I've been trying to be more rigorous with making any passed parameters that shouldn't be touched by a function const.
One situation I've encountered in some of my C++ code is the case where the object may change, but where I want to "lock out" functions from access certain key functionality of the object. For example, for an std::ifstream file handle, I may wish to prevent the function from closing the file.
If I pass it as a const &, the const part keeps me from performing standard file i/o, it seems.
e.g. I want something along the lines of
void GetTags(Arr<std::string> & tags, std::ifstream const& fileHandle)
...but written in such a way to allow file i/o but not open/close operations.
Is there any good/reliable way to do this in C++? What would be considered best practice?

This has already been done for you by the standard library design: Pass a reference to the base class std::istream instead, which does not have a notion of opening or closing - it exposes only the stream interface.
void stream_me(std::istream & is);
std::ifstream is("myfile.txt");
stream_me(is);

In your place I'd just pass a std::istream instead.

You could wrap the ifstream in an object that only exposed the functionality that you wished the caller to be able to use.
However, if you have a bunch of different functions, each with a different subset of ifstream's functionality, you'll end up with lots of different wrapper classes; so I don't see this as a general solution.

I think the best way would be to wrap the ifstream in a new class which only has member functions corresponding to the functionality you wantGetTags to have access to. Then pass that not the ifstream as the second argument to GetTags.

Related

Invoke different functions for different file extensions

Here's the situation:
I have a Graph class written in C++ and I need to build Graph objects from Files. The problem is that Graph are memorized in files in a lot of different ways, so I was thinking about a function that, using the file extension, could invoke the correct procedure for building a Graph in a certain format. How should I proceed? Am I wrong or I can't just overload operator>> in my class?Thanks in advance.
operator>> is (should be) agnostic to any details of the stream from which it is extracting, so using this operator is probably the wrong tact.
The best way to do this would be:
graph_type load_from_file(const std::string& file_path) { //or use something like boost::filesystem::path
std::ofstream file { file_path };
if(endswith(file_path, ".graph") {
return deserialize_from_graph(ofstream);
}
if(endswith(file_path, ".g2") {
return deserialize_from_g2(ofstream);
}
//other formats here
//else throw
}
note, endswith is not from the standard library, boost however has an implementation in it's string algorithms.
How do you determine how the data is memorized. If it is just
the extension, all you need is a map
std::string→pointer_to_function. If the same
extension can have several different representations,
distinguished, for example, by the first couple of bytes in the
file, or information in some common header, you'll have to
differ the final choice until you've read these
bytes—again, a map to the a pointer to function will do
the trick.
Depending on the complexity of the formats to read, you may want
to replace the pointer to a reader function with a pointer to
a factory function, which returns an instance of a reader class,
which derives from an abstract reader.

Passing raw data in C++

Up until now, whenever I wanted to pass some raw data to a function (like a function that loads an image from a buffer), I would do something like this:
void Image::load(const char* buffer, std::size_t size);
Today I took a look at the Boost libraries, more specifically at the property_tree/xml_parser.hpp header, and I noticed this function signature:
template<typename Ptree>
void read_xml(std::basic_istream<typename Ptree::key_type::value_type>&,
Ptree &, int = 0);
This actually made me curious: is this the correct way to pass around raw data in C++, by using streams? Or am I misinterpreting what the function is supposed to be used for?
If it's the former, could you please point me to some resource where I can learn how to use streams for this? I haven't found much myself (mainly API references), and I have't been able to find the Boost source code for the XML parser either.
Edit: Some extra details
Seems there's been some confusion as to what I want. Given a data buffer, how can I convert it to a stream such that it is compatible with the read_xml function I posted above? Here's my specific use case:
I'm using the SevenZip C library to read an XML file from an archive. The library will provide me with a buffer and its size, and I want to put that in stream format such that it is compatible with read_xml. How can I do that?
Well, streams are quite used in C++ because of their conveniences:
- error handling
- they abstract away the data source, so whether you are reading from a file, an audio source, a camera, they are all treated as input streams
- and probably more advantages I don't know of
Here is an overview of the IOstream library, perhaps that might better help you understand what's going on with streams:
http://www.cplusplus.com/reference/iostream/
Understanding what they are exactly will help you understand how and when to use them.
There's no single correct way to pass around data buffers. A combination of pointer and length is the most basic way; it's C-friendly. Passing a stream might allow for sequential/chunked processing - i. e. not storing the whole file in memory at the same time. If you want to pass a mutable buffer (that might potentially grow), a vector<char>& would be a good choice.
Specifically on Windows, a HGLOBAL or a section object handle might be used.
The C++ philosophy explicitly allows for many different styles, depending on context and environment. Get used to it.
Buffers of raw memory in C++ can either be of type unsigned char*, or you can create a std::vector<unsigned char>. You typically don't want to use just a char* for your buffer since char is not guaranteed by the standard to use all the bits in a single byte (i.e., this will end up varying by platform/compiler). That being said, streams have some excellent uses as well, considering that you can use a stream to read bytes from a file or some other input, etc., and from there, store that data in a buffer.
Seems there's been some confusion as to what I want. Given a data buffer, how can I convert it to a stream such that it is compatible with the read_xml function I posted above?
Easily (I hope PTree::Key_type::value_type would be something like char):
istringstream stream(string(data, len));
read_xml(stream, ...);
More on string streams here.
This is essentially using a reference to pass the stream contents. So behind the scene's it's essentially rather similar to what you did so far and it's essentially the same - just using a different notation. Simplified, the reference just hides the pointer aspect, so in your boost example you're essentially working with a pointer to the stream.
References got the advantage avoiding all the referencing/dereferencing and are therefore easier to handle in most situations. However they don't allow you multiple levels of (de-)referencing.
The following two example functions do essentially the same:
void change_a(int &var, myclass &cls)
{
var = cls.convert();
}
void change_b(int *var, myclass *cls)
{
*var = cls->convert();
}
Talking about the passed data itself: It really depends on what you're trying to achieve and what's more effective. If you'd like to modify a string, utilizing an object of class std::string might be more convenient than using a classic pointer to a buffer (char *). Streams got the advantage that they can represent several different things (e.g. data stream on the network, a compressed stream or simply a file or memory stream). This way you can write single functions or methods that accept a stream as input and will instantly work without worrying about the actual stream source. Doing this with classic buffers can be more complicated. On the other side you shouldn't forget that all objects will add some overhead, so depending on the job to be done a simple pointer to a character string might be perfectly fine (and the most effective solution). There's no "the one way to do it".

How can I override an C++ standard-library class function?

How can I override a C++ standard-library class function? In my application, I use ofstream objects in many different places of code. And now I want to open files in a different permission mode in Linux, Ubuntu. But open function of ofstream has no parameter to specify the permission mode of the file it creats.
Now I want to override open() function of ofstream class so it will get a parameter to specify the permissions for user access.
For starters, to clarify your terminology, the STL usually refers to the subset of the C++ standard library containing the containers, iterators, and algorithms. The streams classes are part of the C++ standard library, but are usually not bundled together with the STL. Some purists will insist that there is no such thing as the STL in the C++ standard library (since the STL is, technically speaking, a third-party library that was adopted into the standard), but most C++ programmers will know what you mean.
As for your question, there is no way within the standard to specify permission modes with ofstream. If you want to create your own custom stream class that is like ofstream but which supports permissions, your best bet would be to do the following:
Create a subclass of basic_streambuf that allows you to open, write, and possibly read files while specifying Unix permissions. The streams classes are designed so that the details of communicating with physical devices like disk, networks, and the console are all handled by the basic_streambuf class and its derived classes. If you want to make your own stream class, implementing a stream buffer would be an excellent first step.
Define your own class that subclasses basic_ostream and installs your custom basic_streambuf. By default, the basic_ostream supports all of the standard output routines by implementing them in terms of the underlying basic_streambuf object. Once you have your own stream buffer, building a basic_ostream class that uses that streambuf will cause all of the standard stream operations on that class (such as <<) to start making the appropriate calls to your streambuf.
If you'd like more details on this, an excellent reference is Standard C++ IOStreams and Locales. As a shameless plug, I have used the techniques from this book to build a stream class that wraps a socket connection. While a lot of the code in my stream won't be particularly useful, the basic structure should help you get started.
Hope this helps!
This is not answering your question directly as I wouldn't advise overriding ofstream::open.
Instead couldn't you use the first suggestion in this post? Open the file as you normally would to get the correct permissions, and then construct an ofstream from the file descriptor.
#include <iostream>
#include <fstream>
class gstream: public std::ofstream
{
void open(const std::string& filename, ios_base::openmode mode,int stuff)
{
//put stuff here
}
};
int main() {
gstream test;
//io stuff
return 0;
}
seems to work here.
Another option would be to create a wrapper class that contains an 'ofstream' object and has the interface you want, and passes the work onto its 'oftstream' member. It would look like this.

Deriving from streambuf without rewriting a corresponding stream

Some days ago, I decided that it would be fun to write a streambuf subclass that would use mmap and read-ahead.
I looked at how my STL (SGI) implemented filebuf and realized that basic_filebuf contains a FILE*. So inheriting from basic_filebuf is out of the question.
So I inherited from basic_streambuf. Then i wanted to bind my mmapbuf to a fstream.
I thought the only thing that I would have to do would be to copy the implicit interface of filebuf... but that was a clear mistake. In the SGI, basic_fstream owns a basic_filebuf. No matter if I call basic_filestream.std::::ios::rdbuf( streambuf* ), the filestream completely ignores it and uses its own filebuf.
So now I'm a bit confused... sure, I can create my own mmfstream, that would be the exact copy/paste of the fstream but that sounds really not DRY-oriented.
What I can't understand, is: why does fstream is so tightly coupled with filebuf, so that it is not possible to use anything else than a filebuf? The whole point of separating streams and bufs is that one can use a stream with a different buffer.
Solutions:
=> filestream should rely on the implicit interface of filebuf. That is, fstream should be templated by a streambuf class. That would allow everyone to provide its own streambuf subclass to a fstream as long as it implements filebuf's implicit interface. Problem: we cannot add a template parameter to fstream since it would break template selectors while using fstream as template template parameter.
=> filebuf should be a pure virtual class without any additional attributes. So that one can inherit from it without carrying all its FILE* garbage.
Your ideas on the subject ?
In the IO streams' design, most of the actual streams' functionality (as opposed to the stream buffers' functionality) is implemented in std::basic_istream, std::basic_ostream, and their base classes. The string and file stream classes are more or less just convenience wrappers which make sure a stream with the right type of buffer is instantiated.
If you want to extend the streams, you almost always want to provide your own stream buffer class, and you almost never need to provide your own stream class. .
Once you have your own stream buffer type, you can then make it the buffer for any stream object you happen to have around. Or you derive your own classes from std::basic_istream, std::basic_ostream, and std::basic_iostream which instantiates your stream buffer and pass it to their base classes.
The latter is more convenient for users, but requires you to write some boiler-plate code for the buffer's instantiation (namely constructors for the stream class).
To answer your question: File streams and file buffer are coupled so tightly because the former only exists to ease the creation of the latter. Using a file stream makes it easy to set it all up.
Using your own stream class to wrap construction of your own stream buffer shouldn't be a problem, since you shouldn't be passing around file streams anyway, but only (references) to the base classes.
Check out mapped_file in the Boost.Iostreams library. I've never used used it myself, but it seems like it might already do what you need.
EDIT: Oops, reread your questions and I see you're doing this for fun. Perhaps you can draw inspiration from Boost.Iostreams?
fstream in itself is not a big class. It inherits from basic_stream to provide support for all the << and >> operations, contains a specialized steambuf that have to be initialized, and the corresponding constructors to pass the parameters to the streambuf constructor.
In a sense, what you wrote about your templated solution is OK. But basic_stream can also be derived into a tcp_stream for example. In that case, the constructors of fstream are a bit useless. Thus you need to provide a new tcpstream class, inheriting from basic_stream with the correct parameters for the constructors to be able to create the tcp_stream. In the end, you wouldn't use anything from fstream. Creating this new tcpstream is a matter of writing 3 or 4 functions only.
In the end, you would derive from the fstream class without any real reason to. This would add more coupling in the class hierarchy, unneeded coupling.
The whole point of std::fstream is that it is a _F_ile based std::stream. If you want an ordinary std::stream backed by your mmstreambuf, then you should create a mmstreambuf and pass it to std::stream::stream(std::streambuf*)

Having a class with no data members good option for file manipulation?

I have a file with saved data that sometimes needs to be accessed, written to, erased, etc. when the program is running. I decided to write a SavedDataHandler class to accomplish this. I'm currently using the fstream class.
I considered having one data member be the fstream itself, opening it in the constructor, and closing it in the destructor. However, I realized that different functions called on the SavedDataHandler open the stream differently ( setting different flags, etc. ) so I decided not to go that route.
Instead I just have a static const std::string with the file name, with the public member functions handling the opening and closing of the file as they need to. Performance is not an issue.
Is this route a valid option? Since it has no data members, providing a constructor isn't even necessary. It's just a class that contains functions ( and one static constant ), with the functions operating on a resource rather than a data member.
Hmya, the fstream class is by itself already a capable wrapper class around an operating system handle for a file. If you can't think of a way to add functionality to your own wrapper around fstream, take it as a hint that you don't actually need a wrapper.
Don't wrap (or inherit) just because you can.
Well in some projects, wrapping is essential. Just stop to think if later you'll need for example, to change the file I/O libs (dunno why you'd want to do that, since C++ libs are optimized and ISO). What would you do then? Change all the calls from fstream to YourNewSuperMegaLib::SuperFileSystem::MegaFileStream?
If you want simplicity, I'd just inherit fstream and in the constructor, pass the opening modes you want and invoke the super constructor accodingly.