<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/map/GeocodingMapEngine.h"
#include "common/IRhoClassFactory.h"
#include "common/RhoThread.h"
#include "net/URI.h"
#include "json/JSONIterator.h"

#include "common/RhoMath.h"
#include "common/RhoConf.h"
#include "common/RhodesApp.h"
#include "common/RhoFile.h"
#include "net/INetRequest.h"

#include "ruby/ext/rho/rhoruby.h"

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "GeocodingMapEngine"

extern "C" unsigned long rjson_tokener_parse(const char *str, char** pszError);

namespace rho
{
namespace common
{
namespace map
{

String GoogleGeoCoding::Command::toString()
{
    return address;
}

IMPLEMENT_LOGCLASS(GoogleGeoCoding,"GGeoCoding");
GoogleGeoCoding::GoogleGeoCoding()
{
#ifdef ENABLE_ANDROID_NET_REQUEST
	mNetRequestID = 0;
#endif
    CThreadQueue::setLogCategory(getLogCategory());
    RHO_MAP_TRACE("GoogleGeoCoding: ctor start");
    start(epNormal);
    RHO_MAP_TRACE("GoogleGeoCoding: ctor finish");
}

GoogleGeoCoding::~GoogleGeoCoding()
{
    RHO_MAP_TRACE("GoogleGeoCoding: dtor");

    //m_NetRequest.cancel();
    //CThreadQueue::stop(200);
}
/*
void GoogleGeoCoding::stop()
{
    RHO_MAP_TRACE("GoogleGeoCoding: stop");
    CThreadQueue::stop(200);
}*/

bool GoogleGeoCoding::fetchData(String const &url, void **data, size_t *datasize)
{
    RHO_MAP_TRACE1("GoogleGeoCoding: fetchData: url=%s", url.c_str());
#ifdef ENABLE_ANDROID_NET_REQUEST
    mNetRequestID = mapengine_request_make();
    int s = 0;
    int res = 0;
    res = mapengine_request_data(mNetRequestID, url.c_str(), data, &s);
    *datasize = s;
    return res > 0;
#else
 NetResponse resp = getNet().doRequest("GET", url, "", 0, 0);
    if (!resp.isOK())
        return false;
    *datasize = resp.getDataSize();
    *data = malloc(*datasize);
    if (!*data)
        return false;
    memcpy(*data, resp.getCharData(), *datasize);
    return true;
#endif
 }

void GoogleGeoCoding::resolve(String const &address, GeoCodingCallback *cb)
{
    RHO_MAP_TRACE1("GoogleGeoCoding: resolve address=%s", address.c_str());
    addQueueCommand(new Command(address, cb));
}

void GoogleGeoCoding::resolve(float latitude, float longitude, GeoCodingCallback *cb) {
    addQueueCommand(new Command(latitude, longitude, cb));
}

static bool parse_json(const char *data, double *plat, double *plon, String* adress, bool* coord_ok, bool* adress_ok)
{
    RHO_MAP_TRACE1("parse_json: data=%s", data);
    json::CJSONEntry json(data);
    const char *status = json.getString("status");
    RHO_MAP_TRACE1("parse_json: status=%s", status);
    if (strcasecmp(status, "OK") != 0)
        return false;
    bool params_founded = false;
    if (adress_ok != NULL) {
        *adress_ok = false;
    }
    if (coord_ok != NULL) {
        *coord_ok = false;
    }
    for (json::CJSONArrayIterator results = json.getEntry("results"); !results.isEnd(); results.next())
    {
        json::CJSONEntry item = results.getCurItem();

        if (item.hasName("formatted_address")) {
            json::CJSONEntry formatted_address = item.getEntry("formatted_address");
            if (adress != NULL) {
                *adress = formatted_address.getString();
            }
            params_founded = true;
            if (adress_ok != NULL) {
                *adress_ok = true;
            }
        }

        if (item.hasName("geometry")) {
            json::CJSONEntry geometry = item.getEntry("geometry");
            json::CJSONEntry location = geometry.getEntry("location");
            *plat = location.getDouble("lat");
            *plon = location.getDouble("lng");
            params_founded = true;
            if (coord_ok != NULL) {
                *coord_ok = true;
            }
        }

        if (params_founded) {
            return true;
        }
    }

    return false;
}

void GoogleGeoCoding::processCommand(IQueueCommand *pCmd)
{
    Command *cmd = (Command*)pCmd;
    GeoCodingCallback &cb = *(cmd->callback);

    String url = "http://maps.googleapis.com/maps/api/geocode/json?";

    if (cmd->is_inverse) {
        char* buf = new char[2048];
        url += "latlng=";
        sprintf(buf, "%f,%f", (float)cmd->latitude, (float)cmd->longitude);
        url += buf;
        delete[] buf;
    }
    else {
        url += "address=";
        url += net::URI::urlEncode(cmd->address);
    }
    url += "&sensor=false";

    RHO_MAP_TRACE1("GoogleGeoCoding: processCommand: url=%s", url.c_str());

    void *data;
    size_t datasize;
    if (!fetchData(url, &data, &datasize))
    {
        RAWLOG_ERROR1("Can not fetch data by url=%s", url.c_str());
        return;
    }

    RHO_MAP_TRACE("GoogleGeoCoding: processCommand: Parse received json...");

    double latitude, longitude;
    String cadress;
    bool adress_ok = false;
    bool coordinates_ok = false;

    if (parse_json((const char *)data, &latitude, &longitude, &cadress, &coordinates_ok, &adress_ok))
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: json parsed successfully");
        if (cmd->is_inverse && adress_ok) {
            cb.onSuccess(latitude, longitude, cadress.c_str());
        }
        else if (coordinates_ok) {
            if (adress_ok) {
                cb.onSuccess(latitude, longitude, cadress.c_str());
            }
            else {
                cb.onSuccess(latitude, longitude, NULL);
            }
        }
        else {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: can't found response in json");
            cb.onError("Can not found response in JSON");
        }
    }
    else
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: can't parse json");
        cb.onError("Can not parse JSON response");
    }
    /*
    char *error = 0;
    unsigned long json = rjson_tokener_parse((char const *)data, &error);
    if (!rho_ruby_is_NIL(json))
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: extract coordinates from json...");
        unsigned long coords = rho_ruby_google_geocoding_get_coordinates(json);
        if (rho_ruby_is_NIL(coords))
        {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rho_ruby_google_geocoding_get_coordinates return nil");
            cb.onError("Cannot parse received JSON object");
        }
        else
        {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rho_ruby_google_geocoding_get_coordinates return coordinates");
            double latitude = rho_ruby_google_geocoding_get_latitude(coords);
            double longitude = rho_ruby_google_geocoding_get_longitude(coords);
            RHO_MAP_TRACE2("GoogleGeoCoding: processCommand: latitude=%lf, longitude=%lf", latitude, longitude);
            cb.onSuccess(latitude, longitude);
        }
    }
    else
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rjson_tokener_parse return nil");
        cb.onError(error);
    }

    if (error)
        free (error);
    */

    free(data);
}

} // namespace map
} // namespace common
} // namespace rho

static rho::common::map::GoogleGeoCoding* ourGeocode = NULL;

static rho::common::map::GoogleGeoCoding* getGeocodeSignletone() {
    if (ourGeocode == NULL) {
        ourGeocode = new rho::common::map::GoogleGeoCoding();
    }
    return ourGeocode;
}

class RhoGoogleGeocodeCallbackImpl : public rho::common::map::GeoCodingCallback {
public:
    RhoGoogleGeocodeCallbackImpl(rho::String adress, rho::String callback, int tag) {
        mAdress = adress;
        mCallback = callback;
        mTag = tag;
    }

    virtual ~RhoGoogleGeocodeCallbackImpl() {

    }

    virtual void onError(rho::String const &description) {
        char* buf = new char[2048];

        if (buf == NULL) {
            RAWLOG_ERROR("can not allocate temporary char buffer in GeoLocation callback");
            return;
        }

        sprintf(buf,"&rho_callback=1&status=error&description=%s", description.c_str());

        char* norm_url = rho_http_normalizeurl(mCallback.c_str());
        rho_net_request_with_data(norm_url, buf);
        rho_http_free(norm_url);

        delete[] buf;
        //delete this;
    }

    virtual void onSuccess(double latitude, double longitude, const char* adress) {
        char* buf = new char[2048];

        if (buf == NULL) {
            RAWLOG_ERROR("can not allocate temporary char buffer in GeoLocation callback");
            return;
        }

        if (adress != NULL) {
            rho::String coded_adr = adress;
            coded_adr = rho::net::URI::urlEncode(coded_adr);
            sprintf(buf,"&rho_callback=1&status=ok&tag=%d&latitude=%f&longitude=%f&adress=%s", mTag, (float)latitude, (float)longitude, coded_adr.c_str());
        }
        else {
            sprintf(buf,"&rho_callback=1&status=ok&tag=%d&latitude=%f&longitude=%f", mTag, (float)latitude, (float)longitude);
        }

        char* norm_url = rho_http_normalizeurl(mCallback.c_str());
        rho_net_request_with_data(norm_url, buf);
        rho_http_free(norm_url);

        delete[] buf;
        //delete this;
    }

private:
    rho::String mAdress;
    rho::String mCallback;
    int mTag;
};

void rho_geoimpl_do_geocoding(rho_param* p, const char* callback, int callback_tag) {

    const char* c_adress = NULL;
    bool adress_setted = false;

    float longitude = 0;
    float latitude = 0;
    bool longitude_setted = false;
    bool latitude_setted = false;

    switch (p->type) {
        case RHO_PARAM_HASH: {
            for (int i = 0, lim = p->v.hash->size; i < lim; ++i) {
                const char *name = p->v.hash->name[i];
                rho_param *value = p->v.hash->value[i];

                if (strcasecmp(name, "adress") == 0) {
					c_adress = value->v.string;
                    adress_setted = true;
                }
                if (strcasecmp(name, "latitude") == 0) {
                    latitude = (float)strtod(value->v.string, NULL);
                    latitude_setted = true;
                }
                if (strcasecmp(name, "longitude") == 0) {
                    longitude_setted = true;
                    longitude = (float)strtod(value->v.string, NULL);
                }
            }
        }
        break;
        default: {
            RAWLOG_ERROR("Unexpected parameter type for do_geocoding, should be Hash");
            return;
        }
    }
    if ((c_adress == NULL) && (!latitude_setted && !longitude_setted)) {
        RAWLOG_ERROR("Unexpected parameter type for do_geocoding, should be Hash with 'adress' or 'latitude' + 'longitude' parameters");
        return;
    }

    if (adress_setted) {
        rho::String adress = c_adress;

        getGeocodeSignletone()->resolve(adress, new RhoGoogleGeocodeCallbackImpl(adress, callback, callback_tag));\
    }
    else if (latitude_setted && longitude_setted) {
        getGeocodeSignletone()->resolve(latitude, longitude, new RhoGoogleGeocodeCallbackImpl("", callback, callback_tag));
    }
    else {
        RAWLOG_ERROR("Ivalid parameters type for do_geocoding, should be Hash with 'adress' or 'latitude' + 'longitude' parameters");
    }
}

void rho_geocoding_parse_json_responce(const char* data, char* adress_buf, int max_adress_length, double* latitude, double* longitude, int* is_adress_ok, int* is_coords_ok) {

    rho::String adress;
    bool coord_ok = false;
    bool adress_ok = false;
    bool is_result = rho::common::map::parse_json(data, latitude, longitude, &adress, &coord_ok, &adress_ok);

    *is_adress_ok = 0;
    *is_coords_ok = 0;

    if (is_result) {
        if (adress_ok) {
            if (adress.length() > (max_adress_length-1)) {
                adress = adress.substr(0, max_adress_length-1);
            }
            strcpy(adress_buf, adress.c_str());
            *is_adress_ok = 1;
        }
        if (coord_ok) {
            *is_coords_ok = 1;
        }
    }

}
<commit_msg>fix map crash when network connection is down<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/map/GeocodingMapEngine.h"
#include "common/IRhoClassFactory.h"
#include "common/RhoThread.h"
#include "net/URI.h"
#include "json/JSONIterator.h"

#include "common/RhoMath.h"
#include "common/RhoConf.h"
#include "common/RhodesApp.h"
#include "common/RhoFile.h"
#include "net/INetRequest.h"

#include "ruby/ext/rho/rhoruby.h"

#undef DEFAULT_LOGCATEGORY
#define DEFAULT_LOGCATEGORY "GeocodingMapEngine"

extern "C" unsigned long rjson_tokener_parse(const char *str, char** pszError);

namespace rho
{
namespace common
{
namespace map
{

String GoogleGeoCoding::Command::toString()
{
    return address;
}

IMPLEMENT_LOGCLASS(GoogleGeoCoding,"GGeoCoding");
GoogleGeoCoding::GoogleGeoCoding()
{
#ifdef ENABLE_ANDROID_NET_REQUEST
	mNetRequestID = 0;
#endif
    CThreadQueue::setLogCategory(getLogCategory());
    RHO_MAP_TRACE("GoogleGeoCoding: ctor start");
    start(epNormal);
    RHO_MAP_TRACE("GoogleGeoCoding: ctor finish");
}

GoogleGeoCoding::~GoogleGeoCoding()
{
    RHO_MAP_TRACE("GoogleGeoCoding: dtor");

    //m_NetRequest.cancel();
    //CThreadQueue::stop(200);
}
/*
void GoogleGeoCoding::stop()
{
    RHO_MAP_TRACE("GoogleGeoCoding: stop");
    CThreadQueue::stop(200);
}*/

bool GoogleGeoCoding::fetchData(String const &url, void **data, size_t *datasize)
{
    RHO_MAP_TRACE1("GoogleGeoCoding: fetchData: url=%s", url.c_str());
#ifdef ENABLE_ANDROID_NET_REQUEST
    mNetRequestID = mapengine_request_make();
    int s = 0;
    int res = 0;
    res = mapengine_request_data(mNetRequestID, url.c_str(), data, &s);
    *datasize = s;
    return res > 0;
#else
 NetResponse resp = getNet().doRequest("GET", url, "", 0, 0);
    if (!resp.isOK())
        return false;
    *datasize = resp.getDataSize();
    *data = malloc(*datasize);
    if (!*data)
        return false;
    memcpy(*data, resp.getCharData(), *datasize);
    return true;
#endif
 }

void GoogleGeoCoding::resolve(String const &address, GeoCodingCallback *cb)
{
    RHO_MAP_TRACE1("GoogleGeoCoding: resolve address=%s", address.c_str());
    addQueueCommand(new Command(address, cb));
}

void GoogleGeoCoding::resolve(float latitude, float longitude, GeoCodingCallback *cb) {
    addQueueCommand(new Command(latitude, longitude, cb));
}

static bool parse_json(const char *data, double *plat, double *plon, String* adress, bool* coord_ok, bool* adress_ok)
{
    RHO_MAP_TRACE1("parse_json: data=%s", data);
    json::CJSONEntry json(data);
    const char *status = json.getString("status");
    RHO_MAP_TRACE1("parse_json: status=%s", (0==status)?"(null)":status);
    if ((0==status) || (strcasecmp(status, "OK") != 0))
        return false;
    bool params_founded = false;
    if (adress_ok != NULL) {
        *adress_ok = false;
    }
    if (coord_ok != NULL) {
        *coord_ok = false;
    }
    for (json::CJSONArrayIterator results = json.getEntry("results"); !results.isEnd(); results.next())
    {
        json::CJSONEntry item = results.getCurItem();

        if (item.hasName("formatted_address")) {
            json::CJSONEntry formatted_address = item.getEntry("formatted_address");
            if (adress != NULL) {
                *adress = formatted_address.getString();
            }
            params_founded = true;
            if (adress_ok != NULL) {
                *adress_ok = true;
            }
        }

        if (item.hasName("geometry")) {
            json::CJSONEntry geometry = item.getEntry("geometry");
            json::CJSONEntry location = geometry.getEntry("location");
            *plat = location.getDouble("lat");
            *plon = location.getDouble("lng");
            params_founded = true;
            if (coord_ok != NULL) {
                *coord_ok = true;
            }
        }

        if (params_founded) {
            return true;
        }
    }

    return false;
}

void GoogleGeoCoding::processCommand(IQueueCommand *pCmd)
{
    Command *cmd = (Command*)pCmd;
    GeoCodingCallback &cb = *(cmd->callback);

    String url = "http://maps.googleapis.com/maps/api/geocode/json?";

    if (cmd->is_inverse) {
        char* buf = new char[2048];
        url += "latlng=";
        sprintf(buf, "%f,%f", (float)cmd->latitude, (float)cmd->longitude);
        url += buf;
        delete[] buf;
    }
    else {
        url += "address=";
        url += net::URI::urlEncode(cmd->address);
    }
    url += "&sensor=false";

    RHO_MAP_TRACE1("GoogleGeoCoding: processCommand: url=%s", url.c_str());

    void *data;
    size_t datasize;
    if (!fetchData(url, &data, &datasize))
    {
        RAWLOG_ERROR1("Can not fetch data by url=%s", url.c_str());
        return;
    }

    RHO_MAP_TRACE("GoogleGeoCoding: processCommand: Parse received json...");

    double latitude, longitude;
    String cadress;
    bool adress_ok = false;
    bool coordinates_ok = false;

    if (parse_json((const char *)data, &latitude, &longitude, &cadress, &coordinates_ok, &adress_ok))
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: json parsed successfully");
        if (cmd->is_inverse && adress_ok) {
            cb.onSuccess(latitude, longitude, cadress.c_str());
        }
        else if (coordinates_ok) {
            if (adress_ok) {
                cb.onSuccess(latitude, longitude, cadress.c_str());
            }
            else {
                cb.onSuccess(latitude, longitude, NULL);
            }
        }
        else {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: can't found response in json");
            cb.onError("Can not found response in JSON");
        }
    }
    else
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: can't parse json");
        cb.onError("Can not parse JSON response");
    }
    /*
    char *error = 0;
    unsigned long json = rjson_tokener_parse((char const *)data, &error);
    if (!rho_ruby_is_NIL(json))
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: extract coordinates from json...");
        unsigned long coords = rho_ruby_google_geocoding_get_coordinates(json);
        if (rho_ruby_is_NIL(coords))
        {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rho_ruby_google_geocoding_get_coordinates return nil");
            cb.onError("Cannot parse received JSON object");
        }
        else
        {
            RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rho_ruby_google_geocoding_get_coordinates return coordinates");
            double latitude = rho_ruby_google_geocoding_get_latitude(coords);
            double longitude = rho_ruby_google_geocoding_get_longitude(coords);
            RHO_MAP_TRACE2("GoogleGeoCoding: processCommand: latitude=%lf, longitude=%lf", latitude, longitude);
            cb.onSuccess(latitude, longitude);
        }
    }
    else
    {
        RHO_MAP_TRACE("GoogleGeoCoding: processCommand: rjson_tokener_parse return nil");
        cb.onError(error);
    }

    if (error)
        free (error);
    */

    free(data);
}

} // namespace map
} // namespace common
} // namespace rho

static rho::common::map::GoogleGeoCoding* ourGeocode = NULL;

static rho::common::map::GoogleGeoCoding* getGeocodeSignletone() {
    if (ourGeocode == NULL) {
        ourGeocode = new rho::common::map::GoogleGeoCoding();
    }
    return ourGeocode;
}

class RhoGoogleGeocodeCallbackImpl : public rho::common::map::GeoCodingCallback {
public:
    RhoGoogleGeocodeCallbackImpl(rho::String adress, rho::String callback, int tag) {
        mAdress = adress;
        mCallback = callback;
        mTag = tag;
    }

    virtual ~RhoGoogleGeocodeCallbackImpl() {

    }

    virtual void onError(rho::String const &description) {
        char* buf = new char[2048];

        if (buf == NULL) {
            RAWLOG_ERROR("can not allocate temporary char buffer in GeoLocation callback");
            return;
        }

        sprintf(buf,"&rho_callback=1&status=error&description=%s", description.c_str());

        char* norm_url = rho_http_normalizeurl(mCallback.c_str());
        rho_net_request_with_data(norm_url, buf);
        rho_http_free(norm_url);

        delete[] buf;
        //delete this;
    }

    virtual void onSuccess(double latitude, double longitude, const char* adress) {
        char* buf = new char[2048];

        if (buf == NULL) {
            RAWLOG_ERROR("can not allocate temporary char buffer in GeoLocation callback");
            return;
        }

        if (adress != NULL) {
            rho::String coded_adr = adress;
            coded_adr = rho::net::URI::urlEncode(coded_adr);
            sprintf(buf,"&rho_callback=1&status=ok&tag=%d&latitude=%f&longitude=%f&adress=%s", mTag, (float)latitude, (float)longitude, coded_adr.c_str());
        }
        else {
            sprintf(buf,"&rho_callback=1&status=ok&tag=%d&latitude=%f&longitude=%f", mTag, (float)latitude, (float)longitude);
        }

        char* norm_url = rho_http_normalizeurl(mCallback.c_str());
        rho_net_request_with_data(norm_url, buf);
        rho_http_free(norm_url);

        delete[] buf;
        //delete this;
    }

private:
    rho::String mAdress;
    rho::String mCallback;
    int mTag;
};

void rho_geoimpl_do_geocoding(rho_param* p, const char* callback, int callback_tag) {

    const char* c_adress = NULL;
    bool adress_setted = false;

    float longitude = 0;
    float latitude = 0;
    bool longitude_setted = false;
    bool latitude_setted = false;

    switch (p->type) {
        case RHO_PARAM_HASH: {
            for (int i = 0, lim = p->v.hash->size; i < lim; ++i) {
                const char *name = p->v.hash->name[i];
                rho_param *value = p->v.hash->value[i];

                if (strcasecmp(name, "adress") == 0) {
					c_adress = value->v.string;
                    adress_setted = true;
                }
                if (strcasecmp(name, "latitude") == 0) {
                    latitude = (float)strtod(value->v.string, NULL);
                    latitude_setted = true;
                }
                if (strcasecmp(name, "longitude") == 0) {
                    longitude_setted = true;
                    longitude = (float)strtod(value->v.string, NULL);
                }
            }
        }
        break;
        default: {
            RAWLOG_ERROR("Unexpected parameter type for do_geocoding, should be Hash");
            return;
        }
    }
    if ((c_adress == NULL) && (!latitude_setted && !longitude_setted)) {
        RAWLOG_ERROR("Unexpected parameter type for do_geocoding, should be Hash with 'adress' or 'latitude' + 'longitude' parameters");
        return;
    }

    if (adress_setted) {
        rho::String adress = c_adress;

        getGeocodeSignletone()->resolve(adress, new RhoGoogleGeocodeCallbackImpl(adress, callback, callback_tag));\
    }
    else if (latitude_setted && longitude_setted) {
        getGeocodeSignletone()->resolve(latitude, longitude, new RhoGoogleGeocodeCallbackImpl("", callback, callback_tag));
    }
    else {
        RAWLOG_ERROR("Ivalid parameters type for do_geocoding, should be Hash with 'adress' or 'latitude' + 'longitude' parameters");
    }
}

void rho_geocoding_parse_json_responce(const char* data, char* adress_buf, int max_adress_length, double* latitude, double* longitude, int* is_adress_ok, int* is_coords_ok) {

    rho::String adress;
    bool coord_ok = false;
    bool adress_ok = false;
    bool is_result = rho::common::map::parse_json(data, latitude, longitude, &adress, &coord_ok, &adress_ok);

    *is_adress_ok = 0;
    *is_coords_ok = 0;

    if (is_result) {
        if (adress_ok) {
            if (adress.length() > (max_adress_length-1)) {
                adress = adress.substr(0, max_adress_length-1);
            }
            strcpy(adress_buf, adress.c_str());
            *is_adress_ok = 1;
        }
        if (coord_ok) {
            *is_coords_ok = 1;
        }
    }

}
<|endoftext|>


<commit_before>#include "Calc.hpp"
#include<iostream>

using namespace std;

namespace ModernCppCI {

    Calc::Calc() {
        this->addOperation("+", add);
        this->addOperation("-", sub);
        this->addOperation("*", mul);
        this->addOperation("/", div);
    }

    Calc::Calc(const Calc &other) : Calc() {
        this->operations = other.operations;
        this->steps = other.steps;
    }

	Calc & Calc::operator=(const Calc & other)
	{
		this->operations = other.operations;
		this->steps = other.steps;

		return *this;
	}

    void Calc::addOperation(string name, Operation operation) {
        this->operations[name] = operation;
    }

    unsigned int Calc::totalOperations() {
        return this->operations.size();
    }

    Calc Calc::operator[](string name) {
        auto operation = this->operations[name];

        if (operation == nullptr) {
            operation = NoP;
        }

        auto step = CalcStep(operation);
        this->steps.push_back(step);

        return Calc(*this);
    }

    Calc Calc::operator[](int value) {
        auto step = CalcStep(value);
        this->steps.push_back(step);

        return Calc(*this);
    }

    unsigned int Calc::totalSteps() {
        return steps.size();
    }

    int Calc::result() const {
        int total = 0;
        Operation lastOperation = NoP;
        bool nextExecute = false;
        bool firstValue = true;

        for (auto step : steps) {
            if (step.hasOperation()) {
                lastOperation = step.getOperation();
                nextExecute = true;
                continue;
            }

            if (step.hasValue()) {

                if (firstValue) {
                    total = step.getValue();
                    firstValue = false;
                    continue;
                }

                if (nextExecute) {
                    total = lastOperation(total, step.getValue());
                    nextExecute = false;
                }
            }
        }

        return total;
    }

    Operation Calc::add = [](int value1, int value2) { return value1 + value2; };
    Operation Calc::sub = [](int value1, int value2) { return value1 - value2; };
    Operation Calc::mul = [](int value1, int value2) { return value1 * value2; };
    Operation Calc::div = [](int value1, int value2) { return value1 / value2; };
    Operation Calc::NoP = [](int value1, int value2) { return 0; };

    CalcStep::CalcStep() {
        this->_hasValue = false;
        this->_hasOperation = false;
    }

    CalcStep::CalcStep(int value) : CalcStep() {
        this->_value = value;
        this->_hasValue = true;
    }

    CalcStep::CalcStep(Operation operation) : CalcStep() {
        this->_operation = operation;
        this->_hasOperation = true;
    }

    bool CalcStep::hasValue() {
        return _hasValue;
    }

    bool CalcStep::hasOperation() {
        return _hasOperation;
    }

    int CalcStep::getValue() {
        return _value;
    }

    Operation CalcStep::getOperation() {
        return _operation;
    }

    std::ostream &operator<<(std::ostream &stream, const Calc &calc) {
        stream << calc.result();

        return stream;
    }

}
<commit_msg>minor change<commit_after>#include "Calc.hpp"
#include<iostream>

using namespace std;

namespace ModernCppCI {

    Calc::Calc() {
        this->addOperation("+", add);
        this->addOperation("-", sub);
        this->addOperation("*", mul);
        this->addOperation("/", div);
    }

    Calc::Calc(const Calc &other) : Calc() {
        this->operations = other.operations;
        this->steps = other.steps;
    }

	Calc & Calc::operator=(const Calc &other)
	{
		this->operations = other.operations;
		this->steps = other.steps;

		return *this;
	}

    void Calc::addOperation(string name, Operation operation) {
        this->operations[name] = operation;
    }

    unsigned int Calc::totalOperations() {
        return this->operations.size();
    }

    Calc Calc::operator[](string name) {
        auto operation = this->operations[name];

        if (operation == nullptr) {
            operation = NoP;
        }

        auto step = CalcStep(operation);
        this->steps.push_back(step);

        return Calc(*this);
    }

    Calc Calc::operator[](int value) {
        auto step = CalcStep(value);
        this->steps.push_back(step);

        return Calc(*this);
    }

    unsigned int Calc::totalSteps() {
        return steps.size();
    }

    int Calc::result() const {
        int total = 0;
        Operation lastOperation = NoP;
        bool nextExecute = false;
        bool firstValue = true;

        for (auto step : steps) {
            if (step.hasOperation()) {
                lastOperation = step.getOperation();
                nextExecute = true;
                continue;
            }

            if (step.hasValue()) {

                if (firstValue) {
                    total = step.getValue();
                    firstValue = false;
                    continue;
                }

                if (nextExecute) {
                    total = lastOperation(total, step.getValue());
                    nextExecute = false;
                }
            }
        }

        return total;
    }

    Operation Calc::add = [](int value1, int value2) { return value1 + value2; };
    Operation Calc::sub = [](int value1, int value2) { return value1 - value2; };
    Operation Calc::mul = [](int value1, int value2) { return value1 * value2; };
    Operation Calc::div = [](int value1, int value2) { return value1 / value2; };
    Operation Calc::NoP = [](int value1, int value2) { return 0; };

    CalcStep::CalcStep() {
        this->_hasValue = false;
        this->_hasOperation = false;
    }

    CalcStep::CalcStep(int value) : CalcStep() {
        this->_value = value;
        this->_hasValue = true;
    }

    CalcStep::CalcStep(Operation operation) : CalcStep() {
        this->_operation = operation;
        this->_hasOperation = true;
    }

    bool CalcStep::hasValue() {
        return _hasValue;
    }

    bool CalcStep::hasOperation() {
        return _hasOperation;
    }

    int CalcStep::getValue() {
        return _value;
    }

    Operation CalcStep::getOperation() {
        return _operation;
    }

    std::ostream &operator<<(std::ostream &stream, const Calc &calc) {
        stream << calc.result();

        return stream;
    }

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/script/XLibraryContainer.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/uno/Reference.h>
#include <basic/basrdll.hxx>
#include <tools/urlobj.hxx>
#include <svl/macitem.hxx>
#include <basic/sbxfac.hxx>
#include <basic/sbx.hxx>
#include <vcl/gradient.hxx>
#include <svl/rectitem.hxx>
#include <svl/intitem.hxx>
#include <svl/eitem.hxx>
#include <basic/sbmod.hxx>
#include <svl/whiter.hxx>
#include <basic/sbmeth.hxx>
#include <basic/sbstar.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/msgbox.hxx>
#include <basic/sbuno.hxx>
#include <svtools/sfxecode.hxx>
#include <svtools/ehdl.hxx>

#include <unotools/undoopt.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/useroptions.hxx>
#include <unotools/bootstrap.hxx>

#include <sfx2/appuno.hxx>
#include <sfx2/module.hxx>
#include "arrdecl.hxx"
#include <sfx2/app.hxx>
#include "sfxtypes.hxx"
#include "sfx2/sfxresid.hxx"
#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/progress.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/objitem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/dispatch.hxx>
#include "sfx2/tplpitem.hxx"
#include "sfx2/minfitem.hxx"
#include "app.hrc"
#include <sfx2/evntconf.hxx>
#include <sfx2/request.hxx>
#include <sfx2/dinfdlg.hxx>
#include "appdata.hxx"
#include "appbas.hxx"
#include "sfx2/sfxhelp.hxx"
#include "sfx2/basmgr.hxx"
#include "sorgitm.hxx"
#include "appbaslib.hxx"
#include <basic/basicmanagerrepository.hxx>

#define ITEMID_SEARCH SID_SEARCH_ITEM

#include <svl/srchitem.hxx>
#include <osl/socket.hxx>

#define SFX_TYPEMAP
#define Selection
#include "sfxslots.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::script;

using ::basic::BasicManagerRepository;

//------------------------------------------------------------------------
String lcl_GetVersionString()
{
    ::rtl::OUString aDefault;
    String aVersion( utl::Bootstrap::getBuildIdData( aDefault ));

    if ( aVersion.Len() == 0 )
    {
        OSL_FAIL( "No BUILDID in bootstrap file found" );
    }

    aVersion.Erase( 0, aVersion.Search( ':' ) + 1 );
    aVersion.Erase( aVersion.Search( ')' ) );
    return aVersion;
}

//=========================================================================
sal_uInt16 SfxApplication::SaveBasicManager() const
{
    return 0;
}

//--------------------------------------------------------------------
sal_uInt16 SfxApplication::SaveBasicAndDialogContainer() const
{
    if ( pAppData_Impl->pBasicManager->isValid() )
        pAppData_Impl->pBasicManager->storeAllLibraries();
    return 0;
}

//--------------------------------------------------------------------

SbxVariable* MakeVariable( StarBASIC *pBas, SbxObject *pObject,
           const char *pName, sal_uInt32 nSID, SbxDataType eType, SbxClassType eClassType )
{
    SbxVariable *pVar = pBas->Make( String::CreateFromAscii(pName), eClassType, eType ); //SbxCLASS_PROPERTY
    pVar->SetUserData( nSID );
    pVar->SetFlag( SBX_DONTSTORE );
    pObject->StartListening( pVar->GetBroadcaster() );
    return pVar;
}

//--------------------------------------------------------------------

BasicManager* SfxApplication::GetBasicManager()
{
    return BasicManagerRepository::getApplicationBasicManager( true );
}

//--------------------------------------------------------------------

Reference< XLibraryContainer > SfxApplication::GetDialogContainer()
{
    if ( !pAppData_Impl->pBasicManager->isValid() )
        GetBasicManager();
    return pAppData_Impl->pBasicManager->getLibraryContainer( SfxBasicManagerHolder::DIALOGS );
}

//--------------------------------------------------------------------

Reference< XLibraryContainer > SfxApplication::GetBasicContainer()
{
    if ( !pAppData_Impl->pBasicManager->isValid() )
        GetBasicManager();
    return pAppData_Impl->pBasicManager->getLibraryContainer( SfxBasicManagerHolder::SCRIPTS );
}

//--------------------------------------------------------------------

StarBASIC* SfxApplication::GetBasic()
{
    return GetBasicManager()->GetLib(0);
}

//-------------------------------------------------------------------------
void SfxApplication::PropExec_Impl( SfxRequest &rReq )
{
    rReq.GetArgs();
    sal_uInt16 nSID = rReq.GetSlot();
    switch ( nSID )
    {
        case SID_CREATE_BASICOBJECT:
        {
            SFX_REQUEST_ARG(rReq, pItem, SfxStringItem, nSID, sal_False);
            if ( pItem )
            {
                SbxObject* pObject = SbxBase::CreateObject( pItem->GetValue() );
                pObject->AddRef();
                rReq.Done();
            }
            break;
        }

        case SID_DELETE_BASICOBJECT:
        {
            break;
        }

        case SID_ATTR_UNDO_COUNT:
        {
            SFX_REQUEST_ARG(rReq, pCountItem, SfxUInt16Item, nSID, sal_False);
            SvtUndoOptions().SetUndoCount( pCountItem->GetValue() );
            break;
        }

        case SID_WIN_VISIBLE:
        {
            break;
        }

        case SID_STATUSBARTEXT:
        {
            SFX_REQUEST_ARG(rReq, pStringItem, SfxStringItem, nSID, sal_False);
            String aText = pStringItem->GetValue();
            if ( aText.Len() )
                GetpApp()->ShowStatusText( aText );
            else
                GetpApp()->HideStatusText();
            break;
        }

        case SID_OFFICE_PRIVATE_USE:
        case SID_OFFICE_COMMERCIAL_USE:
        {
            DBG_ASSERT( sal_False, "SfxApplication::PropExec_Impl()\nSID_OFFICE_PRIVATE_USE & SID_OFFICE_COMMERCIAL_USE are obsolete!\n" );
            break;
        }

        case SID_OFFICE_CUSTOMERNUMBER:
        {
            SFX_REQUEST_ARG(rReq, pStringItem, SfxStringItem, nSID, sal_False);

            if ( pStringItem )
                SvtUserOptions().SetCustomerNumber( pStringItem->GetValue() );
            break;
        }
    }
}

//-------------------------------------------------------------------------
void SfxApplication::PropState_Impl( SfxItemSet &rSet )
{
    SfxWhichIter aIter(rSet);
    for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
    {
        switch ( nSID )
        {
            case SID_PROGNAME:
                rSet.Put( SfxStringItem( SID_PROGNAME, GetName() ) );
                break;

            case SID_ACTIVEDOCUMENT:
                rSet.Put( SfxObjectItem( SID_ACTIVEDOCUMENT, SfxObjectShell::Current() ) );
                break;

            case SID_APPLICATION:
                rSet.Put( SfxObjectItem( SID_APPLICATION, this ) );
                break;

            case SID_PROGFILENAME:
                rSet.Put( SfxStringItem( SID_PROGFILENAME, Application::GetAppFileName() ) );
                break;

            case SID_ATTR_UNDO_COUNT:
                rSet.Put( SfxUInt16Item( SID_ATTR_UNDO_COUNT, sal::static_int_cast< sal_uInt16 >( SvtUndoOptions().GetUndoCount() ) ) );
                break;

            case SID_UPDATE_VERSION:
                rSet.Put( SfxUInt32Item( SID_UPDATE_VERSION, SUPD ) );
                break;

            case SID_OFFICE_CUSTOMERNUMBER:
            {
                rSet.Put( SfxStringItem( nSID, SvtUserOptions().GetCustomerNumber() ) );
                break;
            }
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>remove unused lcl_GetVersionString<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/script/XLibraryContainer.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/uno/Reference.h>
#include <basic/basrdll.hxx>
#include <tools/urlobj.hxx>
#include <svl/macitem.hxx>
#include <basic/sbxfac.hxx>
#include <basic/sbx.hxx>
#include <vcl/gradient.hxx>
#include <svl/rectitem.hxx>
#include <svl/intitem.hxx>
#include <svl/eitem.hxx>
#include <basic/sbmod.hxx>
#include <svl/whiter.hxx>
#include <basic/sbmeth.hxx>
#include <basic/sbstar.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/msgbox.hxx>
#include <basic/sbuno.hxx>
#include <svtools/sfxecode.hxx>
#include <svtools/ehdl.hxx>

#include <unotools/undoopt.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/useroptions.hxx>
#include <unotools/bootstrap.hxx>

#include <sfx2/appuno.hxx>
#include <sfx2/module.hxx>
#include "arrdecl.hxx"
#include <sfx2/app.hxx>
#include "sfxtypes.hxx"
#include "sfx2/sfxresid.hxx"
#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/progress.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/objitem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/dispatch.hxx>
#include "sfx2/tplpitem.hxx"
#include "sfx2/minfitem.hxx"
#include "app.hrc"
#include <sfx2/evntconf.hxx>
#include <sfx2/request.hxx>
#include <sfx2/dinfdlg.hxx>
#include "appdata.hxx"
#include "appbas.hxx"
#include "sfx2/sfxhelp.hxx"
#include "sfx2/basmgr.hxx"
#include "sorgitm.hxx"
#include "appbaslib.hxx"
#include <basic/basicmanagerrepository.hxx>

#define ITEMID_SEARCH SID_SEARCH_ITEM

#include <svl/srchitem.hxx>
#include <osl/socket.hxx>

#define SFX_TYPEMAP
#define Selection
#include "sfxslots.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::script;

using ::basic::BasicManagerRepository;

//=========================================================================
sal_uInt16 SfxApplication::SaveBasicManager() const
{
    return 0;
}

//--------------------------------------------------------------------
sal_uInt16 SfxApplication::SaveBasicAndDialogContainer() const
{
    if ( pAppData_Impl->pBasicManager->isValid() )
        pAppData_Impl->pBasicManager->storeAllLibraries();
    return 0;
}

//--------------------------------------------------------------------

SbxVariable* MakeVariable( StarBASIC *pBas, SbxObject *pObject,
           const char *pName, sal_uInt32 nSID, SbxDataType eType, SbxClassType eClassType )
{
    SbxVariable *pVar = pBas->Make( String::CreateFromAscii(pName), eClassType, eType ); //SbxCLASS_PROPERTY
    pVar->SetUserData( nSID );
    pVar->SetFlag( SBX_DONTSTORE );
    pObject->StartListening( pVar->GetBroadcaster() );
    return pVar;
}

//--------------------------------------------------------------------

BasicManager* SfxApplication::GetBasicManager()
{
    return BasicManagerRepository::getApplicationBasicManager( true );
}

//--------------------------------------------------------------------

Reference< XLibraryContainer > SfxApplication::GetDialogContainer()
{
    if ( !pAppData_Impl->pBasicManager->isValid() )
        GetBasicManager();
    return pAppData_Impl->pBasicManager->getLibraryContainer( SfxBasicManagerHolder::DIALOGS );
}

//--------------------------------------------------------------------

Reference< XLibraryContainer > SfxApplication::GetBasicContainer()
{
    if ( !pAppData_Impl->pBasicManager->isValid() )
        GetBasicManager();
    return pAppData_Impl->pBasicManager->getLibraryContainer( SfxBasicManagerHolder::SCRIPTS );
}

//--------------------------------------------------------------------

StarBASIC* SfxApplication::GetBasic()
{
    return GetBasicManager()->GetLib(0);
}

//-------------------------------------------------------------------------
void SfxApplication::PropExec_Impl( SfxRequest &rReq )
{
    rReq.GetArgs();
    sal_uInt16 nSID = rReq.GetSlot();
    switch ( nSID )
    {
        case SID_CREATE_BASICOBJECT:
        {
            SFX_REQUEST_ARG(rReq, pItem, SfxStringItem, nSID, sal_False);
            if ( pItem )
            {
                SbxObject* pObject = SbxBase::CreateObject( pItem->GetValue() );
                pObject->AddRef();
                rReq.Done();
            }
            break;
        }

        case SID_DELETE_BASICOBJECT:
        {
            break;
        }

        case SID_ATTR_UNDO_COUNT:
        {
            SFX_REQUEST_ARG(rReq, pCountItem, SfxUInt16Item, nSID, sal_False);
            SvtUndoOptions().SetUndoCount( pCountItem->GetValue() );
            break;
        }

        case SID_WIN_VISIBLE:
        {
            break;
        }

        case SID_STATUSBARTEXT:
        {
            SFX_REQUEST_ARG(rReq, pStringItem, SfxStringItem, nSID, sal_False);
            String aText = pStringItem->GetValue();
            if ( aText.Len() )
                GetpApp()->ShowStatusText( aText );
            else
                GetpApp()->HideStatusText();
            break;
        }

        case SID_OFFICE_PRIVATE_USE:
        case SID_OFFICE_COMMERCIAL_USE:
        {
            DBG_ASSERT( sal_False, "SfxApplication::PropExec_Impl()\nSID_OFFICE_PRIVATE_USE & SID_OFFICE_COMMERCIAL_USE are obsolete!\n" );
            break;
        }

        case SID_OFFICE_CUSTOMERNUMBER:
        {
            SFX_REQUEST_ARG(rReq, pStringItem, SfxStringItem, nSID, sal_False);

            if ( pStringItem )
                SvtUserOptions().SetCustomerNumber( pStringItem->GetValue() );
            break;
        }
    }
}

//-------------------------------------------------------------------------
void SfxApplication::PropState_Impl( SfxItemSet &rSet )
{
    SfxWhichIter aIter(rSet);
    for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
    {
        switch ( nSID )
        {
            case SID_PROGNAME:
                rSet.Put( SfxStringItem( SID_PROGNAME, GetName() ) );
                break;

            case SID_ACTIVEDOCUMENT:
                rSet.Put( SfxObjectItem( SID_ACTIVEDOCUMENT, SfxObjectShell::Current() ) );
                break;

            case SID_APPLICATION:
                rSet.Put( SfxObjectItem( SID_APPLICATION, this ) );
                break;

            case SID_PROGFILENAME:
                rSet.Put( SfxStringItem( SID_PROGFILENAME, Application::GetAppFileName() ) );
                break;

            case SID_ATTR_UNDO_COUNT:
                rSet.Put( SfxUInt16Item( SID_ATTR_UNDO_COUNT, sal::static_int_cast< sal_uInt16 >( SvtUndoOptions().GetUndoCount() ) ) );
                break;

            case SID_UPDATE_VERSION:
                rSet.Put( SfxUInt32Item( SID_UPDATE_VERSION, SUPD ) );
                break;

            case SID_OFFICE_CUSTOMERNUMBER:
            {
                rSet.Put( SfxStringItem( nSID, SvtUserOptions().GetCustomerNumber() ) );
                break;
            }
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Parameter.h"
#include "IECore/CompoundObject.h"

#include "IECorePython/ParameterBinding.h"
#include "IECorePython/RunTimeTypedBinding.h"

using namespace std;
using namespace boost;
using namespace boost::python;
using namespace IECore;
using namespace IECorePython;

namespace
{

static ObjectPtr defaultValue( Parameter &that )
{
	return that.defaultValue()->copy();
}

static ObjectPtr getValue( Parameter &that )
{
	return that.getValue();
}

static ObjectPtr getValidatedValue( Parameter &that )
{
	return that.getValidatedValue();
}

static void validate( Parameter &that, ObjectPtr value )
{
	that.validate( value.get() );
}

static dict getPresets( Parameter &that )
{
	dict result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result[it->first] = it->second->copy();
	}
	return result;
}

static void setPresets( Parameter &p, const object &presets )
{
	p.setPresets( parameterPresets<Parameter::PresetsContainer>( presets ) );
}

static boost::python::tuple presetNames( const Parameter &that )
{
	boost::python::list result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.append( it->first );
	}
	return boost::python::tuple( result );
}

static boost::python::tuple presetValues( const Parameter &that )
{
	boost::python::list result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.append( it->second->copy() );
	}
	return boost::python::tuple( result );
}

static CompoundObjectPtr userData( Parameter &that )
{
	return that.userData();
}

} // namespace

namespace IECorePython
{

void bindParameter()
{
	using boost::python::arg;

	ParameterClass<Parameter, ParameterWrapper<Parameter> >()
		.def(
			init< const std::string &, const std::string &, ObjectPtr, boost::python::optional<const boost::python::object &, bool, CompoundObjectPtr > >
			(
				(
					arg( "name" ),
					arg( "description" ),
					arg( "defaultValue" ),
					arg( "presets" ) = boost::python::tuple(),
					arg( "presetsOnly" ) = false ,
					arg( "userData" ) = CompoundObject::Ptr( 0 )
				)
			)
		)
		.add_property( "name", make_function( &Parameter::name, return_value_policy<copy_const_reference>() ) )
		.add_property( "description", make_function( &Parameter::description, return_value_policy<copy_const_reference>() ) )
		.add_property( "defaultValue", &defaultValue )
		.def( "setValue", (void (Parameter::*)( ObjectPtr ))&Parameter::setValue )
		.def( "setValue", (void (Parameter::*)( const std::string & ))&Parameter::setValue )
		.def( "setValidatedValue", &Parameter::setValidatedValue )
		.def( "getValue", &getValue )
		.def( "getValidatedValue", &getValidatedValue )
		.def( "getCurrentPresetName", &Parameter::getCurrentPresetName )
		.def( "validate", (void (Parameter::*)() const)&Parameter::validate )
		.def( "validate", &validate )
		.add_property( "presetsOnly", &Parameter::presetsOnly )
		.def( "getPresets", &getPresets, "Returns a dictionary containing presets for the parameter." )
		.def( "setPresets", &setPresets, "Sets the presets for the parameter from a dictionary." )
		.def( "presetNames", &presetNames, "Returns a tuple containing the names of all presets for the parameter." )
		.def( "presetValues", &presetValues, "Returns a tuple containing the values of all presets for the parameter." )
		.def( "userData", &userData )
	;

}

} // namespace IECorePython
<commit_msg>ParameterBinding : Remove unnecessary `static` keywords<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Parameter.h"
#include "IECore/CompoundObject.h"

#include "IECorePython/ParameterBinding.h"
#include "IECorePython/RunTimeTypedBinding.h"

using namespace std;
using namespace boost;
using namespace boost::python;
using namespace IECore;
using namespace IECorePython;

namespace
{

ObjectPtr defaultValue( Parameter &that )
{
	return that.defaultValue()->copy();
}

ObjectPtr getValue( Parameter &that )
{
	return that.getValue();
}

ObjectPtr getValidatedValue( Parameter &that )
{
	return that.getValidatedValue();
}

void validate( Parameter &that, ObjectPtr value )
{
	that.validate( value.get() );
}

dict getPresets( Parameter &that )
{
	dict result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result[it->first] = it->second->copy();
	}
	return result;
}

void setPresets( Parameter &p, const object &presets )
{
	p.setPresets( parameterPresets<Parameter::PresetsContainer>( presets ) );
}

boost::python::tuple presetNames( const Parameter &that )
{
	boost::python::list result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.append( it->first );
	}
	return boost::python::tuple( result );
}

boost::python::tuple presetValues( const Parameter &that )
{
	boost::python::list result;
	const Parameter::PresetsContainer &p = that.getPresets();
	for( Parameter::PresetsContainer::const_iterator it=p.begin(); it!=p.end(); it++ )
	{
		result.append( it->second->copy() );
	}
	return boost::python::tuple( result );
}

CompoundObjectPtr userData( Parameter &that )
{
	return that.userData();
}

} // namespace

namespace IECorePython
{

void bindParameter()
{
	using boost::python::arg;

	ParameterClass<Parameter, ParameterWrapper<Parameter> >()
		.def(
			init< const std::string &, const std::string &, ObjectPtr, boost::python::optional<const boost::python::object &, bool, CompoundObjectPtr > >
			(
				(
					arg( "name" ),
					arg( "description" ),
					arg( "defaultValue" ),
					arg( "presets" ) = boost::python::tuple(),
					arg( "presetsOnly" ) = false ,
					arg( "userData" ) = CompoundObject::Ptr( 0 )
				)
			)
		)
		.add_property( "name", make_function( &Parameter::name, return_value_policy<copy_const_reference>() ) )
		.add_property( "description", make_function( &Parameter::description, return_value_policy<copy_const_reference>() ) )
		.add_property( "defaultValue", &defaultValue )
		.def( "setValue", (void (Parameter::*)( ObjectPtr ))&Parameter::setValue )
		.def( "setValue", (void (Parameter::*)( const std::string & ))&Parameter::setValue )
		.def( "setValidatedValue", &Parameter::setValidatedValue )
		.def( "getValue", &getValue )
		.def( "getValidatedValue", &getValidatedValue )
		.def( "getCurrentPresetName", &Parameter::getCurrentPresetName )
		.def( "validate", (void (Parameter::*)() const)&Parameter::validate )
		.def( "validate", &validate )
		.add_property( "presetsOnly", &Parameter::presetsOnly )
		.def( "getPresets", &getPresets, "Returns a dictionary containing presets for the parameter." )
		.def( "setPresets", &setPresets, "Sets the presets for the parameter from a dictionary." )
		.def( "presetNames", &presetNames, "Returns a tuple containing the names of all presets for the parameter." )
		.def( "presetValues", &presetValues, "Returns a tuple containing the values of all presets for the parameter." )
		.def( "userData", &userData )
	;

}

} // namespace IECorePython
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>
#include <utility>  // std::pair
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"

using namespace utest::v1;

#define PATTERN_CHECK_VALUE  0xF0F0ADAD

class CppTestCaseHelperClass {
private:
    const char *name;
    const unsigned pattern;

public:
    CppTestCaseHelperClass(const char *_name) : name(_name), pattern(PATTERN_CHECK_VALUE)
    {
        print("init");
    }

    void print(const char *message)
    {
        printf("%s::%s\n", name, message);
    }

    bool check_init(void)
    {
        bool result = (pattern == PATTERN_CHECK_VALUE);
        print(result ? "check_init: OK" : "check_init: ERROR");
        return result;
    }

    void stack_test(void)
    {
        print("stack_test");
        CppTestCaseHelperClass t("Stack");
        t.hello();
    }

    void hello(void)
    {
        print("hello");
    }

    ~CppTestCaseHelperClass()
    {
        print("destroy");
    }
};

void test_case_basic()
{
    TEST_ASSERT_TRUE(true);
    TEST_ASSERT_FALSE(false);
    TEST_ASSERT_EQUAL_STRING("The quick brown fox jumps over the lazy dog",
                             "The quick brown fox jumps over the lazy dog");
}

void test_case_blinky()
{
    static DigitalOut myled(LED1);
    const int cnt_max = 1024;
    for (int cnt = 0; cnt < cnt_max; ++cnt) {
        myled = !myled;
    }
}

void test_case_cpp_stack()
{
    // Check C++ start-up initialisation
    CppTestCaseHelperClass s("Static");

    // Global stack object simple test
    s.stack_test();
    TEST_ASSERT_TRUE_MESSAGE(s.check_init(), "s.check_init() failed");
}

void test_case_cpp_heap()
{
    // Heap test object simple test
    CppTestCaseHelperClass *m = new CppTestCaseHelperClass("Heap");
    m->hello();
    TEST_ASSERT_TRUE_MESSAGE(m->check_init(), "m->check_init() failed");
    delete m;
}

utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
    greentea_case_failure_abort_handler(source, reason);
    return STATUS_CONTINUE;
}

// Generic test cases
Case cases[] = {
    Case("Basic", test_case_basic, greentea_failure_handler),
    Case("Blinky", test_case_blinky, greentea_failure_handler),
    Case("C++ stack", test_case_cpp_stack, greentea_failure_handler),
    Case("C++ heap", test_case_cpp_heap, greentea_failure_handler)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(20, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
    Harness::run(specification);
}
<commit_msg>generic_tests update for targets without LED1<commit_after>/*
 * Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>
#include <utility>  // std::pair
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"

using namespace utest::v1;

#define PATTERN_CHECK_VALUE  0xF0F0ADAD

class CppTestCaseHelperClass {
private:
    const char *name;
    const unsigned pattern;

public:
    CppTestCaseHelperClass(const char *_name) : name(_name), pattern(PATTERN_CHECK_VALUE)
    {
        print("init");
    }

    void print(const char *message)
    {
        printf("%s::%s\n", name, message);
    }

    bool check_init(void)
    {
        bool result = (pattern == PATTERN_CHECK_VALUE);
        print(result ? "check_init: OK" : "check_init: ERROR");
        return result;
    }

    void stack_test(void)
    {
        print("stack_test");
        CppTestCaseHelperClass t("Stack");
        t.hello();
    }

    void hello(void)
    {
        print("hello");
    }

    ~CppTestCaseHelperClass()
    {
        print("destroy");
    }
};

void test_case_basic()
{
    TEST_ASSERT_TRUE(true);
    TEST_ASSERT_FALSE(false);
    TEST_ASSERT_EQUAL_STRING("The quick brown fox jumps over the lazy dog",
                             "The quick brown fox jumps over the lazy dog");
}

#ifdef LED1
void test_case_blinky()
{
    static DigitalOut myled(LED1);
    const int cnt_max = 1024;
    for (int cnt = 0; cnt < cnt_max; ++cnt) {
        myled = !myled;
    }
}
#endif

void test_case_cpp_stack()
{
    // Check C++ start-up initialisation
    CppTestCaseHelperClass s("Static");

    // Global stack object simple test
    s.stack_test();
    TEST_ASSERT_TRUE_MESSAGE(s.check_init(), "s.check_init() failed");
}

void test_case_cpp_heap()
{
    // Heap test object simple test
    CppTestCaseHelperClass *m = new CppTestCaseHelperClass("Heap");
    m->hello();
    TEST_ASSERT_TRUE_MESSAGE(m->check_init(), "m->check_init() failed");
    delete m;
}

utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
    greentea_case_failure_abort_handler(source, reason);
    return STATUS_CONTINUE;
}

// Generic test cases
Case cases[] = {
    Case("Basic", test_case_basic, greentea_failure_handler),
#ifdef LED1
    Case("Blinky", test_case_blinky, greentea_failure_handler),
#endif
    Case("C++ stack", test_case_cpp_stack, greentea_failure_handler),
    Case("C++ heap", test_case_cpp_heap, greentea_failure_handler)
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(20, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
    Harness::run(specification);
}
<|endoftext|>


<commit_before>/*
***************************************
*   Yet Another Wheel @ 2014-02-09
***************************************
*/

#ifndef __TREE_L_HPP__
#define __TREE_L_HPP__

/* Asylum Namespace */
namespace asy {

/*************************/
/* Tree Unit (Use List2) */
/*************************/
template<class T>
struct atree_unit
{
    T                       user;
    size_t                  deep;
    atree_unit<T>*          uppe;
    list2<cnode_ptr>        next;
    list2_unit<cnode_ptr>*  node;
};

/********************/
/* Tree (Use List2) */
/********************/
template<class T>
class tree_l : public asylum
{
private:
    size_t          m_cnts;
    atree_unit<T>*  m_root;

public:
    /* ================== */
    bool init (const T* obj)
    {
        m_root = struct_new(atree_unit<T>);
        if (m_root == NULL)
            return (false);
        m_cnts = 1;
        m_root->node = NULL;
        m_root->uppe = NULL;
        m_root->deep = 0;
        mem_cpy(&m_root->user, obj, sizeof(T));
        m_root->next.init();
        return (true);
    }

    /* ====== */
    void free ()
    {
        this->del(m_root);
    }

public:
    /* ====================== */
    atree_unit<T>* root () const
    {
        return (m_root);
    }

    /* ============== */
    size_t size () const
    {
        return (m_cnts);
    }

    /* ====================================== */
    size_t child_num (atree_unit<T>* node) const
    {
        return (node->next.size());
    }

    /* =================================================================== */
    atree_unit<T>* get (atree_unit<T>* node, size_t idx, T* obj = NULL) const
    {
        atree_unit<T>*          dat;
        list2_unit<cnode_ptr>*  unt;

        unt = node->next.get(idx);
        dat = static_cast<atree_unit<T>*>(unt->user.ptr);
        if (obj != NULL)
            mem_cpy(obj, &dat->user, sizeof(T));
        return (dat);
    }

    /* ======================================================================== */
    atree_unit<T>* get_safe (atree_unit<T>* node, size_t idx, T* obj = NULL) const
    {
        if (idx >= node->next.size())
            return (NULL);
        return (this->get(node, idx, obj));
    }

    /* =========================================== */
    atree_unit<T>* parent (atree_unit<T>* node) const
    {
        return (node->uppe);
    }

    /* ========================================= */
    atree_unit<T>* prev (atree_unit<T>* node) const
    {
        list2_unit<cnode_ptr>*  unt = node->node->prev;

        if (unt != NULL)
            return (static_cast<atree_unit<T>*>(unt->user.ptr));
        return (NULL);
    }

    /* ========================================= */
    atree_unit<T>* next (atree_unit<T>* node) const
    {
        list2_unit<cnode_ptr>*  unt = node->node->next;

        if (unt != NULL)
            return (static_cast<atree_unit<T>*>(unt->user.ptr));
        return (NULL);
    }

    /* ======================== */
    void del (atree_unit<T>* node)
    {
        if (m_cnts != 0)
        {
            list2<cnode_ptr>*       lst;
            list2_unit<cnode_ptr>*  unt;

            lst = &node->next;
            unt = lst->tail();
            for (size_t idx = lst->size(); idx != 0; idx--) {
                atree_unit<T>*  child;
                child = static_cast<atree_unit<T>*>(unt->user.ptr);
                unt = unt->prev;
                this->del(child);
            }
            node->user.free();
            if (node->uppe != NULL) {
                lst = &node->uppe->next;
                lst->del(node->node);
            }
            m_cnts -= 1;
            mem_free(node);
        }
    }

    /* =============================================================== */
    atree_unit<T>* insert (atree_unit<T>* node, const T* obj, size_t idx)
    {
        cnode_ptr               next;
        atree_unit<T>*          nnew;
        list2<cnode_ptr>*       list;
        list2_unit<cnode_ptr>*  unit;

        nnew = struct_new(atree_unit<T>);
        if (nnew == NULL)
            return (NULL);
        next.ptr = (void*)nnew;
        list = &node->next;
        if (idx >= list->size()) {
            unit = list->append(&next);
        }
        else {
            unit = list->get(idx);
            unit = list->insert(unit, &next);
        }
        if (unit == NULL) {
            mem_free(nnew);
            return (NULL);
        }
        m_cnts += 1;
        nnew->node = unit;
        nnew->uppe = node;
        nnew->deep = node->deep + 1;
        mem_cpy(&nnew->user, obj, sizeof(T));
        nnew->next.init();
        return (nnew);
    }

    /* =================================================== */
    atree_unit<T>* append (atree_unit<T>* node, const T* obj)
    {
        return (this->insert(node, obj, node->next.size()));
    }

    /* ============================================= */
    template<class TRUN>void trav_bfs (void* ctx) const
    {
        if (m_cnts != 0)
        {
            TRUN    run;

            if (!run.doit(ctx, &m_root->user))
                return;
            this->trav_bfs_int<TRUN>(ctx, m_root);
        }
    }

    /* ============================================= */
    template<class TRUN>void trav_dfs (void* ctx) const
    {
        if (m_cnts != 0)
        {
            TRUN    run;

            this->trav_dfs_int<TRUN>(ctx, m_root);
        }
    }

private:
    /* ====================================================================== */
    template<class TRUN>void trav_bfs_int (void* ctx, atree_unit<T>* node) const
    {
        TRUN                    run;
        list2<cnode_ptr>*       lst;
        list2_unit<cnode_ptr>*  unt;

        lst = &node->next;
        if (lst->size() == 0)
            return;
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            if (!run.doit(ctx, &child->user))
                return;
            unt = unt->next;
        }
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            this->trav_bfs_int<TRUN>(ctx, child);
            unt = unt->next;
        }
    }

    /* ====================================================================== */
    template<class TRUN>void trav_dfs_int (void* ctx, atree_unit<T>* node) const
    {
        TRUN                    run;
        list2<cnode_ptr>*       lst;
        list2_unit<cnode_ptr>*  unt;

        if (!run.doit(ctx, &node->user))
            return;
        lst = &node->next;
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            this->trav_dfs_int<TRUN>(ctx, child);
            unt = unt->next;
        }
    }
};

}   /* namespace */

#endif  /* __TREE_L_HPP__ */
<commit_msg>Asylum: 增加一个特殊情况的处理<commit_after>/*
***************************************
*   Yet Another Wheel @ 2014-02-09
***************************************
*/

#ifndef __TREE_L_HPP__
#define __TREE_L_HPP__

/* Asylum Namespace */
namespace asy {

/*************************/
/* Tree Unit (Use List2) */
/*************************/
template<class T>
struct atree_unit
{
    T                       user;
    size_t                  deep;
    atree_unit<T>*          uppe;
    list2<cnode_ptr>        next;
    list2_unit<cnode_ptr>*  node;
};

/********************/
/* Tree (Use List2) */
/********************/
template<class T>
class tree_l : public asylum
{
private:
    size_t          m_cnts;
    atree_unit<T>*  m_root;

public:
    /* ================== */
    bool init (const T* obj)
    {
        m_root = struct_new(atree_unit<T>);
        if (m_root == NULL)
            return (false);
        m_cnts = 1;
        m_root->node = NULL;
        m_root->uppe = NULL;
        m_root->deep = 0;
        mem_cpy(&m_root->user, obj, sizeof(T));
        m_root->next.init();
        return (true);
    }

    /* ====== */
    void free ()
    {
        this->del(m_root);
    }

public:
    /* ====================== */
    atree_unit<T>* root () const
    {
        return (m_root);
    }

    /* ============== */
    size_t size () const
    {
        return (m_cnts);
    }

    /* ====================================== */
    size_t child_num (atree_unit<T>* node) const
    {
        return (node->next.size());
    }

    /* =================================================================== */
    atree_unit<T>* get (atree_unit<T>* node, size_t idx, T* obj = NULL) const
    {
        atree_unit<T>*          dat;
        list2_unit<cnode_ptr>*  unt;

        unt = node->next.get(idx);
        dat = static_cast<atree_unit<T>*>(unt->user.ptr);
        if (obj != NULL)
            mem_cpy(obj, &dat->user, sizeof(T));
        return (dat);
    }

    /* ======================================================================== */
    atree_unit<T>* get_safe (atree_unit<T>* node, size_t idx, T* obj = NULL) const
    {
        if (idx >= node->next.size())
            return (NULL);
        return (this->get(node, idx, obj));
    }

    /* =========================================== */
    atree_unit<T>* parent (atree_unit<T>* node) const
    {
        return (node->uppe);
    }

    /* ========================================= */
    atree_unit<T>* prev (atree_unit<T>* node) const
    {
        list2_unit<cnode_ptr>*  unt = node->node->prev;

        if (unt != NULL)
            return (static_cast<atree_unit<T>*>(unt->user.ptr));
        return (NULL);
    }

    /* ========================================= */
    atree_unit<T>* next (atree_unit<T>* node) const
    {
        list2_unit<cnode_ptr>*  unt = node->node->next;

        if (unt != NULL)
            return (static_cast<atree_unit<T>*>(unt->user.ptr));
        return (NULL);
    }

    /* ======================== */
    void del (atree_unit<T>* node)
    {
        if (m_cnts != 0)
        {
            list2<cnode_ptr>*       lst;
            list2_unit<cnode_ptr>*  unt;

            lst = &node->next;
            unt = lst->tail();
            for (size_t idx = lst->size(); idx != 0; idx--) {
                atree_unit<T>*  child;
                child = static_cast<atree_unit<T>*>(unt->user.ptr);
                unt = unt->prev;
                this->del(child);
            }
            node->user.free();
            if (node->uppe != NULL) {
                lst = &node->uppe->next;
                lst->del(node->node);
            }
            m_cnts -= 1;
            mem_free(node);
        }
    }

    /* =============================================================== */
    atree_unit<T>* insert (atree_unit<T>* node, const T* obj, size_t idx)
    {
        cnode_ptr               next;
        atree_unit<T>*          nnew;
        list2<cnode_ptr>*       list;
        list2_unit<cnode_ptr>*  unit;

        nnew = struct_new(atree_unit<T>);
        if (nnew == NULL)
            return (NULL);
        next.ptr = (void*)nnew;
        list = &node->next;
        if (idx >= list->size()) {
            unit = list->append(&next);
        }
        else
        if (idx == 0) {
            unit = list->sthead(&next);
        }
        else {
            unit = list->get(idx);
            unit = list->insert(unit, &next);
        }
        if (unit == NULL) {
            mem_free(nnew);
            return (NULL);
        }
        m_cnts += 1;
        nnew->node = unit;
        nnew->uppe = node;
        nnew->deep = node->deep + 1;
        mem_cpy(&nnew->user, obj, sizeof(T));
        nnew->next.init();
        return (nnew);
    }

    /* =================================================== */
    atree_unit<T>* sthead (atree_unit<T>* node, const T* obj)
    {
        return (this->insert(node, obj, 0));
    }

    /* =================================================== */
    atree_unit<T>* append (atree_unit<T>* node, const T* obj)
    {
        return (this->insert(node, obj, node->next.size()));
    }

    /* ============================================= */
    template<class TRUN>void trav_bfs (void* ctx) const
    {
        if (m_cnts != 0)
        {
            TRUN    run;

            if (!run.doit(ctx, &m_root->user))
                return;
            this->trav_bfs_int<TRUN>(ctx, m_root);
        }
    }

    /* ============================================= */
    template<class TRUN>void trav_dfs (void* ctx) const
    {
        if (m_cnts != 0)
        {
            TRUN    run;

            this->trav_dfs_int<TRUN>(ctx, m_root);
        }
    }

private:
    /* ====================================================================== */
    template<class TRUN>void trav_bfs_int (void* ctx, atree_unit<T>* node) const
    {
        TRUN                    run;
        list2<cnode_ptr>*       lst;
        list2_unit<cnode_ptr>*  unt;

        lst = &node->next;
        if (lst->size() == 0)
            return;
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            if (!run.doit(ctx, &child->user))
                return;
            unt = unt->next;
        }
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            this->trav_bfs_int<TRUN>(ctx, child);
            unt = unt->next;
        }
    }

    /* ====================================================================== */
    template<class TRUN>void trav_dfs_int (void* ctx, atree_unit<T>* node) const
    {
        TRUN                    run;
        list2<cnode_ptr>*       lst;
        list2_unit<cnode_ptr>*  unt;

        if (!run.doit(ctx, &node->user))
            return;
        lst = &node->next;
        unt = lst->head();
        for (size_t idx = lst->size(); idx != 0; idx--) {
            atree_unit<T>*  child;
            child = static_cast<atree_unit<T>*>(unt->user.ptr);
            this->trav_dfs_int<TRUN>(ctx, child);
            unt = unt->next;
        }
    }
};

}   /* namespace */

#endif  /* __TREE_L_HPP__ */
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "MeshVisualizer.h"

#include <Corrade/Utility/Resource.h>

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Shader.h"
#include "MagnumExternal/Optional/optional.hpp"

#include "Implementation/CreateCompatibilityShader.h"

namespace Magnum { namespace Shaders {

MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) {
    #ifndef MAGNUM_TARGET_GLES2
    if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
        #ifndef MAGNUM_TARGET_GLES
        MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320);
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
        #else
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::geometry_shader);
        #endif
    }
    #else
    if(flags & Flag::Wireframe)
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives);
    #endif

    #ifdef MAGNUM_BUILD_STATIC
    /* Import resources on static build, if not already */
    if(!Utility::Resource::hasGroup("MagnumShaders"))
        importShaderResources();
    #endif
    Utility::Resource rs("MagnumShaders");

    #ifndef MAGNUM_TARGET_GLES
    const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210});
    CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GL320);
    #else
    const Version version = Context::current()->supportedVersion({Version::GLES310, Version::GLES300, Version::GLES200});
    CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GLES310);
    #endif

    Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
    Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);

    vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
        .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
        #ifdef MAGNUM_TARGET_WEBGL
        .addSource("#define SUBSCRIPTING_WORKAROUND\n")
        #elif defined(MAGNUM_TARGET_GLES2)
        .addSource(Context::current()->detectedDriver() & Context::DetectedDriver::ProbablyAngle ?
            "#define SUBSCRIPTING_WORKAROUND\n" : "")
        #endif
        .addSource(rs.get("generic.glsl"))
        .addSource(rs.get("MeshVisualizer.vert"));
    frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
        .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
        .addSource(rs.get("MeshVisualizer.frag"));

    #ifndef MAGNUM_TARGET_GLES2
    std::optional<Shader> geom;
    if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
        geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry);
        geom->addSource(rs.get("MeshVisualizer.geom"));
    }
    #endif

    #ifndef MAGNUM_TARGET_GLES2
    if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, *geom, frag}));
    else
    #endif
        CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag}));

    attachShaders({vert, frag});
    #ifndef MAGNUM_TARGET_GLES2
    if(geom) attachShader(*geom);
    #endif

    #ifndef MAGNUM_TARGET_GLES
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
    #else
    if(!Context::current()->isVersionSupported(Version::GLES300))
    #endif
    {
        bindAttributeLocation(Position::Location, "position");

        #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
        #ifndef MAGNUM_TARGET_GLES
        if(!Context::current()->isVersionSupported(Version::GL310))
        #endif
        {
            bindAttributeLocation(VertexIndex::Location, "vertexIndex");
        }
        #endif
    }

    CORRADE_INTERNAL_ASSERT_OUTPUT(link());

    #ifndef MAGNUM_TARGET_GLES
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
    #endif
    {
        transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
        colorUniform = uniformLocation("color");
        if(flags & Flag::Wireframe) {
            wireframeColorUniform = uniformLocation("wireframeColor");
            wireframeWidthUniform = uniformLocation("wireframeWidth");
            smoothnessUniform = uniformLocation("smoothness");
            if(!(flags & Flag::NoGeometryShader))
                viewportSizeUniform = uniformLocation("viewportSize");
        }
    }

    /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
    #ifdef MAGNUM_TARGET_GLES
    setColor(Color3(1.0f));
    if(flags & Flag::Wireframe) {
        setWireframeColor(Color3(0.0f));
        setWireframeWidth(1.0f);
        setSmoothness(2.0f);
    }
    #endif
}

}}
<commit_msg>Shaders: fix assertion in MeshVisualizer.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "MeshVisualizer.h"

#include <Corrade/Utility/Resource.h>

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Shader.h"
#include "MagnumExternal/Optional/optional.hpp"

#include "Implementation/CreateCompatibilityShader.h"

namespace Magnum { namespace Shaders {

MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) {
    #ifndef MAGNUM_TARGET_GLES2
    if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
        #ifndef MAGNUM_TARGET_GLES
        MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320);
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
        #else
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::geometry_shader);
        #endif
    }
    #else
    if(flags & Flag::Wireframe)
        MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives);
    #endif

    #ifdef MAGNUM_BUILD_STATIC
    /* Import resources on static build, if not already */
    if(!Utility::Resource::hasGroup("MagnumShaders"))
        importShaderResources();
    #endif
    Utility::Resource rs("MagnumShaders");

    #ifndef MAGNUM_TARGET_GLES
    const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210});
    CORRADE_INTERNAL_ASSERT(!flags || flags & Flag::NoGeometryShader || version >= Version::GL320);
    #else
    const Version version = Context::current()->supportedVersion({Version::GLES310, Version::GLES300, Version::GLES200});
    CORRADE_INTERNAL_ASSERT(!flags || flags & Flag::NoGeometryShader || version >= Version::GLES310);
    #endif

    Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
    Shader frag = Implementation::createCompatibilityShader(rs, version, Shader::Type::Fragment);

    vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
        .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
        #ifdef MAGNUM_TARGET_WEBGL
        .addSource("#define SUBSCRIPTING_WORKAROUND\n")
        #elif defined(MAGNUM_TARGET_GLES2)
        .addSource(Context::current()->detectedDriver() & Context::DetectedDriver::ProbablyAngle ?
            "#define SUBSCRIPTING_WORKAROUND\n" : "")
        #endif
        .addSource(rs.get("generic.glsl"))
        .addSource(rs.get("MeshVisualizer.vert"));
    frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
        .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
        .addSource(rs.get("MeshVisualizer.frag"));

    #ifndef MAGNUM_TARGET_GLES2
    std::optional<Shader> geom;
    if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
        geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry);
        geom->addSource(rs.get("MeshVisualizer.geom"));
    }
    #endif

    #ifndef MAGNUM_TARGET_GLES2
    if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, *geom, frag}));
    else
    #endif
        CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag}));

    attachShaders({vert, frag});
    #ifndef MAGNUM_TARGET_GLES2
    if(geom) attachShader(*geom);
    #endif

    #ifndef MAGNUM_TARGET_GLES
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>(version))
    #else
    if(!Context::current()->isVersionSupported(Version::GLES300))
    #endif
    {
        bindAttributeLocation(Position::Location, "position");

        #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
        #ifndef MAGNUM_TARGET_GLES
        if(!Context::current()->isVersionSupported(Version::GL310))
        #endif
        {
            bindAttributeLocation(VertexIndex::Location, "vertexIndex");
        }
        #endif
    }

    CORRADE_INTERNAL_ASSERT_OUTPUT(link());

    #ifndef MAGNUM_TARGET_GLES
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>(version))
    #endif
    {
        transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
        colorUniform = uniformLocation("color");
        if(flags & Flag::Wireframe) {
            wireframeColorUniform = uniformLocation("wireframeColor");
            wireframeWidthUniform = uniformLocation("wireframeWidth");
            smoothnessUniform = uniformLocation("smoothness");
            if(!(flags & Flag::NoGeometryShader))
                viewportSizeUniform = uniformLocation("viewportSize");
        }
    }

    /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
    #ifdef MAGNUM_TARGET_GLES
    setColor(Color3(1.0f));
    if(flags & Flag::Wireframe) {
        setWireframeColor(Color3(0.0f));
        setWireframeWidth(1.0f);
        setSmoothness(2.0f);
    }
    #endif
}

}}
<|endoftext|>