Codebase list mozc / upstream/1.2.855.102+main unix / ibus / config_util.cc
upstream/1.2.855.102+main

Tree @upstream/1.2.855.102+main (Download .tar.gz)

config_util.cc @upstream/1.2.855.102+mainraw · history · blame

// Copyright 2010-2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. 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.

#include "unix/ibus/config_util.h"

#include <map>

#include "base/base.h"
#include "base/singleton.h"
#include "base/protobuf/descriptor.h"

namespace mozc {
namespace ibus {
#if IBUS_CHECK_VERSION(1, 3, 99)
// IBus-1.4 uses Glib's GVariant for configration.
bool ConfigUtil::GetString(GVariant *value, const gchar **out_string) {
  if (g_variant_classify(value) != G_VARIANT_CLASS_STRING) {
    return false;
  }
  *out_string = g_variant_get_string(value, NULL);
  return true;
}

bool ConfigUtil::GetInteger(GVariant *value, gint *out_integer) {
  if (g_variant_classify(value) != G_VARIANT_CLASS_INT32) {
    return false;
  }
  *out_integer = g_variant_get_int32(value);
  return true;
}

bool ConfigUtil::GetBoolean(GVariant *value, gboolean *out_boolean) {
  if (g_variant_classify(value) != G_VARIANT_CLASS_BOOLEAN) {
    return false;
  }
  *out_boolean = g_variant_get_boolean(value);
  return true;
}
#else
// IBus-1.2 and 1.3 use GValue for configration.
bool ConfigUtil::GetString(GValue *value, const gchar **out_string) {
  if (!G_VALUE_HOLDS_STRING(value)) {
    return false;
  }
  *out_string = g_value_get_string(value);
  return true;
}

bool ConfigUtil::GetInteger(GValue *value, gint *out_integer) {
  if (!G_VALUE_HOLDS_INT(value)) {
    return false;
  }
  *out_integer = g_value_get_int(value);
  return true;
}

bool ConfigUtil::GetBoolean(GValue *value, gboolean *out_boolean) {
  if (!G_VALUE_HOLDS_BOOLEAN(value)) {
    return false;
  }
  *out_boolean = g_value_get_boolean(value);
  return true;
}
#endif

void ConfigUtil::SetFieldForName(const gchar *name,
#if IBUS_CHECK_VERSION(1, 3, 99)
                                 GVariant *value,
#else
                                 GValue *value,
#endif
                                 protobuf::Message *result) {
  if (!name || !value) {
    LOG(ERROR) << "name or value is not specified";
    return;
  }
  DCHECK(result);

  const google::protobuf::Descriptor *descriptor = result->GetDescriptor();
  const google::protobuf::Reflection *reflection = result->GetReflection();
  const google::protobuf::FieldDescriptor *field_to_update =
      descriptor->FindFieldByName(name);

  if (!field_to_update) {
    LOG(ERROR) << "Unknown field name: " << name;
    return;
  }

  // Set |value| to |result|.
  switch (field_to_update->cpp_type()) {
    case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
      // |value| should be STRING.
      const gchar *string_value = NULL;
      if (!GetString(value, &string_value)) {
        LOG(ERROR) << "Bad value type for " << name;
        return;
      }
      DCHECK(string_value);
      const google::protobuf::EnumValueDescriptor *enum_value =
          descriptor->FindEnumValueByName(string_value);
      if (!enum_value) {
        LOG(ERROR) << "Bad value for " << name << ": " << string_value;
        return;
      }
      reflection->SetEnum(result, field_to_update, enum_value);
      VLOG(2) << "setting field: " << name << " = " << string_value;
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
      // unsigned int is not supported as chrome's preference type and int is
      // used as an alternative type, so |value| should be INT.
      gint int_value = -1;
      if (!GetInteger(value, &int_value)) {
        LOG(ERROR) << "Bad value type for " << name;
        return;
      }
      reflection->SetUInt32(result, field_to_update, int_value);
      VLOG(2) << "setting field: " << name << " = " << int_value;
      break;
    }
    case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
      // |value| should be BOOLEAN.
      gboolean boolean_value = FALSE;
      if (!GetBoolean(value, &boolean_value)) {
        LOG(ERROR) << "Bad value type for " << name;
        return;
      }
      reflection->SetBool(result, field_to_update, boolean_value);
      VLOG(2) << "setting field: " << name << " = "
              << (boolean_value ? "true" : "false");
      break;
    }
    default: {
      // TODO(yusukes): Support other types.
      LOG(ERROR) << "Unknown or unsupported type: " << name << ": "
                 << field_to_update->cpp_type();
      return;
    }
  }
}

#ifdef OS_CHROMEOS

void ConfigUtil::InitConfig(IBusConfig* config,
                            const char *section_name,
                            const map<string, const char*> &name_to_field) {
#if IBUS_CHECK_VERSION(1, 3, 99)
  for (map<string, const char*>::const_iterator i = name_to_field.begin();
       i != name_to_field.end(); ++i) {
    const gchar *name = i->first.c_str();
    GVariant *value = ibus_config_get_value(config, section_name, name);
    if (!value) {
      LOG(WARNING) << "ibus_config_get_value failed for " << name;
      continue;
    }
    // Invoke the signal handler for the "value-changed" message.
    g_signal_emit_by_name(config, "value-changed", section_name, name,
                          value);
    g_variant_unref(value);
  }
#else
#error ibus version 1.3.99 or higher required
#endif
}

#endif  // OS_CHROMEOS

}  // namespace ibus
}  // namespace mozc