Skip to content

Commit

Permalink
Implemented a curl_writer used to change stream and writer callback f…
Browse files Browse the repository at this point in the history
…unctions used by libcurl .Now you can choose your stream (for example a file) and write libcurl function output into it, using your custom function/method, or use a default one.
  • Loading branch information
JosephP91 committed Jul 3, 2014
1 parent 78d1272 commit fc12e75
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 31 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,16 @@ using std::ofstream;
using curl::curl_easy;

int main(int argc, const char * argv[]) {

ofstream myfile;
// Create a file
ofstream myfile;
myfile.open ("/Users/Giuseppe/Desktop/test.txt");
// Create a writer to handle the stream

curl_writer(myfile);
// Pass it to the easy constructor and watch the content returned in that file!
curl_easy easy(myfile);
curl_easy easy(writer);

// Add some option to the easy handle
easy.add(curl_pair<CURLoption,string>(CURLOPT_URL,"http://www.google.it") );
easy.add(curl_pair<CURLoption,long>(CURLOPT_FOLLOWLOCATION,1L));
try {
Expand Down
10 changes: 6 additions & 4 deletions include/curl_easy.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@

#include "curl_interface.h"
#include "curl_pair.h"
#include "curl_writer.h"

using std::vector;
using std::list;
using std::for_each;
using std::unique_ptr;
using std::ostream;

using curl::curl_pair;
using curl::curl_writer;
using curl::curl_interface;
using curl::curl_easy_exception;

Expand All @@ -46,7 +47,7 @@ namespace curl {
* stream where they want to put the output of the libcurl
* operations.
*/
explicit curl_easy(ostream &);
explicit curl_easy(curl_writer &);
/**
* This overloaded constructor allows users to specify a flag
* used to initialize libcurl environment.
Expand All @@ -56,7 +57,7 @@ namespace curl {
* This overloaded constructor allows to specify the environment
* initialization flags and a stream where to put libcurl output.
*/
curl_easy(const long, ostream &);
curl_easy(const long, curl_writer &);
/**
* Copy constructor to handle pointer copy. Internally, it uses
* a function which duplicates the easy handler.
Expand Down Expand Up @@ -120,7 +121,8 @@ namespace curl {
void unescape(string &);
/**
* This fuctions performs all the operations that user has specified
* with the add methods.
* with the add methods. If the performing operationd has finished
* the method returns true. Else, returns false.
*/
void perform();
/**
Expand Down
8 changes: 4 additions & 4 deletions include/curl_multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,21 @@ namespace curl {
*/
bool is_finished(const curl_easy &);
/**
* Perform all the operations. Go baby!
* Perform all the operations. Go baby! If the performing operations
* has finished, the method returns true. Else, returns false. Check
* online documentation for further documentation.
*/
bool perform();
/**
* This method wraps the libcurl function that reads/writes available data
* given an action. Read the libcurl online documentation to learn more
* about this function!
* TODO I would like to wrap curl_socket_t, but I don't know ....
*/
bool socket_action(const curl_socket_t, const int);
/**
* This method wraps the libcurl function that extracts file descriptor
* information from the multi handler.
* Read the libcurl online documentation to learn more about this function.
* TODO I would like to wrap fd_set in curl_file_descriptor. We'll see ...
*/
void set_fd(fd_set *, fd_set *, fd_set *, int *);
/**
Expand Down Expand Up @@ -229,4 +229,4 @@ namespace curl {
}
}

#endif /* curl_multi_H */
#endif /* curl_multi_H */
71 changes: 71 additions & 0 deletions include/curl_writer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// curl_writer.h
// curlcpp
//
// Created by Giuseppe Persico on 03/07/14.
// Copyright (c) 2014 Giuseppe Persico. All rights reserved.
//

#ifndef __curlcpp__curl_writer__
#define __curlcpp__curl_writer__

#include <iostream>

using std::ostream;

// Let's typedef this big boy to enheance code readability.
typedef size_t (*curlcpp_writer_type)(void *, size_t, size_t, void *);

namespace curl {
/**
* This class allows users to specify a stream where to put the
* output returned by libcurl functions. curl_easy class
* will set all the necessary options to make it easy. You just have
* to specify your stream and your writer function.
*/
class curl_writer {
public:
/**
* The default constructor will use a default stream and a default
* writer callback to perform the operations.
*/
curl_writer();
/**
* This overloaded constructor allows users to specify a stream
* where to write, using the default writer callback.
*/
curl_writer(ostream &);
/**
* This overloaed constructor allows users to specify a writer
* callback function used specify how to write something on the
* the default stream which is std::cout;
*/
curl_writer(curlcpp_writer_type);
/**
* This overloaded constructor allows users to specify a custom
* stream and a custom writer callback function.
*/
curl_writer(ostream &, curlcpp_writer_type);
/**
* Simple getter method that returns the stream specifyed in the
* constructor.
*/
ostream *get_stream() const;
/**
* Simple getter method that returns the function specified (or not)
* in the constructor.
*/
curlcpp_writer_type get_function() const;
protected:
/**
* Utility method used to validate the function pointer eventually
* specified.
*/
void set_writer_ptr(curlcpp_writer_type);
private:
curlcpp_writer_type _writer_ptr;
ostream *_stream_ptr;
};
}

#endif /* defined(__curlcpp__curl_writer__) */
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SET(CURLCPP_SOURCE
curl_share.cpp
curl_info.cpp
curl_exception.cpp
curl_writer.cpp
)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Expand Down
32 changes: 12 additions & 20 deletions src/curl_easy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,25 @@

using curl::curl_easy;

// Default memory write callback.
namespace {
size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) {
const size_t realsize = size * nmemb;
ostream* const mem = static_cast<ostream*>(userp);
mem->write(static_cast<const char*>(contents), realsize);
return realsize;
}
}

// Implementation of default constructor.
curl_easy::curl_easy() : curl_interface() {
this->curl = curl_easy_init();
if (this->curl == nullptr) {
throw curl_easy_exception("Null pointer intercepted",__FUNCTION__);
}
this->add(curl_pair<CURLoption, size_t(*)(void*,size_t,size_t,void *)>(CURLOPT_WRITEFUNCTION, &write_memory_callback));
this->add(curl_pair<CURLoption, void *>(CURLOPT_WRITEDATA, static_cast<void*>(&cout)));
curl_writer writer;
this->add(curl_pair<CURLoption,curlcpp_writer_type>(CURLOPT_WRITEFUNCTION,writer.get_function()));
this->add(curl_pair<CURLoption,void *>(CURLOPT_WRITEDATA, static_cast<void*>(writer.get_stream())));
}

// Implementation of default constructor.
curl_easy::curl_easy(ostream &outstream) : curl_interface() {
curl_easy::curl_easy(curl_writer &writer) : curl_interface() {
this->curl = curl_easy_init();
if (this->curl == nullptr) {
throw curl_easy_exception("Null pointer intercepted",__FUNCTION__);
}
this->add(curl_pair<CURLoption, size_t(*)(void*,size_t,size_t,void*)>(CURLOPT_WRITEFUNCTION, &write_memory_callback));
this->add(curl_pair<CURLoption, void*>(CURLOPT_WRITEDATA, static_cast<void*>(&outstream)));
this->add(curl_pair<CURLoption,curlcpp_writer_type>(CURLOPT_WRITEFUNCTION,writer.get_function()));
this->add(curl_pair<CURLoption,void*>(CURLOPT_WRITEDATA, static_cast<void*>(writer.get_stream())));
}

// Implementation of overridden constructor.
Expand All @@ -45,18 +36,19 @@ curl_easy::curl_easy(const long flag) : curl_interface(flag) {
if (this->curl == nullptr) {
throw curl_easy_exception("Null pointer intercepted",__FUNCTION__);
}
this->add(curl_pair<CURLoption, size_t(*)(void*,size_t,size_t,void *)>(CURLOPT_WRITEFUNCTION, &write_memory_callback));
this->add(curl_pair<CURLoption, void *>(CURLOPT_WRITEDATA, static_cast<void*>(&cout)));
curl_writer writer;
this->add(curl_pair<CURLoption,curlcpp_writer_type>(CURLOPT_WRITEFUNCTION,writer.get_function()));
this->add(curl_pair<CURLoption,void *>(CURLOPT_WRITEDATA, static_cast<void*>(writer.get_stream())));
}

// Implementation of overridden constructor.
curl_easy::curl_easy(const long flag, ostream &outstream) : curl_interface(flag) {
curl_easy::curl_easy(const long flag, curl_writer &writer) : curl_interface(flag) {
this->curl = curl_easy_init();
if (this->curl == nullptr) {
throw curl_easy_exception("Null pointer intercepted",__FUNCTION__);
}
this->add(curl_pair<CURLoption, size_t(*)(void*,size_t,size_t,void*)>(CURLOPT_WRITEFUNCTION, &write_memory_callback));
this->add(curl_pair<CURLoption, void*>(CURLOPT_WRITEDATA, static_cast<void*>(&outstream)));
this->add(curl_pair<CURLoption, size_t(*)(void*,size_t,size_t,void*)>(CURLOPT_WRITEFUNCTION,writer.get_function()));
this->add(curl_pair<CURLoption, void*>(CURLOPT_WRITEDATA, static_cast<void*>(writer.get_stream())));
}

// Implementation of copy constructor to respect the rule of three.
Expand Down
61 changes: 61 additions & 0 deletions src/curl_writer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// curl_writer.cpp
// curlcpp
//
// Created by Giuseppe Persico on 03/07/14.
// Copyright (c) 2014 Giuseppe Persico. All rights reserved.
//

#include "curl_writer.h"

using std::cout;
using curl::curl_writer;

// Default memory write callback.
namespace {
size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp) {
const size_t realsize = size * nmemb;
ostream* const mem = static_cast<ostream*>(userp);
mem->write(static_cast<const char*>(contents), realsize);
return realsize;
}
}

// Implementation of constructor.
curl_writer::curl_writer() {
_stream_ptr = &cout;
_writer_ptr = &write_memory_callback;
}

// Implementation of overloaded constructor.
curl_writer::curl_writer(ostream &stream) {
_stream_ptr = &stream;
_writer_ptr = &write_memory_callback;
}

// Implementation of another overloaded constructor.
curl_writer::curl_writer(curlcpp_writer_type writer_ptr) {
_stream_ptr = &cout;
this->set_writer_ptr(writer_ptr);
}

// Implementation of another overloaded constructor.
curl_writer::curl_writer(ostream &stream, curlcpp_writer_type writer_ptr) {
_stream_ptr = &stream;
this->set_writer_ptr(writer_ptr);
}

// Implementation of get_stream method.
ostream *curl_writer::get_stream() const {
return _stream_ptr;
}

// Impementation of get_function method.
curlcpp_writer_type curl_writer::get_function() const {
return _writer_ptr;
}

// Implementation of set_writer_ptr method.
void curl_writer::set_writer_ptr(curlcpp_writer_type writer_ptr) {
_writer_ptr = (writer_ptr == nullptr) ? &write_memory_callback : writer_ptr;
}

0 comments on commit fc12e75

Please sign in to comment.