<commit_before>//=======================================================================
// Copyright (c) 2013-2020 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <set>

#include "api/server_api.hpp"
#include "api/recurrings_api.hpp"

#include "recurring.hpp"
#include "accounts.hpp"
#include "guid.hpp"
#include "http.hpp"
#include "data.hpp"

using namespace budget;

void budget::add_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_name") || !req.has_param("input_amount") || !req.has_param("input_account") || !req.has_param("input_recurs")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    try {
        recurring recurring;
        recurring.guid    = budget::generate_guid();
        recurring.account = budget::get_account(budget::to_number<size_t>(req.get_param_value("input_account"))).name;
        recurring.name    = req.get_param_value("input_name");
        recurring.amount  = budget::parse_money(req.get_param_value("input_amount"));
        recurring.recurs  = req.get_param_value("input_recurs");

        add_recurring(std::move(recurring));

        api_success(req, res, "Recurring " + to_string(recurring.id) + " has been created", to_string(recurring.id));
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::edit_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_id") || !req.has_param("input_name") || !req.has_param("input_amount") || !req.has_param("input_account") || !req.has_param("input_recurs")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    auto id = req.get_param_value("input_id");

    if (!budget::recurring_exists(budget::to_number<size_t>(id))) {
        api_error(req, res, "recurring " + id + " does not exist");
        return;
    }

    try {
        recurring recurring = recurring_get(budget::to_number<size_t>(id));
        recurring.account   = budget::get_account(budget::to_number<size_t>(req.get_param_value("input_account"))).name;
        recurring.name      = req.get_param_value("input_name");
        recurring.amount    = budget::parse_money(req.get_param_value("input_amount"));
        recurring.recurs    = req.get_param_value("input_recurs");

        edit_recurring(recurring);

        api_success(req, res, "Recurring " + to_string(recurring.id) + " has been modified");
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::delete_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_id")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    auto id = req.get_param_value("input_id");

    if (!budget::recurring_exists(budget::to_number<size_t>(id))) {
        api_error(req, res, "The recurring " + id + " does not exit");
        return;
    }

    try {
        budget::recurring_delete(budget::to_number<size_t>(id));

        api_success(req, res, "Recurring " + id + " has been deleted");
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::list_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    try {
        std::stringstream ss;

        for (auto& recurring : all_recurrings()) {
            data_writer writer;
            recurring.save(writer);
            ss << writer.to_string() << std::endl;
        }

        api_success_content(req, res, ss.str());
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}
<commit_msg>Extra validation in the API<commit_after>//=======================================================================
// Copyright (c) 2013-2020 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <set>

#include "api/server_api.hpp"
#include "api/recurrings_api.hpp"

#include "recurring.hpp"
#include "accounts.hpp"
#include "guid.hpp"
#include "http.hpp"
#include "data.hpp"

using namespace budget;

void budget::add_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_name") || !req.has_param("input_amount") || !req.has_param("input_account") || !req.has_param("input_recurs")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    try {
        recurring recurring;
        recurring.guid    = budget::generate_guid();
        recurring.account = budget::get_account(budget::to_number<size_t>(req.get_param_value("input_account"))).name;
        recurring.name    = req.get_param_value("input_name");
        recurring.amount  = budget::parse_money(req.get_param_value("input_amount"));
        recurring.recurs  = req.get_param_value("input_recurs");

        if (recurring.recurs != "monthly" && recurring.recurs != "weekly") {
            api_error(req, res, "Invalid recurring frequency");
            return;
        }

        add_recurring(std::move(recurring));

        api_success(req, res, "Recurring " + to_string(recurring.id) + " has been created", to_string(recurring.id));
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::edit_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_id") || !req.has_param("input_name") || !req.has_param("input_amount") || !req.has_param("input_account") || !req.has_param("input_recurs")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    auto id = req.get_param_value("input_id");

    if (!budget::recurring_exists(budget::to_number<size_t>(id))) {
        api_error(req, res, "recurring " + id + " does not exist");
        return;
    }

    try {
        recurring recurring = recurring_get(budget::to_number<size_t>(id));
        recurring.account   = budget::get_account(budget::to_number<size_t>(req.get_param_value("input_account"))).name;
        recurring.name      = req.get_param_value("input_name");
        recurring.amount    = budget::parse_money(req.get_param_value("input_amount"));
        recurring.recurs    = req.get_param_value("input_recurs");

        if (recurring.recurs != "monthly" && recurring.recurs != "weekly") {
            api_error(req, res, "Invalid recurring frequency");
            return;
        }

        edit_recurring(recurring);

        api_success(req, res, "Recurring " + to_string(recurring.id) + " has been modified");
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::delete_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    if (!req.has_param("input_id")) {
        api_error(req, res, "Invalid parameters");
        return;
    }

    auto id = req.get_param_value("input_id");

    if (!budget::recurring_exists(budget::to_number<size_t>(id))) {
        api_error(req, res, "The recurring " + id + " does not exit");
        return;
    }

    try {
        budget::recurring_delete(budget::to_number<size_t>(id));

        api_success(req, res, "Recurring " + id + " has been deleted");
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}

void budget::list_recurrings_api(const httplib::Request& req, httplib::Response& res) {
    if (!api_start(req, res)) {
        return;
    }

    try {
        std::stringstream ss;

        for (auto& recurring : all_recurrings()) {
            data_writer writer;
            recurring.save(writer);
            ss << writer.to_string() << std::endl;
        }

        api_success_content(req, res, ss.str());
    } catch (const budget_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    } catch (const date_exception& e) {
        api_error(req, res, "Exception occurred: " + e.message());
    }
}
<|endoftext|>


<commit_before>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.KeyRemap4MacBook");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char* name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "keyremap4macbook.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    std::map<std::string, int>::iterator it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char* name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char* filename, void (* func)(const char*))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char* sysctl_begin = "<sysctl>";
      const char* sysctl_end = "</sysctl>";

      char* begin = strstr(line, "<sysctl>");
      if (! begin) continue;
      char* end = strstr(line, sysctl_end);
      if (! end) continue;

      begin += strlen(sysctl_begin);
      *end = '\0';

      func(begin);
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/KeyRemap4MacBook/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char* p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char** targetFiles, CFStringRef identify)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(identify, dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char** targetFiles, CFStringRef identify)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void*>(CFPreferencesCopyAppValue(identify, applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  // ============================================================
  // ADD & DELETE & SELECT
  void
  setConfigList(CFArrayRef list)
  {
    CFPreferencesSetAppValue(CFSTR("configList"), list, applicationID);
  }

  CFArrayRef
  getConfigList(void)
  {
    CFArrayRef list = reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(CFSTR("configList"), applicationID));

    if (! list || CFArrayGetCount(list) == 0) {
      if (list) CFRelease(list);

      CFMutableDictionaryRef dict[1];
      dict[0] = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
      CFDictionarySetValue(dict[0], CFSTR("name"), CFSTR("Default"));
      CFDictionarySetValue(dict[0], CFSTR("identify"), CFSTR("config_default"));

      list = CFArrayCreate(NULL, const_cast<const void**>(reinterpret_cast<void**>(dict)), 1, NULL);
      setConfigList(list);
    }

    return list;
  }

  CFDictionaryRef
  getConfigDictionary(CFIndex index)
  {
    CFArrayRef list = getConfigList();
    if (! list) return NULL;

    if (index < 0) return NULL;
    if (index >= CFArrayGetCount(list)) return NULL;

    return reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(list, index));
  }

  CFStringRef
  getIdentify(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("identify")));
  }

  CFStringRef
  getConfigName(int index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("name")));
  }

  bool
  appendConfig(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    struct timeval tm;
    gettimeofday(&tm, NULL);
    CFStringRef identify = CFStringCreateWithFormat(NULL, NULL, CFSTR("config_%d_%d"), tm.tv_sec, tm.tv_usec);

    CFMutableDictionaryRef dict;
    dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    CFDictionarySetValue(dict, CFSTR("name"), CFSTR("NewItem"));
    CFDictionarySetValue(dict, CFSTR("identify"), identify);

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayAppendValue(newlist, dict);

    setConfigList(newlist);
    return true;
  }

  bool
  removeConfig(int index)
  {
    CFStringRef identify = getIdentify(index);
    if (! identify) return false;

    CFPreferencesSetAppValue(identify, NULL, applicationID);

    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayRemoveValueAtIndex(newlist, index);

    setConfigList(newlist);
    return true;
  }

  bool
  renameConfig(int index, const char* newname)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFDictionaryRef olddict = getConfigDictionary(index);
    if (! olddict) return false;

    CFMutableDictionaryRef newdict = CFDictionaryCreateMutableCopy(NULL, 0, olddict);
    CFDictionarySetValue(newdict, CFSTR("name"), CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8));

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArraySetValueAtIndex(newlist, index, newdict);

    setConfigList(newlist);
    return true;
  }

  CFIndex
  getConfigCount(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return 0;

    return CFArrayGetCount(list);
  }

  // ----------------------------------------
  bool
  setSelectedIndex(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return false;

    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &index);
    CFPreferencesSetAppValue(CFSTR("selectedIndex"), val, applicationID);

    return true;
  }

  CFIndex
  getSelectedIndex(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("selectedIndex"), applicationID, &isOK);
    if (! isOK || value < 0) {
      value = 0;
      setSelectedIndex(value);
    }
    return value;
  }

  // ----------------------------------------
  bool
  setStatusbarEnable(CFIndex enable)
  {
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &enable);
    CFPreferencesSetAppValue(CFSTR("isStatusbarEnable"), val, applicationID);
    return true;
  }

  CFIndex
  isStatusbarEnable(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("isStatusbarEnable"), applicationID, &isOK);
    if (! isOK) {
      value = 1;
      setStatusbarEnable(value);
    }
    return value;
  }

  void
  stripString(char* buf, size_t buflen)
  {
    char* p = buf;
    for (;;) {
      if (! isspace(*p)) break;
      ++p;
    }
    char* q = p;
    for (;;) {
      if (*q == '\0' || *q == '\r' || *q == '\n') break;
      ++q;
    }
    *q = '\0';
    snprintf(buf, buflen, "%s", p);
  }
}

int
main(int argc, char** argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load|add|delete|rename|getname|select|count|current|statusbar|toggle_statusbar) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;

  if (strcmp(argv[1], "select") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s select index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = setSelectedIndex(index);

  } else if (strcmp(argv[1], "add") == 0) {
    isSuccess = appendConfig();

  } else if (strcmp(argv[1], "delete") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s delete index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = removeConfig(index);

  } else if (strcmp(argv[1], "rename") == 0) {
    // sysctl_ctl rename "index" "newname"
    if (argc < 4) {
      fprintf(stderr, "Usage: %s rename index newname\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    char buf[512];
    snprintf(buf, sizeof(buf), "%s", argv[3]);
    stripString(buf, sizeof(buf));
    if (buf[0] == '\0') {
      snprintf(buf, sizeof(buf), "(null)");
    }
    isSuccess = renameConfig(index, buf);

  } else if (strcmp(argv[1], "count") == 0) {
    printf("%ld\n", getConfigCount());
    return 0;

  } else if (strcmp(argv[1], "current") == 0) {
    printf("%ld\n", getSelectedIndex());
    return 0;

  } else if (strcmp(argv[1], "statusbar") == 0) {
    printf("%ld\n", isStatusbarEnable());
    return 0;

  } else if (strcmp(argv[1], "toggle_statusbar") == 0) {
    CFIndex value = isStatusbarEnable();
    isSuccess = setStatusbarEnable(! value);

  } else if (strcmp(argv[1], "getname") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s getname index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    CFStringRef name = getConfigName(index);
    if (name) {
      char buf[512];
      if (CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8)) {
        stripString(buf, sizeof(buf));
        printf("%s\n", buf);
      } else {
        printf("(null)\n", buf);
      }
    }
    return 0;

  } else if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    CFIndex value = getSelectedIndex();
    CFStringRef identify = getIdentify(value);

    const char* targetFiles[] = {
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/checkbox.xml",
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/number.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles, identify);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_reset");
      isSuccess = loadFromFile(targetFiles, identify);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

finish:
  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<commit_msg>cleanup src/bin/sysctl_ctl/main.cpp<commit_after>#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
#include <map>

#include <CoreFoundation/CoreFoundation.h>

namespace {
  CFStringRef applicationID = CFSTR("org.pqrs.KeyRemap4MacBook");

  // ============================================================
  // SAVE & LOAD
  CFMutableDictionaryRef dict_sysctl = NULL;
  std::map<std::string, int> map_reset;

  void
  save(const char* name)
  {
    if (! dict_sysctl) return;

    char entry[512];
    snprintf(entry, sizeof(entry), "keyremap4macbook.%s", name);

    int value;
    size_t len = sizeof(value);
    if (sysctlbyname(entry, &value, &len, NULL, 0) == -1) return;

    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &value);

    std::map<std::string, int>::iterator it = map_reset.find(name);
    if (it == map_reset.end()) return;
    CFNumberRef defaultval = CFNumberCreate(NULL, kCFNumberIntType, &(it->second));

    if (CFNumberCompare(val, defaultval, NULL) != 0) {
      CFDictionarySetValue(dict_sysctl, key, val);
    }
  }

  void
  load(const char* name)
  {
    if (! dict_sysctl) return;
    CFStringRef key = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);

    CFNumberRef val = reinterpret_cast<CFNumberRef>(CFDictionaryGetValue(dict_sysctl, key));
    if (! val) return;

    int value;
    if (! CFNumberGetValue(val, kCFNumberIntType, &value)) return;

    char cmd[512];
    snprintf(cmd, sizeof(cmd), "/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_set %s %d", name, value);
    system(cmd);
  }

  void
  scanLines(const char* filename, void (* func)(const char*))
  {
    std::ifstream ifs(filename);
    if (! ifs) return;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      const char* sysctl_begin = "<sysctl>";
      const char* sysctl_end = "</sysctl>";

      char* begin = strstr(line, "<sysctl>");
      if (! begin) continue;
      char* end = strstr(line, sysctl_end);
      if (! end) continue;

      begin += strlen(sysctl_begin);
      *end = '\0';

      func(begin);
    }
  }

  bool
  makeMapReset(void)
  {
    std::ifstream ifs("/Library/org.pqrs/KeyRemap4MacBook/share/reset");
    if (! ifs) return false;

    while (! ifs.eof()) {
      char line[512];

      ifs.getline(line, sizeof(line));

      char* p = strchr(line, ' ');
      if (! p) continue;
      *p = '\0';

      int value = atoi(p + 1);

      map_reset[line] = value;
    }

    return true;
  }

  bool
  saveToFile(const char** targetFiles, CFStringRef identify)
  {
    if (! makeMapReset()) return false;

    dict_sysctl = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, save);
    }
    CFPreferencesSetAppValue(identify, dict_sysctl, applicationID);

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  bool
  loadFromFile(const char** targetFiles, CFStringRef identify)
  {
    dict_sysctl = reinterpret_cast<CFMutableDictionaryRef>(const_cast<void*>(CFPreferencesCopyAppValue(identify, applicationID)));
    if (! dict_sysctl) return false;

    for (int i = 0;; ++i) {
      const char* filename = targetFiles[i];
      if (! filename) break;
      scanLines(filename, load);
    }

    CFRelease(dict_sysctl); dict_sysctl = NULL;
    return true;
  }

  // ============================================================
  // ADD & DELETE & SELECT
  void
  setConfigList(CFArrayRef list)
  {
    CFPreferencesSetAppValue(CFSTR("configList"), list, applicationID);
  }

  CFArrayRef
  getConfigList(void)
  {
    CFArrayRef list = reinterpret_cast<CFArrayRef>(CFPreferencesCopyAppValue(CFSTR("configList"), applicationID));

    if (! list || CFArrayGetCount(list) == 0) {
      if (list) CFRelease(list);

      CFMutableDictionaryRef dict[1];
      dict[0] = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
      CFDictionarySetValue(dict[0], CFSTR("name"), CFSTR("Default"));
      CFDictionarySetValue(dict[0], CFSTR("identify"), CFSTR("config_default"));

      list = CFArrayCreate(NULL, const_cast<const void**>(reinterpret_cast<void**>(dict)), 1, NULL);
      setConfigList(list);
    }

    return list;
  }

  CFDictionaryRef
  getConfigDictionary(CFIndex index)
  {
    CFArrayRef list = getConfigList();
    if (! list) return NULL;

    if (index < 0) return NULL;
    if (index >= CFArrayGetCount(list)) return NULL;

    return reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(list, index));
  }

  CFStringRef
  getIdentify(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("identify")));
  }

  CFStringRef
  getConfigName(int index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return NULL;

    return reinterpret_cast<CFStringRef>(CFDictionaryGetValue(dict, CFSTR("name")));
  }

  bool
  appendConfig(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    struct timeval tm;
    gettimeofday(&tm, NULL);
    CFStringRef identify = CFStringCreateWithFormat(NULL, NULL, CFSTR("config_%d_%d"), tm.tv_sec, tm.tv_usec);

    CFMutableDictionaryRef dict;
    dict = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
    CFDictionarySetValue(dict, CFSTR("name"), CFSTR("NewItem"));
    CFDictionarySetValue(dict, CFSTR("identify"), identify);

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayAppendValue(newlist, dict);

    setConfigList(newlist);
    return true;
  }

  bool
  removeConfig(int index)
  {
    CFStringRef identify = getIdentify(index);
    if (! identify) return false;

    CFPreferencesSetAppValue(identify, NULL, applicationID);

    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArrayRemoveValueAtIndex(newlist, index);

    setConfigList(newlist);
    return true;
  }

  bool
  renameConfig(int index, const char* newname)
  {
    CFArrayRef list = getConfigList();
    if (! list) return false;

    CFDictionaryRef olddict = getConfigDictionary(index);
    if (! olddict) return false;

    CFMutableDictionaryRef newdict = CFDictionaryCreateMutableCopy(NULL, 0, olddict);
    CFDictionarySetValue(newdict, CFSTR("name"), CFStringCreateWithCString(NULL, newname, kCFStringEncodingUTF8));

    CFMutableArrayRef newlist = CFArrayCreateMutableCopy(NULL, 0, list);
    CFArraySetValueAtIndex(newlist, index, newdict);

    setConfigList(newlist);
    return true;
  }

  CFIndex
  getConfigCount(void)
  {
    CFArrayRef list = getConfigList();
    if (! list) return 0;

    return CFArrayGetCount(list);
  }

  // ----------------------------------------
  bool
  setSelectedIndex(CFIndex index)
  {
    CFDictionaryRef dict = getConfigDictionary(index);
    if (! dict) return false;

    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &index);
    CFPreferencesSetAppValue(CFSTR("selectedIndex"), val, applicationID);

    return true;
  }

  CFIndex
  getSelectedIndex(void)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(CFSTR("selectedIndex"), applicationID, &isOK);
    if (! isOK || value < 0) {
      value = 0;
      setSelectedIndex(value);
    }
    return value;
  }

  // ----------------------------------------
  bool
  setBool(CFStringRef name, CFIndex enable)
  {
    CFNumberRef val = CFNumberCreate(NULL, kCFNumberIntType, &enable);
    CFPreferencesSetAppValue(name, val, applicationID);
    return true;
  }

  CFIndex
  getBool(CFStringRef name)
  {
    Boolean isOK;
    CFIndex value = CFPreferencesGetAppIntegerValue(name, applicationID, &isOK);
    if (! isOK) {
      value = 1;
      setBool(name, value);
    }
    return value;
  }

  void
  stripString(char* buf, size_t buflen)
  {
    char* p = buf;
    for (;;) {
      if (! isspace(*p)) break;
      ++p;
    }
    char* q = p;
    for (;;) {
      if (*q == '\0' || *q == '\r' || *q == '\n') break;
      ++q;
    }
    *q = '\0';
    snprintf(buf, buflen, "%s", p);
  }
}

int
main(int argc, char** argv)
{
  if (argc == 1) {
    fprintf(stderr, "Usage: %s (save|load|add|delete|rename|getname|select|count|current|statusbar|toggle_statusbar) [params]\n", argv[0]);
    return 1;
  }

  bool isSuccess = false;

  if (strcmp(argv[1], "select") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s select index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = setSelectedIndex(index);

  } else if (strcmp(argv[1], "add") == 0) {
    isSuccess = appendConfig();

  } else if (strcmp(argv[1], "delete") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s delete index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    isSuccess = removeConfig(index);

  } else if (strcmp(argv[1], "rename") == 0) {
    // sysctl_ctl rename "index" "newname"
    if (argc < 4) {
      fprintf(stderr, "Usage: %s rename index newname\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    char buf[512];
    snprintf(buf, sizeof(buf), "%s", argv[3]);
    stripString(buf, sizeof(buf));
    if (buf[0] == '\0') {
      snprintf(buf, sizeof(buf), "(null)");
    }
    isSuccess = renameConfig(index, buf);

  } else if (strcmp(argv[1], "count") == 0) {
    printf("%ld\n", getConfigCount());
    return 0;

  } else if (strcmp(argv[1], "current") == 0) {
    printf("%ld\n", getSelectedIndex());
    return 0;

  } else if (strcmp(argv[1], "statusbar") == 0) {
    printf("%ld\n", getBool(CFSTR("isStatusbarEnable")));
    return 0;

  } else if (strcmp(argv[1], "toggle_statusbar") == 0) {
    CFStringRef name = CFSTR("isStatusbarEnable");
    CFIndex value = getBool(name);
    isSuccess = setBool(name, ! value);

  } else if (strcmp(argv[1], "getname") == 0) {
    if (argc < 3) {
      fprintf(stderr, "Usage: %s getname index\n", argv[0]);
      goto finish;
    }
    int index = atoi(argv[2]);
    CFStringRef name = getConfigName(index);
    if (name) {
      char buf[512];
      if (CFStringGetCString(name, buf, sizeof(buf), kCFStringEncodingUTF8)) {
        stripString(buf, sizeof(buf));
        printf("%s\n", buf);
      } else {
        printf("(null)\n", buf);
      }
    }
    return 0;

  } else if ((strcmp(argv[1], "save") == 0) || (strcmp(argv[1], "load") == 0)) {
    CFIndex value = getSelectedIndex();
    CFStringRef identify = getIdentify(value);

    const char* targetFiles[] = {
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/checkbox.xml",
      "/Library/org.pqrs/KeyRemap4MacBook/prefpane/number.xml",
      NULL,
    };
    if (strcmp(argv[1], "save") == 0) {
      isSuccess = saveToFile(targetFiles, identify);
    }
    if (strcmp(argv[1], "load") == 0) {
      system("/Library/org.pqrs/KeyRemap4MacBook/bin/KeyRemap4MacBook_sysctl_reset");
      isSuccess = loadFromFile(targetFiles, identify);
    }
  }

  CFPreferencesAppSynchronize(applicationID);

finish:
  if (isSuccess) {
    fprintf(stderr, "[DONE]\n");
  } else {
    fprintf(stderr, "[ERROR]\n");
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2009 The FLWOR Foundation.
 *
 * 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 <zorba/item.h>
#include <zorba/options.h>
#include <zorba/singleton_item_sequence.h>
#include <zorba/serializable.h>
#include <zorba/default_error_handler.h>

#include "api/zorbaimpl.h"
#include "api/serialization/serializable_wrapper.h"
#include "api/serialization/serializable.h"
#include "api/unmarshaller.h"

#include "serializerimpl.h"

namespace zorba {

Serializer_t
Serializer::createSerializer(const Zorba_SerializerOptions_t& aOptions)
{
  return new SerializerImpl(aOptions);
}

Serializer_t
Serializer::createSerializer(ItemSequence* aOptions)
{
  return new SerializerImpl(aOptions);
}

SerializerImpl::SerializerImpl(const Zorba_SerializerOptions_t& aOptions, ErrorHandler* aErrorHandler)
  : theInternalSerializer(&theErrorManager),
    theErrorHandler(aErrorHandler)
{
  setSerializationParameters(theInternalSerializer, aOptions);
  if (!theErrorHandler) {
    theErrorHandler = new DefaultErrorHandler();
  }
}

SerializerImpl::SerializerImpl(ItemSequence* aOptions, ErrorHandler* aErrorHandler)
  : theInternalSerializer(&theErrorManager),
    theErrorHandler(aErrorHandler)
{
  setSerializationParameters(theInternalSerializer, aOptions);
  if (!theErrorHandler) {
    theErrorHandler = new DefaultErrorHandler();
  }
}

void
SerializerImpl::serialize(Serializable* aObject, std::ostream& aOs) const
{
  try {
    intern::SerializableWrapper lWrapper(aObject);
    theInternalSerializer.serialize((intern::Serializable*)&lWrapper, aOs);
  } catch (error::ZorbaError& e) {
    ZorbaImpl::notifyError(theErrorHandler, e);
  }
}

int
SerializerImpl::getSerializationMethod() const
{
  switch (theInternalSerializer.getSerializationMethod())
  {
  case serializer::PARAMETER_VALUE_HTML:
    return ZORBA_SERIALIZATION_METHOD_HTML;
  case serializer::PARAMETER_VALUE_XHTML:
    return ZORBA_SERIALIZATION_METHOD_XHTML;
  case serializer::PARAMETER_VALUE_TEXT:
    return ZORBA_SERIALIZATION_METHOD_TEXT;
  case serializer::PARAMETER_VALUE_JSON:
    return ZORBA_SERIALIZATION_METHOD_JSON;
  case serializer::PARAMETER_VALUE_JSONML:
    return ZORBA_SERIALIZATION_METHOD_JSONML;
  case serializer::PARAMETER_VALUE_BINARY:
    return ZORBA_SERIALIZATION_METHOD_BINARY;
  default:
    return ZORBA_SERIALIZATION_METHOD_XML;
  }
}

void
SerializerImpl::setSerializationParameters(
  serializer&                       aInternalSerializer,
  const Zorba_SerializerOptions_t&  aSerializerOptions)
{
  switch (aSerializerOptions.ser_method)
  {
  case ZORBA_SERIALIZATION_METHOD_XML:
    aInternalSerializer.setParameter("method", "xml"); break;
  case ZORBA_SERIALIZATION_METHOD_HTML:
    aInternalSerializer.setParameter("method", "html"); break;
  case ZORBA_SERIALIZATION_METHOD_XHTML:
    aInternalSerializer.setParameter("method", "xhtml"); break;
  case ZORBA_SERIALIZATION_METHOD_TEXT:
    aInternalSerializer.setParameter("method", "text"); break;
  case ZORBA_SERIALIZATION_METHOD_JSON:
    aInternalSerializer.setParameter("method", "json"); break;
  case ZORBA_SERIALIZATION_METHOD_JSONML:
    aInternalSerializer.setParameter("method", "jsonml"); break;
  case ZORBA_SERIALIZATION_METHOD_BINARY:
    aInternalSerializer.setParameter("method", "binary"); break;
  }

  switch (aSerializerOptions.byte_order_mark)
  {
  case ZORBA_BYTE_ORDER_MARK_YES:
    aInternalSerializer.setParameter("byte-order-mark", "yes"); break;
  case ZORBA_BYTE_ORDER_MARK_NO:
    aInternalSerializer.setParameter("byte-order-mark", "no"); break;
  }

  switch (aSerializerOptions.include_content_type)
  {
  case ZORBA_INCLUDE_CONTENT_TYPE_YES:
    aInternalSerializer.setParameter("include-content-type", "yes"); break;
  case ZORBA_INCLUDE_CONTENT_TYPE_NO:
    aInternalSerializer.setParameter("include-content-type", "no"); break;
  }

  switch (aSerializerOptions.indent)
  {
  case ZORBA_INDENT_YES:
    aInternalSerializer.setParameter("indent", "yes"); break;
  case ZORBA_INDENT_NO:
    aInternalSerializer.setParameter("indent", "no"); break;
  }

  switch (aSerializerOptions.omit_xml_declaration)
  {
  case ZORBA_OMIT_XML_DECLARATION_YES:
    aInternalSerializer.setParameter("omit-xml-declaration", "yes"); break;
  case ZORBA_OMIT_XML_DECLARATION_NO:
    aInternalSerializer.setParameter("omit-xml-declaration", "no"); break;
  }

  switch (aSerializerOptions.standalone)
  {
  case ZORBA_STANDALONE_YES:
    aInternalSerializer.setParameter("standalone", "yes"); break;
  case ZORBA_STANDALONE_NO:
    aInternalSerializer.setParameter("standalone", "no"); break;
  case ZORBA_STANDALONE_OMIT:
    aInternalSerializer.setParameter("standalone", "omit"); break;
  }

  switch (aSerializerOptions.undeclare_prefixes)
  {
  case ZORBA_UNDECLARE_PREFIXES_YES:
    aInternalSerializer.setParameter("undeclare-prefixes", "yes"); break;
  case ZORBA_UNDECLARE_PREFIXES_NO:
    aInternalSerializer.setParameter("undeclare-prefixes", "no"); break;
  }

  if (aSerializerOptions.media_type != "")
    aInternalSerializer.setParameter("media-type", aSerializerOptions.media_type.c_str());

  if (aSerializerOptions.doctype_system != "")
    aInternalSerializer.setParameter("doctype-system", aSerializerOptions.doctype_system.c_str());

  if (aSerializerOptions.doctype_public != "")
    aInternalSerializer.setParameter("doctype-public", aSerializerOptions.doctype_public.c_str());

  if (aSerializerOptions.cdata_section_elements != "")
    aInternalSerializer.setParameter("cdata-section-elements", aSerializerOptions.cdata_section_elements.c_str());

  if (aSerializerOptions.version != "")
    aInternalSerializer.setParameter("version", aSerializerOptions.version.c_str());
}

void
SerializerImpl::setSerializationParameters(
  serializer&   aInternalSerializer,
  ItemSequence* aSerializerOptions)
{
  Item lItem;
  while (aSerializerOptions->next(lItem)) {
    Item lNodeName;
    lItem.getNodeName(lNodeName);
    aInternalSerializer.setParameter(lNodeName.getLocalName().c_str(), lItem.getStringValue().c_str());
  }
}

} // namespace zorba
<commit_msg>fixed a warning introduced in revision 9353. Also, re-enabled the test for bug #3085093 which was also fixed in rev. 9353.<commit_after>/*
 * Copyright 2006-2009 The FLWOR Foundation.
 *
 * 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 <zorba/item.h>
#include <zorba/options.h>
#include <zorba/singleton_item_sequence.h>
#include <zorba/serializable.h>
#include <zorba/default_error_handler.h>

#include "api/zorbaimpl.h"
#include "api/serialization/serializable_wrapper.h"
#include "api/serialization/serializable.h"
#include "api/unmarshaller.h"

#include "serializerimpl.h"

namespace zorba {

Serializer_t
Serializer::createSerializer(const Zorba_SerializerOptions_t& aOptions)
{
  return new SerializerImpl(aOptions);
}

Serializer_t
Serializer::createSerializer(ItemSequence* aOptions)
{
  return new SerializerImpl(aOptions);
}

SerializerImpl::SerializerImpl(const Zorba_SerializerOptions_t& aOptions, ErrorHandler* aErrorHandler)
  : theErrorHandler(aErrorHandler),
    theInternalSerializer(&theErrorManager)
{
  setSerializationParameters(theInternalSerializer, aOptions);
  if (!theErrorHandler) {
    theErrorHandler = new DefaultErrorHandler();
  }
}

SerializerImpl::SerializerImpl(ItemSequence* aOptions, ErrorHandler* aErrorHandler)
  : theErrorHandler(aErrorHandler),
    theInternalSerializer(&theErrorManager)
{
  setSerializationParameters(theInternalSerializer, aOptions);
  if (!theErrorHandler) {
    theErrorHandler = new DefaultErrorHandler();
  }
}

void
SerializerImpl::serialize(Serializable* aObject, std::ostream& aOs) const
{
  try {
    intern::SerializableWrapper lWrapper(aObject);
    theInternalSerializer.serialize((intern::Serializable*)&lWrapper, aOs);
  } catch (error::ZorbaError& e) {
    ZorbaImpl::notifyError(theErrorHandler, e);
  }
}

int
SerializerImpl::getSerializationMethod() const
{
  switch (theInternalSerializer.getSerializationMethod())
  {
  case serializer::PARAMETER_VALUE_HTML:
    return ZORBA_SERIALIZATION_METHOD_HTML;
  case serializer::PARAMETER_VALUE_XHTML:
    return ZORBA_SERIALIZATION_METHOD_XHTML;
  case serializer::PARAMETER_VALUE_TEXT:
    return ZORBA_SERIALIZATION_METHOD_TEXT;
  case serializer::PARAMETER_VALUE_JSON:
    return ZORBA_SERIALIZATION_METHOD_JSON;
  case serializer::PARAMETER_VALUE_JSONML:
    return ZORBA_SERIALIZATION_METHOD_JSONML;
  case serializer::PARAMETER_VALUE_BINARY:
    return ZORBA_SERIALIZATION_METHOD_BINARY;
  default:
    return ZORBA_SERIALIZATION_METHOD_XML;
  }
}

void
SerializerImpl::setSerializationParameters(
  serializer&                       aInternalSerializer,
  const Zorba_SerializerOptions_t&  aSerializerOptions)
{
  switch (aSerializerOptions.ser_method)
  {
  case ZORBA_SERIALIZATION_METHOD_XML:
    aInternalSerializer.setParameter("method", "xml"); break;
  case ZORBA_SERIALIZATION_METHOD_HTML:
    aInternalSerializer.setParameter("method", "html"); break;
  case ZORBA_SERIALIZATION_METHOD_XHTML:
    aInternalSerializer.setParameter("method", "xhtml"); break;
  case ZORBA_SERIALIZATION_METHOD_TEXT:
    aInternalSerializer.setParameter("method", "text"); break;
  case ZORBA_SERIALIZATION_METHOD_JSON:
    aInternalSerializer.setParameter("method", "json"); break;
  case ZORBA_SERIALIZATION_METHOD_JSONML:
    aInternalSerializer.setParameter("method", "jsonml"); break;
  case ZORBA_SERIALIZATION_METHOD_BINARY:
    aInternalSerializer.setParameter("method", "binary"); break;
  }

  switch (aSerializerOptions.byte_order_mark)
  {
  case ZORBA_BYTE_ORDER_MARK_YES:
    aInternalSerializer.setParameter("byte-order-mark", "yes"); break;
  case ZORBA_BYTE_ORDER_MARK_NO:
    aInternalSerializer.setParameter("byte-order-mark", "no"); break;
  }

  switch (aSerializerOptions.include_content_type)
  {
  case ZORBA_INCLUDE_CONTENT_TYPE_YES:
    aInternalSerializer.setParameter("include-content-type", "yes"); break;
  case ZORBA_INCLUDE_CONTENT_TYPE_NO:
    aInternalSerializer.setParameter("include-content-type", "no"); break;
  }

  switch (aSerializerOptions.indent)
  {
  case ZORBA_INDENT_YES:
    aInternalSerializer.setParameter("indent", "yes"); break;
  case ZORBA_INDENT_NO:
    aInternalSerializer.setParameter("indent", "no"); break;
  }

  switch (aSerializerOptions.omit_xml_declaration)
  {
  case ZORBA_OMIT_XML_DECLARATION_YES:
    aInternalSerializer.setParameter("omit-xml-declaration", "yes"); break;
  case ZORBA_OMIT_XML_DECLARATION_NO:
    aInternalSerializer.setParameter("omit-xml-declaration", "no"); break;
  }

  switch (aSerializerOptions.standalone)
  {
  case ZORBA_STANDALONE_YES:
    aInternalSerializer.setParameter("standalone", "yes"); break;
  case ZORBA_STANDALONE_NO:
    aInternalSerializer.setParameter("standalone", "no"); break;
  case ZORBA_STANDALONE_OMIT:
    aInternalSerializer.setParameter("standalone", "omit"); break;
  }

  switch (aSerializerOptions.undeclare_prefixes)
  {
  case ZORBA_UNDECLARE_PREFIXES_YES:
    aInternalSerializer.setParameter("undeclare-prefixes", "yes"); break;
  case ZORBA_UNDECLARE_PREFIXES_NO:
    aInternalSerializer.setParameter("undeclare-prefixes", "no"); break;
  }

  if (aSerializerOptions.media_type != "")
    aInternalSerializer.setParameter("media-type", aSerializerOptions.media_type.c_str());

  if (aSerializerOptions.doctype_system != "")
    aInternalSerializer.setParameter("doctype-system", aSerializerOptions.doctype_system.c_str());

  if (aSerializerOptions.doctype_public != "")
    aInternalSerializer.setParameter("doctype-public", aSerializerOptions.doctype_public.c_str());

  if (aSerializerOptions.cdata_section_elements != "")
    aInternalSerializer.setParameter("cdata-section-elements", aSerializerOptions.cdata_section_elements.c_str());

  if (aSerializerOptions.version != "")
    aInternalSerializer.setParameter("version", aSerializerOptions.version.c_str());
}

void
SerializerImpl::setSerializationParameters(
  serializer&   aInternalSerializer,
  ItemSequence* aSerializerOptions)
{
  Item lItem;
  while (aSerializerOptions->next(lItem)) {
    Item lNodeName;
    lItem.getNodeName(lNodeName);
    aInternalSerializer.setParameter(lNodeName.getLocalName().c_str(), lItem.getStringValue().c_str());
  }
}

} // namespace zorba
<|endoftext|>


<commit_before>#include <Tools/Profiler.h>
#include <GLFW/glfw3.h>
#include <imgui/imgui.h>
#include <Graphics/Color.h>

using namespace Osm;
using namespace std;

vector<ImU32> colors =
{
	ImColor(Color::Magenta.integervalue),
	ImColor(Color::Yellow.integervalue),
	ImColor(Color::Green.integervalue),
	ImColor(Color::Cyan.integervalue),
	ImColor(Color::Orange.integervalue)
};

Profiler::Profiler(CEngine& engine)
	: Component(engine)
	, _sections()
	, _frameStart(-1.0f)
{
}

void Profiler::StartFrame()
{
	_frameStart = glfwGetTime();
}

uint Profiler::StartSection(const std::string& name)
{
	Section section;
	section.Name = name;
	section.StartTime = glfwGetTime() - _frameStart;
	section.EndTime = -1.0f;
	_sections.push_back(std::move(section));
	return _sections.size() - 1;
}

void Profiler::EndSection(uint sectionId)
{
	ASSERT(sectionId >= 0 && sectionId < _sections.size());
	auto& section = _sections[sectionId];
	section.EndTime = glfwGetTime() - _frameStart;
}

#ifdef INSPECTOR
void Profiler::Inspect()
{
	ImGuiWindowFlags window_flags = 0;
	window_flags |= ImGuiWindowFlags_NoResize;
	bool open;

	if (ImGui::Begin("Profiler"))
	{

		ImDrawList* draw_list = ImGui::GetWindowDrawList();

		float spacing = 8.0f;
		float sz = 10.0f;
		float barOffset = 200;
		const ImVec2 basePos = ImGui::GetCursorScreenPos();
		float lenghtF = 1000 * 30;

		for (size_t i = 0; i < _sections.size(); i++)
		{
			ImVec2 p = ImGui::GetCursorScreenPos();

			ImU32 color = colors[i % colors.size()];

			auto& section = _sections[i];
			if (section.EndTime == -1.0f)
				continue;

			double time = section.EndTime - section.StartTime;

			ImGui::TextColored(ImColor(color), "%s - %f", section.Name.c_str(), time * 1000);

			float x0 = p.x + (int)(section.StartTime * lenghtF) + barOffset;
			float x1 = p.x + (int)(section.EndTime * lenghtF) + barOffset;

			draw_list->AddRectFilled(ImVec2(x0, p.y + 4), ImVec2(x1, p.y + sz), color);

			p.y += sz + spacing;
			ImGui::SetCursorScreenPos(p);

			//p.y += sz + spacing;

			//x = p.x + 4;

			// time *= 1000;
			// ImGui::Text("Section: %s took: %f", section.Name.c_str(), time);

			// ImGui::

			// ImGui::ProgressBar()
			// section.EndTime = glfwGetTime();
		}

		float lowY = ImGui::GetCursorScreenPos().y;
		ImVec2 p = ImGui::GetCursorScreenPos();

		float max = 1.0f / 60.0f;
		draw_list->AddRectFilled(	ImVec2(p.x + max * lenghtF + barOffset, 0),
									ImVec2(p.x + max * lenghtF + barOffset + 2, lowY),
									ImColor(Color::White.integervalue));

		ImGui::End();
	}

	_sections.clear();
}
#endif
<commit_msg>Code cleanup<commit_after>#include <Tools/Profiler.h>
#include <GLFW/glfw3.h>
#include <imgui/imgui.h>
#include <Graphics/Color.h>

using namespace Osm;
using namespace std;

vector<ImU32> colors =
{
	ImColor(Color::Magenta.integervalue),
	ImColor(Color::Yellow.integervalue),
	ImColor(Color::Green.integervalue),
	ImColor(Color::Cyan.integervalue),
	ImColor(Color::Orange.integervalue)
};

Profiler::Profiler(CEngine& engine)
	: Component(engine)
	, _sections()
	, _frameStart(-1.0f)
{
}

void Profiler::StartFrame()
{
	_frameStart = glfwGetTime();
}

uint Profiler::StartSection(const std::string& name)
{
	Section section;
	section.Name = name;
	section.StartTime = glfwGetTime() - _frameStart;
	section.EndTime = -1.0f;
	_sections.push_back(std::move(section));
	return _sections.size() - 1;
}

void Profiler::EndSection(uint sectionId)
{
	ASSERT(sectionId >= 0 && sectionId < _sections.size());
	auto& section = _sections[sectionId];
	section.EndTime = glfwGetTime() - _frameStart;
}

#ifdef INSPECTOR
void Profiler::Inspect()
{
	ImGuiWindowFlags window_flags = 0;
	window_flags |= ImGuiWindowFlags_NoResize;
	bool open;

	if (ImGui::Begin("Profiler"))
	{

		ImDrawList* draw_list = ImGui::GetWindowDrawList();

		float spacing = 8.0f;
		float sz = 10.0f;
		float barOffset = 200;
		const ImVec2 basePos = ImGui::GetCursorScreenPos();
		float lenghtF = 1000 * 30;

		for (size_t i = 0; i < _sections.size(); i++)
		{
			ImVec2 p = ImGui::GetCursorScreenPos();

			ImU32 color = colors[i % colors.size()];

			auto& section = _sections[i];
			if (section.EndTime == -1.0f)
				continue;

			double time = section.EndTime - section.StartTime;

			ImGui::TextColored(ImColor(color), "%s - %f", section.Name.c_str(), time * 1000);

			float x0 = p.x + (int)(section.StartTime * lenghtF) + barOffset;
			float x1 = p.x + (int)(section.EndTime * lenghtF) + barOffset;

			draw_list->AddRectFilled(ImVec2(x0, p.y + 4), ImVec2(x1, p.y + sz), color);

			p.y += sz + spacing;
			ImGui::SetCursorScreenPos(p);
		}

		float lowY = ImGui::GetCursorScreenPos().y;
		ImVec2 p = ImGui::GetCursorScreenPos();

		float max = 1.0f / 60.0f;
		draw_list->AddRectFilled(	ImVec2(p.x + max * lenghtF + barOffset, 0),
									ImVec2(p.x + max * lenghtF + barOffset + 2, lowY),
									ImColor(Color::White.integervalue));

		ImGui::End();
	}

	_sections.clear();
}
#endif
<|endoftext|>


<commit_before>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <ctime>
#include <QMutexLocker>
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/internal.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::multiplexing;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
subscriber::subscriber() {
  // Register self in subscriber list.
  QMutexLocker lock1(&gl_subscribersm);
  QMutexLocker lock2(&_mutex);
  _process_in = true;
  _process_out = true;
  gl_subscribers.push_back(this);
  logging::debug(logging::low) << "multiplexing: "
    << gl_subscribers.size()
    << " subscribers are registered after insertion";
}

/**
 *  Destructor.
 */
subscriber::~subscriber() {
  clean();
  QMutexLocker lock(&gl_subscribersm);
  for (QVector<subscriber*>::iterator it(gl_subscribers.begin());
       it != gl_subscribers.end();)
    if (*it == this)
      it = gl_subscribers.erase(it);
    else
      ++it;
}

/**
 *  Unregister or re-register from event publishing notifications.
 *
 *  @param[in] in  Process input events.
 *  @param[in] out Process output events.
 */
void subscriber::process(bool in, bool out) {
  // Debug message.
  logging::debug(logging::low) << "multiplexing: subscriber " \
    "processing request in=" << in << ", out=" << out;

  // Lock mutex.
  QMutexLocker lock(&_mutex);

  // Set data.
  _process_in = in;
  _process_out = (_process_out && out);

  // Unregister.
  if (!in || !out) {
    _cv.wakeAll();
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after deletion";
  }
  // Re-register.
  else if (in && out) {
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after reregistration";
  }

  return ;
}

/**
 *  Get the next available event.
 *
 *  @param[out] d Next available event.
 */
void subscriber::read(misc::shared_ptr<io::data>& d) {
  this->read(d, (time_t)-1);
  return ;
}

/**
 *  Get the next available event without waiting more than timeout.
 *
 *  @param[out] event     Next available event.
 *  @param[in]  timeout   Date limit.
 *  @param[out] timed_out Set to true if read timed out.
 */
void subscriber::read(
                   misc::shared_ptr<io::data>& event,
                   time_t timeout,
                   bool* timed_out) {
  QMutexLocker lock(&_mutex);

  // No data is directly available.
  if (_events.empty()) {
    // Wait a while if subscriber was not shutdown.
    if (_process_in && _process_out) {
      if ((time_t)-1 == timeout)
        _cv.wait(&_mutex);
      else {
        time_t now(time(NULL));
        if (now < timeout) {
          bool timedout(!_cv.wait(&_mutex, (timeout - now) * 1000));
          if (timed_out)
            *timed_out = timedout;
        }
        else if (timed_out)
          *timed_out = true;
      }
      if (!_events.isEmpty()) {
        event = _events.dequeue();
        lock.unlock();
        logging::debug(logging::low) << "multiplexing: "
          << _events.size() << " events remaining in subcriber";
      }
      else
        event.clear();
    }
    // If subscriber is shutdown, notify caller.
    else
      throw (io::exceptions::shutdown(true, true) << "subscriber "
               << this << " is shutdown, cannot read");
  }
  // Data is available, no need to wait.
  else {
    if (!_process_in && _process_out)
      throw (io::exceptions::shutdown(true, false) << "subscriber "
             << this << " is shutdown, cannot read");
    event = _events.dequeue();
    lock.unlock();
    logging::debug(logging::low) << "multiplexing: " << _events.size()
      << " events remaining in subscriber";
  }
  return ;
}

/**
 *  Add a new event to the internal event list.
 *
 *  @param[in] event Event to add.
 */
void subscriber::write(misc::shared_ptr<io::data> const& event) {
  {
    QMutexLocker lock(&_mutex);
    _events.enqueue(event);
  }
  _cv.wakeOne();
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  subscriber is not copyable. Any attempt to use the copy constructor
 *  will result in a call to abort().
 *
 *  @param[in] s Unused.
 */
subscriber::subscriber(subscriber const& s) : io::stream(s) {
  assert(!"subscriber is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  subscriber is not copyable. Any attempt to use the assignment
 *  operator will result in a call to abort().
 *
 *  @param[in] s Unused.
 *
 *  @return This object.
 */
subscriber& subscriber::operator=(subscriber const& s) {
  (void)s;
  assert(!"subscriber is not copyable");
  abort();
  return (*this);
}

/**
 *  Release all events stored within the internal list.
 */
void subscriber::clean() {
  QMutexLocker lock(&_mutex);
  _events.clear();
  return ;
}
<commit_msg>Some technical error message was changed to a more readable one.<commit_after>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cassert>
#include <cstdlib>
#include <ctime>
#include <QMutexLocker>
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/internal.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::multiplexing;

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Default constructor.
 */
subscriber::subscriber() {
  // Register self in subscriber list.
  QMutexLocker lock1(&gl_subscribersm);
  QMutexLocker lock2(&_mutex);
  _process_in = true;
  _process_out = true;
  gl_subscribers.push_back(this);
  logging::debug(logging::low) << "multiplexing: "
    << gl_subscribers.size()
    << " subscribers are registered after insertion";
}

/**
 *  Destructor.
 */
subscriber::~subscriber() {
  clean();
  QMutexLocker lock(&gl_subscribersm);
  for (QVector<subscriber*>::iterator it(gl_subscribers.begin());
       it != gl_subscribers.end();)
    if (*it == this)
      it = gl_subscribers.erase(it);
    else
      ++it;
}

/**
 *  Unregister or re-register from event publishing notifications.
 *
 *  @param[in] in  Process input events.
 *  @param[in] out Process output events.
 */
void subscriber::process(bool in, bool out) {
  // Debug message.
  logging::debug(logging::low) << "multiplexing: subscriber " \
    "processing request in=" << in << ", out=" << out;

  // Lock mutex.
  QMutexLocker lock(&_mutex);

  // Set data.
  _process_in = in;
  _process_out = (_process_out && out);

  // Unregister.
  if (!in || !out) {
    _cv.wakeAll();
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after deletion";
  }
  // Re-register.
  else if (in && out) {
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after reregistration";
  }

  return ;
}

/**
 *  Get the next available event.
 *
 *  @param[out] d Next available event.
 */
void subscriber::read(misc::shared_ptr<io::data>& d) {
  this->read(d, (time_t)-1);
  return ;
}

/**
 *  Get the next available event without waiting more than timeout.
 *
 *  @param[out] event     Next available event.
 *  @param[in]  timeout   Date limit.
 *  @param[out] timed_out Set to true if read timed out.
 */
void subscriber::read(
                   misc::shared_ptr<io::data>& event,
                   time_t timeout,
                   bool* timed_out) {
  QMutexLocker lock(&_mutex);

  // No data is directly available.
  if (_events.empty()) {
    // Wait a while if subscriber was not shutdown.
    if (_process_in && _process_out) {
      if ((time_t)-1 == timeout)
        _cv.wait(&_mutex);
      else {
        time_t now(time(NULL));
        if (now < timeout) {
          bool timedout(!_cv.wait(&_mutex, (timeout - now) * 1000));
          if (timed_out)
            *timed_out = timedout;
        }
        else if (timed_out)
          *timed_out = true;
      }
      if (!_events.isEmpty()) {
        event = _events.dequeue();
        lock.unlock();
        logging::debug(logging::low) << "multiplexing: "
          << _events.size() << " events remaining in subcriber";
      }
      else
        event.clear();
    }
    // If subscriber is shutdown, notify caller.
    else
      throw (io::exceptions::shutdown(true, true)
             << "thread is shutdown, cannot get any further event");
  }
  // Data is available, no need to wait.
  else {
    if (!_process_in && _process_out)
      throw (io::exceptions::shutdown(true, false)
             << "thread is shutdown, cannot get any further event");
    event = _events.dequeue();
    lock.unlock();
    logging::debug(logging::low) << "multiplexing: " << _events.size()
      << " events remaining in subscriber";
  }
  return ;
}

/**
 *  Add a new event to the internal event list.
 *
 *  @param[in] event Event to add.
 */
void subscriber::write(misc::shared_ptr<io::data> const& event) {
  {
    QMutexLocker lock(&_mutex);
    _events.enqueue(event);
  }
  _cv.wakeOne();
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  @brief Copy constructor.
 *
 *  subscriber is not copyable. Any attempt to use the copy constructor
 *  will result in a call to abort().
 *
 *  @param[in] s Unused.
 */
subscriber::subscriber(subscriber const& s) : io::stream(s) {
  assert(!"subscriber is not copyable");
  abort();
}

/**
 *  @brief Assignment operator.
 *
 *  subscriber is not copyable. Any attempt to use the assignment
 *  operator will result in a call to abort().
 *
 *  @param[in] s Unused.
 *
 *  @return This object.
 */
subscriber& subscriber::operator=(subscriber const& s) {
  (void)s;
  assert(!"subscriber is not copyable");
  abort();
  return (*this);
}

/**
 *  Release all events stored within the internal list.
 */
void subscriber::clean() {
  QMutexLocker lock(&_mutex);
  _events.clear();
  return ;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * 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 the copyright holders nor the names of its
 * contributors 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.
 *
 * Authors: Gabe Black
 *          Stephen Hines
 */

#ifndef __ARCH_ARM_PREDECODER_HH__
#define __ARCH_ARM_PREDECODER_HH__

#include "arch/arm/types.hh"
#include "base/misc.hh"
#include "base/types.hh"

class ThreadContext;

namespace ArmISA
{
    class Predecoder
    {
      protected:
        ThreadContext * tc;
        //The extended machine instruction being generated
        ExtMachInst emi;
        MachInst data;
        bool bigThumb;
        int offset;

      public:
        Predecoder(ThreadContext * _tc) :
            tc(_tc), data(0), bigThumb(false), offset(0)
        {}

        ThreadContext * getTC()
        {
            return tc;
        }

        void setTC(ThreadContext * _tc)
        {
            tc = _tc;
        }

        void reset()
        {
            bigThumb = false;
            offset = 0;
            emi = 0;
        }

        void process()
        {
            if (!emi.thumb) {
                emi.instBits = data;
                emi.sevenAndFour = bits(data, 7) && bits(data, 4);
                emi.isMisc = (bits(data, 24, 23) == 0x2 &&
                              bits(data, 20) == 0);
                DPRINTF(Predecoder, "Arm inst.\n");
            } else {
                uint16_t word = (data >> (offset * 8));
                if (bigThumb) {
                    // A 32 bit thumb inst is half collected.
                    emi.instBits = emi.instBits | word;
                    bigThumb = false;
                    offset += 2;
                    DPRINTF(Predecoder, "Second half of 32 bit Thumb.\n");
                } else {
                    uint16_t highBits = word & 0xF800;
                    if (highBits == 0xE800 || highBits == 0xF000 ||
                            highBits == 0xF800) {
                        // The start of a 32 bit thumb inst.
                        emi.bigThumb = 1;
                        if (offset == 0) {
                            // We've got the whole thing.
                            DPRINTF(Predecoder,
                                    "All of 32 bit Thumb.\n");
                            emi.instBits = (data >> 16) | (data << 16);
                            offset += 4;
                        } else {
                            // We only have the first half word.
                            DPRINTF(Predecoder,
                                    "First half of 32 bit Thumb.\n");
                            emi.instBits = (uint32_t)word << 16;
                            bigThumb = true;
                            offset += 2;
                        }
                    } else {
                        // A 16 bit thumb inst.
                        DPRINTF(Predecoder, "16 bit Thumb.\n");
                        offset += 2;
                        emi.instBits = word;
                        // Set the condition code field artificially.
                        emi.condCode = COND_UC;
                    }
                }
            }
        }

        //Use this to give data to the predecoder. This should be used
        //when there is control flow.
        void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
        {
            data = inst;
            offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
            emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0;
            process();
        }

        //Use this to give data to the predecoder. This should be used
        //when instructions are executed in order.
        void moreBytes(MachInst machInst)
        {
            moreBytes(0, 0, machInst);
        }

        bool needMoreBytes()
        {
            return sizeof(MachInst) > offset;
        }

        bool extMachInstReady()
        {
            // The only way an instruction wouldn't be ready is if this is a
            // 32 bit ARM instruction that's not 32 bit aligned.
            return !bigThumb;
        }

        int getInstSize()
        {
            return (!emi.thumb || emi.bigThumb) ? 4 : 2;
        }

        //This returns a constant reference to the ExtMachInst to avoid a copy
        ExtMachInst getExtMachInst()
        {
            ExtMachInst thisEmi = emi;
            emi = 0;
            return thisEmi;
        }
    };
};

#endif // __ARCH_ARM_PREDECODER_HH__
<commit_msg>ARM: Make the predecoder print out the ExtMachInst it gathered when traced.<commit_after>/*
 * Copyright (c) 2010 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2006 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * 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 the copyright holders nor the names of its
 * contributors 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.
 *
 * Authors: Gabe Black
 *          Stephen Hines
 */

#ifndef __ARCH_ARM_PREDECODER_HH__
#define __ARCH_ARM_PREDECODER_HH__

#include "arch/arm/types.hh"
#include "base/misc.hh"
#include "base/types.hh"

class ThreadContext;

namespace ArmISA
{
    class Predecoder
    {
      protected:
        ThreadContext * tc;
        //The extended machine instruction being generated
        ExtMachInst emi;
        MachInst data;
        bool bigThumb;
        int offset;

      public:
        Predecoder(ThreadContext * _tc) :
            tc(_tc), data(0), bigThumb(false), offset(0)
        {}

        ThreadContext * getTC()
        {
            return tc;
        }

        void setTC(ThreadContext * _tc)
        {
            tc = _tc;
        }

        void reset()
        {
            bigThumb = false;
            offset = 0;
            emi = 0;
        }

        void process()
        {
            if (!emi.thumb) {
                emi.instBits = data;
                emi.sevenAndFour = bits(data, 7) && bits(data, 4);
                emi.isMisc = (bits(data, 24, 23) == 0x2 &&
                              bits(data, 20) == 0);
                DPRINTF(Predecoder, "Arm inst.\n");
            } else {
                uint16_t word = (data >> (offset * 8));
                if (bigThumb) {
                    // A 32 bit thumb inst is half collected.
                    emi.instBits = emi.instBits | word;
                    bigThumb = false;
                    offset += 2;
                    DPRINTF(Predecoder, "Second half of 32 bit Thumb: %#x.\n",
                            emi.instBits);
                } else {
                    uint16_t highBits = word & 0xF800;
                    if (highBits == 0xE800 || highBits == 0xF000 ||
                            highBits == 0xF800) {
                        // The start of a 32 bit thumb inst.
                        emi.bigThumb = 1;
                        if (offset == 0) {
                            // We've got the whole thing.
                            emi.instBits = (data >> 16) | (data << 16);
                            DPRINTF(Predecoder, "All of 32 bit Thumb: %#x.\n",
                                    emi.instBits);
                            offset += 4;
                        } else {
                            // We only have the first half word.
                            DPRINTF(Predecoder,
                                    "First half of 32 bit Thumb.\n");
                            emi.instBits = (uint32_t)word << 16;
                            bigThumb = true;
                            offset += 2;
                        }
                    } else {
                        // A 16 bit thumb inst.
                        offset += 2;
                        emi.instBits = word;
                        // Set the condition code field artificially.
                        emi.condCode = COND_UC;
                        DPRINTF(Predecoder, "16 bit Thumb: %#x.\n",
                                emi.instBits);
                    }
                }
            }
        }

        //Use this to give data to the predecoder. This should be used
        //when there is control flow.
        void moreBytes(Addr pc, Addr fetchPC, MachInst inst)
        {
            data = inst;
            offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
            emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0;
            process();
        }

        //Use this to give data to the predecoder. This should be used
        //when instructions are executed in order.
        void moreBytes(MachInst machInst)
        {
            moreBytes(0, 0, machInst);
        }

        bool needMoreBytes()
        {
            return sizeof(MachInst) > offset;
        }

        bool extMachInstReady()
        {
            // The only way an instruction wouldn't be ready is if this is a
            // 32 bit ARM instruction that's not 32 bit aligned.
            return !bigThumb;
        }

        int getInstSize()
        {
            return (!emi.thumb || emi.bigThumb) ? 4 : 2;
        }

        //This returns a constant reference to the ExtMachInst to avoid a copy
        ExtMachInst getExtMachInst()
        {
            ExtMachInst thisEmi = emi;
            emi = 0;
            return thisEmi;
        }
    };
};

#endif // __ARCH_ARM_PREDECODER_HH__
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * 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
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * 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.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_REMOTEGDB_HH__
#define __ARCH_X86_REMOTEGDB_HH__

#error X86 is not yet supported!

namespace X86ISA
{
};

#endif // __ARCH_X86_REMOTEGDB_HH__
<commit_msg>Filled in a stub header file for remote gdb<commit_after>/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * 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
 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * 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.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_X86_REMOTEGDB_HH__
#define __ARCH_X86_REMOTEGDB_HH__

#include "arch/x86/types.hh"
#include "base/remote_gdb.hh"

class System;
class ThreadContext;

namespace X86ISA
{
    class RemoteGDB : public BaseRemoteGDB
    {
      protected:
        enum RegisterContants
        {
            //XXX fill this in
        };

      public:
        RemoteGDB(System *system, ThreadContext *context);

        bool acc(Addr addr, size_t len);

      protected:
        void getregs();
        void setregs();

        void clearSingleStep();
        void setSingleStep();

        Addr nextBkpt;
    };
}

#endif // __ARCH_X86_REMOTEGDB_HH__
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "arrow/util/value_parsing.h"

#include <string>
#include <utility>

#include "arrow/util/double_conversion.h"

namespace arrow {
namespace internal {

namespace {

struct StringToFloatConverterImpl {
  StringToFloatConverterImpl()
      : main_converter_(flags_, main_junk_value_, main_junk_value_, "inf", "nan"),
        fallback_converter_(flags_, fallback_junk_value_, fallback_junk_value_, "inf",
                            "nan") {}

  // NOTE: This is only supported in double-conversion 3.1+
  static constexpr int flags_ =
      util::double_conversion::StringToDoubleConverter::ALLOW_CASE_INSENSIBILITY;

  // Two unlikely values to signal a parsing error
  static constexpr double main_junk_value_ = 0.7066424364107089;
  static constexpr double fallback_junk_value_ = 0.40088499148279166;

  util::double_conversion::StringToDoubleConverter main_converter_;
  util::double_conversion::StringToDoubleConverter fallback_converter_;
};

static const StringToFloatConverterImpl g_string_to_float;

}  // namespace

bool StringToFloat(const char* s, size_t length, float* out) {
  int processed_length;
  float v;
  v = g_string_to_float.main_converter_.StringToFloat(s, static_cast<int>(length),
                                                      &processed_length);
  if (ARROW_PREDICT_FALSE(v == static_cast<float>(g_string_to_float.main_junk_value_))) {
    v = g_string_to_float.fallback_converter_.StringToFloat(s, static_cast<int>(length),
                                                            &processed_length);
    if (ARROW_PREDICT_FALSE(v ==
                            static_cast<float>(g_string_to_float.fallback_junk_value_))) {
      return false;
    }
  }
  *out = v;
  return true;
}

bool StringToFloat(const char* s, size_t length, double* out) {
  int processed_length;
  double v;
  v = g_string_to_float.main_converter_.StringToDouble(s, static_cast<int>(length),
                                                       &processed_length);
  if (ARROW_PREDICT_FALSE(v == g_string_to_float.main_junk_value_)) {
    v = g_string_to_float.fallback_converter_.StringToDouble(s, static_cast<int>(length),
                                                             &processed_length);
    if (ARROW_PREDICT_FALSE(v == g_string_to_float.fallback_junk_value_)) {
      return false;
    }
  }
  *out = v;
  return true;
}

// ----------------------------------------------------------------------
// strptime-like parsing

class StrptimeTimestampParser : public TimestampParser {
 public:
  explicit StrptimeTimestampParser(std::string format) : format_(std::move(format)) {}

  bool operator()(const char* s, size_t length, TimeUnit::type out_unit,
                  int64_t* out) const override {
    return ParseTimestampStrptime(s, length, format_.c_str(),
                                  /*ignore_time_in_day=*/false,
                                  /*allow_trailing_chars=*/false, out_unit, out);
  }

 private:
  std::string format_;
};

class ISO8601Parser : public TimestampParser {
 public:
  ISO8601Parser() {}

  bool operator()(const char* s, size_t length, TimeUnit::type out_unit,
                  int64_t* out) const override {
    return ParseTimestampISO8601(s, length, out_unit, out);
  }
};

}  // namespace internal

std::shared_ptr<TimestampParser> TimestampParser::MakeStrptime(std::string format) {
  return std::make_shared<internal::StrptimeTimestampParser>(std::move(format));
}

std::shared_ptr<TimestampParser> TimestampParser::MakeISO8601() {
  return std::make_shared<internal::ISO8601Parser>();
}

}  // namespace arrow
<commit_msg>ARROW-8962: [C++] Add explicit implementation for junk values<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "arrow/util/value_parsing.h"

#include <string>
#include <utility>

#include "arrow/util/double_conversion.h"

namespace arrow {
namespace internal {

namespace {

struct StringToFloatConverterImpl {
  StringToFloatConverterImpl()
      : main_converter_(flags_, main_junk_value_, main_junk_value_, "inf", "nan"),
        fallback_converter_(flags_, fallback_junk_value_, fallback_junk_value_, "inf",
                            "nan") {}

  // NOTE: This is only supported in double-conversion 3.1+
  static constexpr int flags_ =
      util::double_conversion::StringToDoubleConverter::ALLOW_CASE_INSENSIBILITY;

  // Two unlikely values to signal a parsing error
  static constexpr double main_junk_value_ = 0.7066424364107089;
  static constexpr double fallback_junk_value_ = 0.40088499148279166;

  util::double_conversion::StringToDoubleConverter main_converter_;
  util::double_conversion::StringToDoubleConverter fallback_converter_;
};

static const StringToFloatConverterImpl g_string_to_float;

// Older clang versions need an explicit implementation definition.
constexpr double StringToFloatConverterImpl::main_junk_value_;
constexpr double StringToFloatConverterImpl::fallback_junk_value_;

}  // namespace

bool StringToFloat(const char* s, size_t length, float* out) {
  int processed_length;
  float v;
  v = g_string_to_float.main_converter_.StringToFloat(s, static_cast<int>(length),
                                                      &processed_length);
  if (ARROW_PREDICT_FALSE(v == static_cast<float>(g_string_to_float.main_junk_value_))) {
    v = g_string_to_float.fallback_converter_.StringToFloat(s, static_cast<int>(length),
                                                            &processed_length);
    if (ARROW_PREDICT_FALSE(v ==
                            static_cast<float>(g_string_to_float.fallback_junk_value_))) {
      return false;
    }
  }
  *out = v;
  return true;
}

bool StringToFloat(const char* s, size_t length, double* out) {
  int processed_length;
  double v;
  v = g_string_to_float.main_converter_.StringToDouble(s, static_cast<int>(length),
                                                       &processed_length);
  if (ARROW_PREDICT_FALSE(v == g_string_to_float.main_junk_value_)) {
    v = g_string_to_float.fallback_converter_.StringToDouble(s, static_cast<int>(length),
                                                             &processed_length);
    if (ARROW_PREDICT_FALSE(v == g_string_to_float.fallback_junk_value_)) {
      return false;
    }
  }
  *out = v;
  return true;
}

// ----------------------------------------------------------------------
// strptime-like parsing

class StrptimeTimestampParser : public TimestampParser {
 public:
  explicit StrptimeTimestampParser(std::string format) : format_(std::move(format)) {}

  bool operator()(const char* s, size_t length, TimeUnit::type out_unit,
                  int64_t* out) const override {
    return ParseTimestampStrptime(s, length, format_.c_str(),
                                  /*ignore_time_in_day=*/false,
                                  /*allow_trailing_chars=*/false, out_unit, out);
  }

 private:
  std::string format_;
};

class ISO8601Parser : public TimestampParser {
 public:
  ISO8601Parser() {}

  bool operator()(const char* s, size_t length, TimeUnit::type out_unit,
                  int64_t* out) const override {
    return ParseTimestampISO8601(s, length, out_unit, out);
  }
};

}  // namespace internal

std::shared_ptr<TimestampParser> TimestampParser::MakeStrptime(std::string format) {
  return std::make_shared<internal::StrptimeTimestampParser>(std::move(format));
}

std::shared_ptr<TimestampParser> TimestampParser::MakeISO8601() {
  return std::make_shared<internal::ISO8601Parser>();
}

}  // namespace arrow
<|endoftext|>


<commit_before>#include "classify/perceptron.h"

namespace meta {
namespace classify {

perceptron::perceptron( double alpha, double gamma, double bias,
                        size_t max_iter )
        : alpha_{ alpha }, gamma_{ gamma }, bias_{ bias },
          max_iter_{ max_iter } { }

double perceptron::get_weight( const class_label & label,
                               const term_id & term ) const {
    auto weight_it = weights_.find( label );
    if( weight_it == weights_.end() )
        return 0;
    auto term_it = weight_it->second.find( term );
    if( term_it == weight_it->second.end() )
        return 0;
    return term_it->second;
}

void perceptron::zero_weights( const std::vector<index::Document> & docs ) {
    for( const auto & d : docs )
        weights_[ d.getCategory() ] = {};
}

void perceptron::train( const std::vector<index::Document> & docs ) {
    zero_weights( docs );
    for( size_t iter = 0; iter < max_iter_; ++iter ) {
        common::show_progress( iter, max_iter_, 10, "[perceptron]: training " );
        double error_count = 0;
        for( const index::Document & doc : docs ) {
            class_label guess = classify( doc );
            class_label actual = doc.getCategory();
            if( guess != actual ) {
                error_count += 1;
                for( const auto & count : doc.getFrequencies() ) {
                    weights_[ guess ][ count.first ] -= alpha_ * count.second;
                    weights_[ actual ][ count.first ] += alpha_ * count.second;
                }
            }
        }
        if( error_count / docs.size() < gamma_ )
            break;
    }
    common::end_progress("[perceptron]: training ");
}

class_label perceptron::classify( const index::Document & doc ) {
    class_label best_label = weights_.begin()->first;
    double best_dot = 0;
    for( const auto & w : weights_ ) {
        double dot = bias_;
        for( const auto & count : doc.getFrequencies() ) {
            dot += count.second * get_weight( w.first, count.first );
        }
        if( dot > best_dot ) {
            dot = best_dot;
            best_label = w.first;
        }
    }
    return best_label;
}

void perceptron::reset() {
    weights_ = {};
}

}
}
<commit_msg>Fix silly bug in perceptron.<commit_after>#include "classify/perceptron.h"

namespace meta {
namespace classify {

perceptron::perceptron( double alpha, double gamma, double bias,
                        size_t max_iter )
        : alpha_{ alpha }, gamma_{ gamma }, bias_{ bias },
          max_iter_{ max_iter } { }

double perceptron::get_weight( const class_label & label,
                               const term_id & term ) const {
    auto weight_it = weights_.find( label );
    if( weight_it == weights_.end() )
        return 0;
    auto term_it = weight_it->second.find( term );
    if( term_it == weight_it->second.end() )
        return 0;
    return term_it->second;
}

void perceptron::zero_weights( const std::vector<index::Document> & docs ) {
    for( const auto & d : docs )
        weights_[ d.getCategory() ] = {};
}

void perceptron::train( const std::vector<index::Document> & docs ) {
    zero_weights( docs );
    for( size_t iter = 0; iter < max_iter_; ++iter ) {
        common::show_progress( iter, max_iter_, 10, "[perceptron]: training " );
        double error_count = 0;
        for( const index::Document & doc : docs ) {
            class_label guess = classify( doc );
            class_label actual = doc.getCategory();
            if( guess != actual ) {
                error_count += 1;
                for( const auto & count : doc.getFrequencies() ) {
                    weights_[ guess ][ count.first ] -= alpha_ * count.second;
                    weights_[ actual ][ count.first ] += alpha_ * count.second;
                }
            }
        }
        if( error_count / docs.size() < gamma_ )
            break;
    }
    common::end_progress("[perceptron]: training ");
}

class_label perceptron::classify( const index::Document & doc ) {
    class_label best_label = weights_.begin()->first;
    double best_dot = 0;
    for( const auto & w : weights_ ) {
        double dot = bias_;
        for( const auto & count : doc.getFrequencies() ) {
            dot += count.second * get_weight( w.first, count.first );
        }
        if( dot > best_dot ) {
            best_dot = dot;
            best_label = w.first;
        }
    }
    return best_label;
}

void perceptron::reset() {
    weights_ = {};
}

}
}
<|endoftext|>