CLOUD: Add complex callbacks

Originally, I intended to add Storage API, StorageFile and StorageInfo
stubs. When I tried to implement a simple info() call, I ended up fixing
Request to contain some pointer field and all callbacks to have Request*
parameter. And, now I have to place callback pointer into Request. which
calls another callback.

And, eventually, these "simple" callbacks would again require another
pointer (to some caller class).
This commit is contained in:
Alexander Tkachev 2016-05-21 00:44:09 +06:00
parent f913675c43
commit 17eb5f9143
8 changed files with 149 additions and 33 deletions

View File

@ -35,7 +35,7 @@ namespace Dropbox {
Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth
Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow
static void printJsonCallback(void *ptr) {
static void printJsonCallback(Networking::Request* rq, void *ptr) {
Common::JSONValue *json = (Common::JSONValue *)ptr;
if (json) {
debug("printJsonCallback:");
@ -46,7 +46,7 @@ static void printJsonCallback(void *ptr) {
}
}
static void saveAccessTokenCallback(void *ptr) {
static void saveAccessTokenCallback(Networking::Request* rq, void *ptr) {
Common::JSONValue *json = (Common::JSONValue *)ptr;
if (json) {
debug("saveAccessTokenCallback:");
@ -69,6 +69,29 @@ static void saveAccessTokenCallback(void *ptr) {
}
}
void infoCallback(Networking::Request* request, void *jsonPointer) {
if (!request) {
warning("infoCallback: got NULL instead of Request");
Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
if (json) delete json; //yeah I know we can delete NULL safely
return;
}
Storage::InfoCallback callback = (Storage::InfoCallback)request->pointer();
Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
if (json) {
//Common::JSONObject result = json->asObject();
if (callback) {
callback(StorageInfo(json->stringify()));
}
delete json;
} else {
warning("infoCallback: got NULL instead of JSON!");
}
}
DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) {
curl_global_init(CURL_GLOBAL_ALL);
}
@ -77,18 +100,21 @@ DropboxStorage::~DropboxStorage() {
curl_global_cleanup();
}
void DropboxStorage::listDirectory(Common::String path) {
void syncSavesInfoCallback(StorageInfo info) {
debug("info: %s", info.info().c_str());
}
void DropboxStorage::syncSaves() {
//not syncing, but already something:
printInfo();
void DropboxStorage::syncSaves(OperationCallback callback) {
//this is not the real syncSaves() implementation
info(syncSavesInfoCallback);
}
void DropboxStorage::printInfo() {
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(printJsonCallback, "https://api.dropboxapi.com/1/account/info");
void DropboxStorage::info(InfoCallback callback) {
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(infoCallback, "https://api.dropboxapi.com/1/account/info");
request->addHeader("Authorization: Bearer " + _token);
ConnMan.addRequest(request);
request->setPointer(callback);
}
DropboxStorage *DropboxStorage::loadFromConfig() {

View File

@ -42,9 +42,36 @@ class DropboxStorage: public Cloud::Storage {
public:
virtual ~DropboxStorage();
virtual void listDirectory(Common::String path);
virtual void syncSaves();
virtual void printInfo();
/** Returns pointer to Common::Array<CloudFile>. */
virtual void listDirectory(Common::String path, ListDirectoryCallback callback) {} //TODO
/** Calls the callback when finished. */
virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) {} //TODO
/** Returns pointer to Common::ReadStream. */
virtual void download(Common::String path, DownloadCallback callback) {} //TODO
/** Calls the callback when finished. */
virtual void remove(Common::String path, OperationCallback callback) {} //TODO
/** Calls the callback when finished. */
virtual void syncSaves(OperationCallback callback);
/** Calls the callback when finished. */
virtual void createDirectory(Common::String path, OperationCallback callback) {} //TODO
/** Calls the callback when finished. */
virtual void touch(Common::String path, OperationCallback callback) {} //TODO
/** Returns pointer to the ServiceInfo struct. */
virtual void info(InfoCallback callback);
/** Returns whether saves sync process is running. */
virtual bool isSyncing() { return false; } //TODO
/** Returns whether there are any requests running. */
virtual bool isWorking() { return false; } //TODO
/**
* Load token and user id from configs and return DropboxStorage for those.
* @return pointer to the newly created DropboxStorage or 0 if some problem occured.

View File

@ -46,9 +46,9 @@ Storage* Manager::getCurrentStorage() {
return _currentStorage;
}
void Manager::syncSaves() {
void Manager::syncSaves(Storage::OperationCallback callback) {
Storage* storage = getCurrentStorage();
if (storage) storage->syncSaves();
if (storage) storage->syncSaves(callback);
}
} //end of namespace Cloud

View File

@ -38,7 +38,7 @@ public:
virtual void init();
virtual Storage* getCurrentStorage();
virtual void syncSaves();
virtual void syncSaves(Storage::OperationCallback callback);
};
} //end of namespace Cloud

View File

@ -23,37 +23,90 @@
#ifndef BACKENDS_CLOUD_STORAGE_H
#define BACKENDS_CLOUD_STORAGE_H
#include "common/array.h"
#include "common/stream.h"
#include "common/str.h"
namespace Cloud {
class StorageFile {
Common::String _path, _name;
uint32 _size, _timestamp;
bool _isDirectory;
public:
StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) {
_path = pth;
_name = pth;
for (uint32 i = _name.size() - 1; i >= 0; --i) {
if (_name[i] == '/' || _name[i] == '\\') {
_name.erase(0, i);
break;
}
if (i == 0) break; //OK, I admit that's strange
}
_size = sz;
_timestamp = ts;
_isDirectory = dir;
}
Common::String path() const { return _path; }
Common::String name() const { return _name; }
uint32 size() const { return _size; }
uint32 timestamp() const { return _timestamp; }
bool isDirectory() const { return _isDirectory; }
};
class StorageInfo {
Common::String _info;
public:
StorageInfo(Common::String info): _info(info) {}
Common::String info() const { return _info; }
};
class Storage {
public:
typedef void(*ListDirectoryCallback)(Common::Array<StorageFile>& result);
typedef void(*DownloadCallback)(Common::ReadStream* result);
typedef void(*InfoCallback)(StorageInfo result);
typedef void(*OperationCallback)(bool successed);
Storage() {}
virtual ~Storage() {}
/**
* Lists given directory.
*
* @param path directory to list
*/
/** Returns pointer to Common::Array<CloudFile>. */
virtual void listDirectory(Common::String path, ListDirectoryCallback callback) = 0;
//TODO: actually make it list directories
//TODO: add some callback to pass gathered files list
/** Calls the callback when finished. */
virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) = 0;
virtual void listDirectory(Common::String path) = 0;
/** Returns pointer to Common::ReadStream. */
virtual void download(Common::String path, DownloadCallback callback) = 0;
/**
* Starts saves syncing process.
*/
/** Calls the callback when finished. */
virtual void remove(Common::String path, OperationCallback callback) = 0;
virtual void syncSaves() = 0;
/** Calls the callback when finished. */
virtual void syncSaves(OperationCallback callback) = 0;
/**
* Prints user info on console. (Temporary)
*/
/** Calls the callback when finished. */
virtual void createDirectory(Common::String path, OperationCallback callback) = 0;
virtual void printInfo() = 0;
/** Calls the callback when finished. */
virtual void touch(Common::String path, OperationCallback callback) = 0;
/** Returns pointer to the ServiceInfo struct. */
virtual void info(InfoCallback callback) = 0;
/** Returns whether saves sync process is running. */
virtual bool isSyncing() = 0;
/** Returns whether there are any requests running. */
virtual bool isWorking() = 0;
};
} //end of namespace Cloud

View File

@ -75,7 +75,7 @@ bool CurlJsonRequest::handle() {
if (_callback) {
char *contents = getPreparedContents();
Common::JSONValue *json = Common::JSON::parse(contents);
_callback(json); //potential memory leak, free it in your callbacks!
_callback(this, json); //potential memory leak, free it in your callbacks!
}
return true;
}

View File

@ -27,7 +27,7 @@ namespace Networking {
class Request {
protected:
typedef void(*Callback)(void *result);
typedef void(*Callback)(Request* request, void *result);
/**
* Callback, which should be called before Request returns true in handle().
@ -36,6 +36,13 @@ protected:
Callback _callback;
/**
* Pointer, which could be set by Request creating code. It might be accessed
* from this Request when callback is called, for example.
*/
void *_pointer;
public:
Request(Callback cb): _callback(cb) {};
virtual ~Request() {};
@ -47,6 +54,9 @@ public:
*/
virtual bool handle() = 0;
void setPointer(void *ptr) { _pointer = ptr; }
void *pointer() const { return _pointer; }
};
} //end of namespace Cloud

View File

@ -53,7 +53,7 @@ public:
* Starts saves syncing process in currently active storage if there is any.
*/
virtual void syncSaves() = 0;
virtual void syncSaves(Cloud::Storage::OperationCallback callback = 0) = 0;
};
} //end of namespace Common