<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "webkit/glue/plugins/test/plugin_client.h"
#include "webkit/glue/plugins/test/plugin_arguments_test.h"
#include "webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h"
#include "webkit/glue/plugins/test/plugin_get_javascript_url_test.h"
#include "webkit/glue/plugins/test/plugin_geturl_test.h"
#include "webkit/glue/plugins/test/plugin_javascript_open_popup.h"
#include "webkit/glue/plugins/test/plugin_new_fails_test.h"
#include "webkit/glue/plugins/test/plugin_private_test.h"
#include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h"
#include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h"
#include "webkit/glue/plugins/test/plugin_window_size_test.h"
#include "webkit/glue/plugins/test/plugin_windowless_test.h"
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npruntime.h"

namespace NPAPIClient {

NPNetscapeFuncs* PluginClient::host_functions_;

NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) {
  if (pFuncs == NULL)
    return NPERR_INVALID_FUNCTABLE_ERROR;

  if (pFuncs->size < sizeof(NPPluginFuncs))
    return NPERR_INVALID_FUNCTABLE_ERROR;

  pFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
  pFuncs->newp          = NPP_New;
  pFuncs->destroy       = NPP_Destroy;
  pFuncs->setwindow     = NPP_SetWindow;
  pFuncs->newstream     = NPP_NewStream;
  pFuncs->destroystream = NPP_DestroyStream;
  pFuncs->asfile        = NPP_StreamAsFile;
  pFuncs->writeready    = NPP_WriteReady;
  pFuncs->write         = NPP_Write;
  pFuncs->print         = NPP_Print;
  pFuncs->event         = NPP_HandleEvent;
  pFuncs->urlnotify     = NPP_URLNotify;
  pFuncs->getvalue      = NPP_GetValue;
  pFuncs->setvalue      = NPP_SetValue;
  pFuncs->javaClass     = static_cast<JRIGlobalRef>(NPP_GetJavaClass);

  return NPERR_NO_ERROR;
}

NPError PluginClient::Initialize(NPNetscapeFuncs* pFuncs) {
  if (pFuncs == NULL) {
    return NPERR_INVALID_FUNCTABLE_ERROR;
  }

  if (static_cast<unsigned char>((pFuncs->version >> 8) & 0xff) >
      NP_VERSION_MAJOR) {
    return NPERR_INCOMPATIBLE_VERSION_ERROR;
  }

  host_functions_ = pFuncs;

  return NPERR_NO_ERROR;
}

NPError PluginClient::Shutdown() {
  return NPERR_NO_ERROR;
}

} // namespace NPAPIClient

extern "C" {
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
                int16 argc, char* argn[], char* argv[], NPSavedData* saved) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // We look at the test name requested via the plugin arguments.  We match
  // that against a given test and try to instantiate it.

  // lookup the name parameter
  std::string test_name;
  for (int name_index = 0; name_index < argc; name_index++)
    if (base::strcasecmp(argn[name_index], "name") == 0) {
      test_name = argv[name_index];
      break;
    }

  if (test_name.empty())
    return NPERR_GENERIC_ERROR;  // no name found

  NPError ret = NPERR_GENERIC_ERROR;
  bool windowless_plugin = false;

  NPAPIClient::PluginTest *new_test = NULL;
  if (test_name == "arguments") {
    new_test = new NPAPIClient::PluginArgumentsTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "geturl") {
    new_test = new NPAPIClient::PluginGetURLTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_proxy") {
    new_test = new NPAPIClient::NPObjectProxyTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_windowless_test.*.
  } else if (test_name == "execute_script_delete_in_paint" ||
             test_name == "execute_script_delete_in_mouse_move" ||
             test_name == "delete_frame_test") {
    new_test = new NPAPIClient::WindowlessPluginTest(instance,
      NPAPIClient::PluginClient::HostFunctions(), test_name);
    windowless_plugin = true;
#endif
  } else if (test_name == "getjavascripturl") {
    new_test = new NPAPIClient::ExecuteGetJavascriptUrlTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_window_size_test.*.
  } else if (test_name == "checkwindowrect") {
    new_test = new NPAPIClient::PluginWindowSizeTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#endif
  } else if (test_name == "self_delete_plugin_stream") {
    new_test = new NPAPIClient::DeletePluginInStreamTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_npobject_lifetime_test.*.
  } else if (test_name == "npobject_lifetime_test") {
    new_test = new NPAPIClient::NPObjectLifetimeTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_lifetime_test_second_instance") {
    new_test = new NPAPIClient::NPObjectLifetimeTestInstance2(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "new_fails") {
    new_test = new NPAPIClient::NewFailsTest(instance,
        NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_delete_plugin_in_evaluate") {
    new_test = new NPAPIClient::NPObjectDeletePluginInNPN_Evaluate(instance,
      NPAPIClient::PluginClient::HostFunctions());
#endif
  } else if (test_name ==
             "plugin_javascript_open_popup_with_plugin") {
    new_test = new NPAPIClient::ExecuteJavascriptOpenPopupWithPluginTest(
        instance, NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "plugin_popup_with_plugin_target") {
    new_test = new NPAPIClient::ExecuteJavascriptPopupWindowTargetPluginTest(
        instance, NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "private") {
    new_test = new NPAPIClient::PrivateTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else {
    // If we don't have a test case for this, create a
    // generic one which basically never fails.
    LOG(WARNING) << "Unknown test name '" << test_name
                 << "'; using default test.";
    new_test = new NPAPIClient::PluginTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  }

  if (new_test) {
    ret = new_test->New(mode, argc, (const char**)argn,
                       (const char**)argv, saved);
    if ((ret == NPERR_NO_ERROR) && windowless_plugin) {
      NPAPIClient::PluginClient::HostFunctions()->setvalue(
            instance, NPPVpluginWindowBool, NULL);
    }
  }

  return ret;
}

NPError NPP_Destroy(NPP instance, NPSavedData** save) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;
  delete plugin;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  if (pNPWindow->window == NULL) {
    return NPERR_NO_ERROR;
  }

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->SetWindow(pNPWindow);
}

NPError NPP_NewStream(NPP instance, NPMIMEType type,
                      NPStream* stream, NPBool seekable, uint16* stype) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->NewStream(type, stream, seekable, stype);
}

int32 NPP_WriteReady(NPP instance, NPStream *stream) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->WriteReady(stream);
}

int32 NPP_Write(NPP instance, NPStream *stream, int32 offset,
                 int32 len, void *buffer) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->Write(stream, offset, len, buffer);
}

NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->DestroyStream(stream, reason);
}

void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
  if (instance == NULL)
    return;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->StreamAsFile(stream, fname);
}

void NPP_Print(NPP instance, NPPrint* printInfo) {
  if (instance == NULL)
    return;

  // XXXMB - do work here.
}

void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
                   void* notifyData) {
  if (instance == NULL)
    return;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->URLNotify(url, reason, notifyData);
}

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

int16 NPP_HandleEvent(NPP instance, void* event) {
  if (instance == NULL)
    return 0;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->HandleEvent(event);
}

void* NPP_GetJavaClass(void) {
  // XXXMB - do work here.
  return NULL;
}
} // extern "C"
<commit_msg>Fix build break due to incorrect merge, TBR=awalker<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/string_util.h"
#include "webkit/glue/plugins/test/plugin_client.h"
#include "webkit/glue/plugins/test/plugin_arguments_test.h"
#include "webkit/glue/plugins/test/plugin_delete_plugin_in_stream_test.h"
#include "webkit/glue/plugins/test/plugin_get_javascript_url_test.h"
#include "webkit/glue/plugins/test/plugin_geturl_test.h"
#include "webkit/glue/plugins/test/plugin_javascript_open_popup.h"
#include "webkit/glue/plugins/test/plugin_new_fails_test.h"
#include "webkit/glue/plugins/test/plugin_private_test.h"
#include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h"
#include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h"
#include "webkit/glue/plugins/test/plugin_window_size_test.h"
#include "webkit/glue/plugins/test/plugin_windowless_test.h"
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npruntime.h"

namespace NPAPIClient {

NPNetscapeFuncs* PluginClient::host_functions_;

NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) {
  if (pFuncs == NULL)
    return NPERR_INVALID_FUNCTABLE_ERROR;

  if (pFuncs->size < sizeof(NPPluginFuncs))
    return NPERR_INVALID_FUNCTABLE_ERROR;

  pFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
  pFuncs->newp          = NPP_New;
  pFuncs->destroy       = NPP_Destroy;
  pFuncs->setwindow     = NPP_SetWindow;
  pFuncs->newstream     = NPP_NewStream;
  pFuncs->destroystream = NPP_DestroyStream;
  pFuncs->asfile        = NPP_StreamAsFile;
  pFuncs->writeready    = NPP_WriteReady;
  pFuncs->write         = NPP_Write;
  pFuncs->print         = NPP_Print;
  pFuncs->event         = NPP_HandleEvent;
  pFuncs->urlnotify     = NPP_URLNotify;
  pFuncs->getvalue      = NPP_GetValue;
  pFuncs->setvalue      = NPP_SetValue;
  pFuncs->javaClass     = reinterpret_cast<JRIGlobalRef>(NPP_GetJavaClass);

  return NPERR_NO_ERROR;
}

NPError PluginClient::Initialize(NPNetscapeFuncs* pFuncs) {
  if (pFuncs == NULL) {
    return NPERR_INVALID_FUNCTABLE_ERROR;
  }

  if (static_cast<unsigned char>((pFuncs->version >> 8) & 0xff) >
      NP_VERSION_MAJOR) {
    return NPERR_INCOMPATIBLE_VERSION_ERROR;
  }

  host_functions_ = pFuncs;

  return NPERR_NO_ERROR;
}

NPError PluginClient::Shutdown() {
  return NPERR_NO_ERROR;
}

} // namespace NPAPIClient

extern "C" {
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
                int16 argc, char* argn[], char* argv[], NPSavedData* saved) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // We look at the test name requested via the plugin arguments.  We match
  // that against a given test and try to instantiate it.

  // lookup the name parameter
  std::string test_name;
  for (int name_index = 0; name_index < argc; name_index++)
    if (base::strcasecmp(argn[name_index], "name") == 0) {
      test_name = argv[name_index];
      break;
    }

  if (test_name.empty())
    return NPERR_GENERIC_ERROR;  // no name found

  NPError ret = NPERR_GENERIC_ERROR;
  bool windowless_plugin = false;

  NPAPIClient::PluginTest *new_test = NULL;
  if (test_name == "arguments") {
    new_test = new NPAPIClient::PluginArgumentsTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "geturl") {
    new_test = new NPAPIClient::PluginGetURLTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_proxy") {
    new_test = new NPAPIClient::NPObjectProxyTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_windowless_test.*.
  } else if (test_name == "execute_script_delete_in_paint" ||
             test_name == "execute_script_delete_in_mouse_move" ||
             test_name == "delete_frame_test") {
    new_test = new NPAPIClient::WindowlessPluginTest(instance,
      NPAPIClient::PluginClient::HostFunctions(), test_name);
    windowless_plugin = true;
#endif
  } else if (test_name == "getjavascripturl") {
    new_test = new NPAPIClient::ExecuteGetJavascriptUrlTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_window_size_test.*.
  } else if (test_name == "checkwindowrect") {
    new_test = new NPAPIClient::PluginWindowSizeTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#endif
  } else if (test_name == "self_delete_plugin_stream") {
    new_test = new NPAPIClient::DeletePluginInStreamTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
#if defined(OS_WIN)
  // TODO(port): plugin_npobject_lifetime_test.*.
  } else if (test_name == "npobject_lifetime_test") {
    new_test = new NPAPIClient::NPObjectLifetimeTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_lifetime_test_second_instance") {
    new_test = new NPAPIClient::NPObjectLifetimeTestInstance2(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "new_fails") {
    new_test = new NPAPIClient::NewFailsTest(instance,
        NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "npobject_delete_plugin_in_evaluate") {
    new_test = new NPAPIClient::NPObjectDeletePluginInNPN_Evaluate(instance,
      NPAPIClient::PluginClient::HostFunctions());
#endif
  } else if (test_name ==
             "plugin_javascript_open_popup_with_plugin") {
    new_test = new NPAPIClient::ExecuteJavascriptOpenPopupWithPluginTest(
        instance, NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "plugin_popup_with_plugin_target") {
    new_test = new NPAPIClient::ExecuteJavascriptPopupWindowTargetPluginTest(
        instance, NPAPIClient::PluginClient::HostFunctions());
  } else if (test_name == "private") {
    new_test = new NPAPIClient::PrivateTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  } else {
    // If we don't have a test case for this, create a
    // generic one which basically never fails.
    LOG(WARNING) << "Unknown test name '" << test_name
                 << "'; using default test.";
    new_test = new NPAPIClient::PluginTest(instance,
      NPAPIClient::PluginClient::HostFunctions());
  }

  if (new_test) {
    ret = new_test->New(mode, argc, (const char**)argn,
                       (const char**)argv, saved);
    if ((ret == NPERR_NO_ERROR) && windowless_plugin) {
      NPAPIClient::PluginClient::HostFunctions()->setvalue(
            instance, NPPVpluginWindowBool, NULL);
    }
  }

  return ret;
}

NPError NPP_Destroy(NPP instance, NPSavedData** save) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;
  delete plugin;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  if (pNPWindow->window == NULL) {
    return NPERR_NO_ERROR;
  }

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->SetWindow(pNPWindow);
}

NPError NPP_NewStream(NPP instance, NPMIMEType type,
                      NPStream* stream, NPBool seekable, uint16* stype) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->NewStream(type, stream, seekable, stype);
}

int32 NPP_WriteReady(NPP instance, NPStream *stream) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->WriteReady(stream);
}

int32 NPP_Write(NPP instance, NPStream *stream, int32 offset,
                 int32 len, void *buffer) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->Write(stream, offset, len, buffer);
}

NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->DestroyStream(stream, reason);
}

void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
  if (instance == NULL)
    return;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->StreamAsFile(stream, fname);
}

void NPP_Print(NPP instance, NPPrint* printInfo) {
  if (instance == NULL)
    return;

  // XXXMB - do work here.
}

void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
                   void* notifyData) {
  if (instance == NULL)
    return;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->URLNotify(url, reason, notifyData);
}

NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
  if (instance == NULL)
    return NPERR_INVALID_INSTANCE_ERROR;

  // XXXMB - do work here.
  return NPERR_GENERIC_ERROR;
}

int16 NPP_HandleEvent(NPP instance, void* event) {
  if (instance == NULL)
    return 0;

  NPAPIClient::PluginTest *plugin =
    (NPAPIClient::PluginTest*)instance->pdata;

  return plugin->HandleEvent(event);
}

void* NPP_GetJavaClass(void) {
  // XXXMB - do work here.
  return NULL;
}
} // extern "C"
<|endoftext|>


<commit_before>#include <ir/index_manager/index/Indexer.h>
#include <ir/index_manager/index/FieldIndexer.h>
#include <ir/index_manager/index/TermReader.h>
#include <ir/index_manager/index/TermPositions.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>

using namespace std;

namespace bfs = boost::filesystem;

NS_IZENELIB_IR_BEGIN

namespace indexmanager
{

FieldIndexer::FieldIndexer(const char* field, MemCache* pCache, Indexer* pIndexer)
        :field_(field),pMemCache_(pCache),pIndexer_(pIndexer),vocFilePointer_(0),alloc_(0),sorter_(0),termCount_(0)
{
    skipInterval_ = pIndexer_->getSkipInterval();
    maxSkipLevel_ = pIndexer_->getMaxSkipLevel();
    if (! pIndexer_->isRealTime())
    {
        std::string sorterName = field_+".tmp";
        bfs::path path(bfs::path(pIndexer->pConfigurationManager_->indexStrategy_.indexLocation_) /bfs::path(sorterName));
        sorterFullPath_= path.string();
        sorter_=new izenelib::am::IzeneSort<uint32_t, uint8_t, true>(sorterFullPath_.c_str(), 120000000);
    }
    else
        alloc_ = new boost::scoped_alloc(recycle_);
}

FieldIndexer::~FieldIndexer()
{
    /*
        InMemoryPostingMap::iterator iter = postingMap_.begin()
        for(; iter !=postingMap_.end(); ++iter)
        {
            delete iter->second;
        }
    */
    if (alloc_) delete alloc_;
    pMemCache_ = NULL;
    if (sorter_) delete sorter_;
}

void convert(char* data, uint32_t termId, uint32_t docId, uint32_t offset)
{
    char* pData = data;
    memcpy(pData, &(termId), sizeof(termId));
    pData += sizeof(termId);
    memcpy(pData, &(docId), sizeof(docId));
    pData += sizeof(docId);
    memcpy(pData, &(offset), sizeof(offset));
    pData += sizeof(offset);
}

void FieldIndexer::addField(docid_t docid, boost::shared_ptr<LAInput> laInput)
{
    if (pIndexer_->isRealTime())
    {
        InMemoryPosting* curPosting;
        for (LAInput::iterator iter = laInput->begin(); iter != laInput->end(); ++iter)
        {
            InMemoryPostingMap::iterator postingIter = postingMap_.find(iter->termId_);
            if (postingIter == postingMap_.end())
            {
                //curPosting = new InMemoryPosting(pMemCache_, skipInterval_, maxSkipLevel_);
                curPosting = BOOST_NEW(*alloc_, InMemoryPosting)(pMemCache_, skipInterval_, maxSkipLevel_);
                postingMap_[iter->termId_] = curPosting;
            }
            else
                curPosting = postingIter->second;
            curPosting->add(docid, iter->offset_);
        }
    }
    else
    {
        if (!sorter_)
            sorter_=new izenelib::am::IzeneSort<uint32_t, uint8_t, true>(sorterFullPath_.c_str(), 120000000);

        char data[12];
        for (LAInput::iterator iter = laInput->begin(); iter != laInput->end(); ++iter)
        {
            convert(data,iter->termId_,docid,iter->offset_);
            sorter_->add_data(12, data);
        }
    }
}

void FieldIndexer::addField(docid_t docid, boost::shared_ptr<ForwardIndex> forwardindex)
{
    InMemoryPosting* curPosting;

    for (ForwardIndex::iterator iter = forwardindex->begin(); iter != forwardindex->end(); ++iter)
    {
        InMemoryPostingMap::iterator postingIter = postingMap_.find(iter->first);
        if (postingIter == postingMap_.end())
        {
            curPosting = BOOST_NEW(*alloc_, InMemoryPosting)(pMemCache_, skipInterval_, maxSkipLevel_);
            postingMap_[iter->first] = curPosting;
        }
        else
            curPosting = postingIter->second;

        ForwardIndexOffset::iterator	endit = iter->second->end();
        for (ForwardIndexOffset::iterator it = iter->second->begin(); it != endit; ++it)
            curPosting->add(docid, *it);
    }
}

void FieldIndexer::reset()
{
    InMemoryPosting* pPosting;
    for (InMemoryPostingMap::iterator iter = postingMap_.begin(); iter !=postingMap_.end(); ++iter)
    {
        pPosting = iter->second;
        if (!pPosting->hasNoChunk())
        {
            pPosting->reset();		///clear posting data
        }
    }
    postingMap_.clear();
    termCount_ = 0;
}

void writeTermInfo(IndexOutput* pVocWriter, termid_t tid, const TermInfo& termInfo)
{
    pVocWriter->writeInt(tid);					///write term id
    pVocWriter->writeInt(termInfo.docFreq_);		///write df
    pVocWriter->writeInt(termInfo.ctf_);			///write ctf
    pVocWriter->writeInt(termInfo.lastDocID_);		///write last doc id
    pVocWriter->writeInt(termInfo.skipLevel_);		///write skip level
    pVocWriter->writeLong(termInfo.skipPointer_);	///write skip list offset offset
    pVocWriter->writeLong(termInfo.docPointer_);	///write document posting offset
    pVocWriter->writeInt(termInfo.docPostingLen_);	///write document posting length (without skiplist)
    pVocWriter->writeLong(termInfo.positionPointer_);	///write position posting offset
    pVocWriter->writeInt(termInfo.positionPostingLen_);///write position posting length
}

fileoffset_t FieldIndexer::write(OutputDescriptor* pWriterDesc)
{
    vocFilePointer_ = pWriterDesc->getVocOutput()->getFilePointer();

    IndexOutput* pVocWriter = pWriterDesc->getVocOutput();

    termid_t tid;
    InMemoryPosting* pPosting;
    fileoffset_t vocOffset = pVocWriter->getFilePointer();
    TermInfo termInfo;

    if (pIndexer_->isRealTime())
    {
        izenelib::util::ScopedWriteLock<izenelib::util::ReadWriteLock> lock(rwLock_);
        for (InMemoryPostingMap::iterator iter = postingMap_.begin(); iter !=postingMap_.end(); ++iter)
        {
            pPosting = iter->second;
            pPosting->setDirty(true);
            if (!pPosting->hasNoChunk())
            {
                tid = iter->first;
                pPosting->write(pWriterDesc, termInfo);		///write posting data
                writeTermInfo(pVocWriter,tid,termInfo);
                pPosting->reset();								///clear posting data
                termInfo.reset();
                termCount_++;
            }
            //delete pPosting;
            //pPosting = NULL;
        }

        postingMap_.clear();

        delete alloc_;
        alloc_ = new boost::scoped_alloc(recycle_);
    }
    else
    {
        sorter_->sort();
        FILE* f = fopen(sorterFullPath_.c_str(),"r");
        fseek(f, 0, SEEK_SET);
        uint64_t count;
        fread(&count, sizeof(uint64_t), 1, f);

        pPosting = new InMemoryPosting(pMemCache_, skipInterval_, maxSkipLevel_);
        termid_t lastTerm = BAD_DOCID;
        try
        {
        for (uint64_t i = 0; i < count; ++i)
        {
            uint8_t len;
            fread(&len, sizeof(uint8_t), 1, f);
            uint32_t docId,offset;
            fread(&tid, sizeof(uint32_t), 1, f);
            fread(&docId, sizeof(uint32_t), 1, f);
            fread(&offset, sizeof(uint32_t), 1, f);

            if(tid != lastTerm && lastTerm != BAD_DOCID)
            {
                if (!pPosting->hasNoChunk())
                {
                    pPosting->write(pWriterDesc, termInfo); 	///write posting data
                    writeTermInfo(pVocWriter, lastTerm, termInfo);
                    pPosting->reset();								///clear posting data
                    pMemCache_->flushMem();
                    termInfo.reset();
                    termCount_++;
                }
            }
            pPosting->add(docId, offset);
            lastTerm = tid;
        }
        }catch(std::exception& e)
        {
        cout<<e.what()<<endl;
        }

        if (!pPosting->hasNoChunk())
        {
            pPosting->write(pWriterDesc, termInfo);	///write posting data
            writeTermInfo(pVocWriter, lastTerm, termInfo);
            pPosting->reset(); 							///clear posting data
            pMemCache_->flushMem();
            termInfo.reset();
            termCount_++;
        }

        fclose(f);
        sorter_->clear_files();
        delete sorter_;
        sorter_ = NULL;
        delete pPosting;
    }

    fileoffset_t vocDescOffset = pVocWriter->getFilePointer();
    int64_t vocLength = vocDescOffset - vocOffset;
    ///begin write vocabulary descriptor
    pVocWriter->writeLong(vocLength);	///<VocLength(Int64)>
    pVocWriter->writeLong(termCount_);	///<TermCount(Int64)>
    ///end write vocabulary descriptor

    return vocDescOffset;
}

TermReader* FieldIndexer::termReader()
{
    izenelib::util::ScopedReadLock<izenelib::util::ReadWriteLock> lock(rwLock_);
    return new InMemoryTermReader(getField(),this);
}

}

NS_IZENELIB_IR_END

<commit_msg>make memory buffer size for izenesoft to be aligned with record length<commit_after>#include <ir/index_manager/index/Indexer.h>
#include <ir/index_manager/index/FieldIndexer.h>
#include <ir/index_manager/index/TermReader.h>
#include <ir/index_manager/index/TermPositions.h>

#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>

using namespace std;

namespace bfs = boost::filesystem;

NS_IZENELIB_IR_BEGIN

namespace indexmanager
{

FieldIndexer::FieldIndexer(const char* field, MemCache* pCache, Indexer* pIndexer)
        :field_(field),pMemCache_(pCache),pIndexer_(pIndexer),vocFilePointer_(0),alloc_(0),sorter_(0),termCount_(0)
{
    skipInterval_ = pIndexer_->getSkipInterval();
    maxSkipLevel_ = pIndexer_->getMaxSkipLevel();
    if (! pIndexer_->isRealTime())
    {
        std::string sorterName = field_+".tmp";
        bfs::path path(bfs::path(pIndexer->pConfigurationManager_->indexStrategy_.indexLocation_) /bfs::path(sorterName));
        sorterFullPath_= path.string();
        sorter_=new izenelib::am::IzeneSort<uint32_t, uint8_t, true>(sorterFullPath_.c_str(), 130000000);
    }
    else
        alloc_ = new boost::scoped_alloc(recycle_);
}

FieldIndexer::~FieldIndexer()
{
    /*
        InMemoryPostingMap::iterator iter = postingMap_.begin()
        for(; iter !=postingMap_.end(); ++iter)
        {
            delete iter->second;
        }
    */
    if (alloc_) delete alloc_;
    pMemCache_ = NULL;
    if (sorter_) delete sorter_;
}

void convert(char* data, uint32_t termId, uint32_t docId, uint32_t offset)
{
    char* pData = data;
    memcpy(pData, &(termId), sizeof(termId));
    pData += sizeof(termId);
    memcpy(pData, &(docId), sizeof(docId));
    pData += sizeof(docId);
    memcpy(pData, &(offset), sizeof(offset));
    pData += sizeof(offset);
}

void FieldIndexer::addField(docid_t docid, boost::shared_ptr<LAInput> laInput)
{
    if (pIndexer_->isRealTime())
    {
        InMemoryPosting* curPosting;
        for (LAInput::iterator iter = laInput->begin(); iter != laInput->end(); ++iter)
        {
            InMemoryPostingMap::iterator postingIter = postingMap_.find(iter->termId_);
            if (postingIter == postingMap_.end())
            {
                //curPosting = new InMemoryPosting(pMemCache_, skipInterval_, maxSkipLevel_);
                curPosting = BOOST_NEW(*alloc_, InMemoryPosting)(pMemCache_, skipInterval_, maxSkipLevel_);
                postingMap_[iter->termId_] = curPosting;
            }
            else
                curPosting = postingIter->second;
            curPosting->add(docid, iter->offset_);
        }
    }
    else
    {
        if (!sorter_)
            sorter_=new izenelib::am::IzeneSort<uint32_t, uint8_t, true>(sorterFullPath_.c_str(), 130000000);

        char data[12];
        for (LAInput::iterator iter = laInput->begin(); iter != laInput->end(); ++iter)
        {
            convert(data,iter->termId_,docid,iter->offset_);
            sorter_->add_data(12, data);
        }
    }
}

void FieldIndexer::addField(docid_t docid, boost::shared_ptr<ForwardIndex> forwardindex)
{
    InMemoryPosting* curPosting;

    for (ForwardIndex::iterator iter = forwardindex->begin(); iter != forwardindex->end(); ++iter)
    {
        InMemoryPostingMap::iterator postingIter = postingMap_.find(iter->first);
        if (postingIter == postingMap_.end())
        {
            curPosting = BOOST_NEW(*alloc_, InMemoryPosting)(pMemCache_, skipInterval_, maxSkipLevel_);
            postingMap_[iter->first] = curPosting;
        }
        else
            curPosting = postingIter->second;

        ForwardIndexOffset::iterator	endit = iter->second->end();
        for (ForwardIndexOffset::iterator it = iter->second->begin(); it != endit; ++it)
            curPosting->add(docid, *it);
    }
}

void FieldIndexer::reset()
{
    InMemoryPosting* pPosting;
    for (InMemoryPostingMap::iterator iter = postingMap_.begin(); iter !=postingMap_.end(); ++iter)
    {
        pPosting = iter->second;
        if (!pPosting->hasNoChunk())
        {
            pPosting->reset();		///clear posting data
        }
    }
    postingMap_.clear();
    termCount_ = 0;
}

void writeTermInfo(IndexOutput* pVocWriter, termid_t tid, const TermInfo& termInfo)
{
    pVocWriter->writeInt(tid);					///write term id
    pVocWriter->writeInt(termInfo.docFreq_);		///write df
    pVocWriter->writeInt(termInfo.ctf_);			///write ctf
    pVocWriter->writeInt(termInfo.lastDocID_);		///write last doc id
    pVocWriter->writeInt(termInfo.skipLevel_);		///write skip level
    pVocWriter->writeLong(termInfo.skipPointer_);	///write skip list offset offset
    pVocWriter->writeLong(termInfo.docPointer_);	///write document posting offset
    pVocWriter->writeInt(termInfo.docPostingLen_);	///write document posting length (without skiplist)
    pVocWriter->writeLong(termInfo.positionPointer_);	///write position posting offset
    pVocWriter->writeInt(termInfo.positionPostingLen_);///write position posting length
}

fileoffset_t FieldIndexer::write(OutputDescriptor* pWriterDesc)
{
    vocFilePointer_ = pWriterDesc->getVocOutput()->getFilePointer();

    IndexOutput* pVocWriter = pWriterDesc->getVocOutput();

    termid_t tid;
    InMemoryPosting* pPosting;
    fileoffset_t vocOffset = pVocWriter->getFilePointer();
    TermInfo termInfo;

    if (pIndexer_->isRealTime())
    {
        izenelib::util::ScopedWriteLock<izenelib::util::ReadWriteLock> lock(rwLock_);
        for (InMemoryPostingMap::iterator iter = postingMap_.begin(); iter !=postingMap_.end(); ++iter)
        {
            pPosting = iter->second;
            pPosting->setDirty(true);
            if (!pPosting->hasNoChunk())
            {
                tid = iter->first;
                pPosting->write(pWriterDesc, termInfo);		///write posting data
                writeTermInfo(pVocWriter,tid,termInfo);
                pPosting->reset();								///clear posting data
                termInfo.reset();
                termCount_++;
            }
            //delete pPosting;
            //pPosting = NULL;
        }

        postingMap_.clear();

        delete alloc_;
        alloc_ = new boost::scoped_alloc(recycle_);
    }
    else
    {
        sorter_->sort();
        FILE* f = fopen(sorterFullPath_.c_str(),"r");
        fseek(f, 0, SEEK_SET);
        uint64_t count;
        fread(&count, sizeof(uint64_t), 1, f);

        pPosting = new InMemoryPosting(pMemCache_, skipInterval_, maxSkipLevel_);
        termid_t lastTerm = BAD_DOCID;
        try
        {
        for (uint64_t i = 0; i < count; ++i)
        {
            uint8_t len;
            fread(&len, sizeof(uint8_t), 1, f);
            uint32_t docId,offset;
            fread(&tid, sizeof(uint32_t), 1, f);
            fread(&docId, sizeof(uint32_t), 1, f);
            fread(&offset, sizeof(uint32_t), 1, f);

            if(tid != lastTerm && lastTerm != BAD_DOCID)
            {
                if (!pPosting->hasNoChunk())
                {
                    pPosting->write(pWriterDesc, termInfo); 	///write posting data
                    writeTermInfo(pVocWriter, lastTerm, termInfo);
                    pPosting->reset();								///clear posting data
                    pMemCache_->flushMem();
                    termInfo.reset();
                    termCount_++;
                }
            }
            pPosting->add(docId, offset);
            lastTerm = tid;
        }
        }catch(std::exception& e)
        {
        cout<<e.what()<<endl;
        }

        if (!pPosting->hasNoChunk())
        {
            pPosting->write(pWriterDesc, termInfo);	///write posting data
            writeTermInfo(pVocWriter, lastTerm, termInfo);
            pPosting->reset(); 							///clear posting data
            pMemCache_->flushMem();
            termInfo.reset();
            termCount_++;
        }

        fclose(f);
        sorter_->clear_files();
        delete sorter_;
        sorter_ = NULL;
        delete pPosting;
    }

    fileoffset_t vocDescOffset = pVocWriter->getFilePointer();
    int64_t vocLength = vocDescOffset - vocOffset;
    ///begin write vocabulary descriptor
    pVocWriter->writeLong(vocLength);	///<VocLength(Int64)>
    pVocWriter->writeLong(termCount_);	///<TermCount(Int64)>
    ///end write vocabulary descriptor

    return vocDescOffset;
}

TermReader* FieldIndexer::termReader()
{
    izenelib::util::ScopedReadLock<izenelib::util::ReadWriteLock> lock(rwLock_);
    return new InMemoryTermReader(getField(),this);
}

}

NS_IZENELIB_IR_END

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2006 Red Hat, Inc
 *
 * Sugar is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Sugar 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include "gecko-browser.h"

#include <nsCOMPtr.h>
#include <nsIPrefService.h>
#include <nsServiceManagerUtils.h>

enum {
	PROP_0,
	PROP_PROGRESS
};

void
gecko_browser_startup(void)
{
	nsCOMPtr<nsIPrefService> prefService;

	prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
	NS_ENSURE_TRUE(prefService, );

	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));
	NS_ENSURE_TRUE(pref, );

	pref->SetBoolPref ("dom.disable_open_during_load", TRUE);
}

G_DEFINE_TYPE(GeckoBrowser, gecko_browser, GTK_TYPE_MOZ_EMBED)

//static guint signals[N_SIGNALS];

GeckoBrowser *
gecko_browser_new(void)
{
	return GECKO_BROWSER(g_object_new(GECKO_TYPE_BROWSER, NULL));
}

static void
gecko_browser_get_property(GObject         *object,
						   guint            prop_id,
						   GValue          *value,
						   GParamSpec      *pspec)
{
	GeckoBrowser *browser = GECKO_BROWSER(object);

	switch (prop_id) {
	    case PROP_PROGRESS:
			g_value_set_double(value, browser->progress);
		break;

		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
gecko_browser_class_init(GeckoBrowserClass *browser_class)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS(browser_class);

	gobject_class->get_property = gecko_browser_get_property;

	g_object_class_install_property (gobject_class, PROP_PROGRESS,
                                     g_param_spec_double ("progress",
                                                          "Progress",
                                                          "Progress",
                                                          0.0, 1.0, 0.0,
                                                          G_PARAM_READABLE));
}

GeckoBrowser *
gecko_browser_create_window(GeckoBrowser *browser)
{
	return GECKO_BROWSER_GET_CLASS(browser)->create_window(browser);
}

static void
new_window_cb(GtkMozEmbed  *embed,
			  GtkMozEmbed **newEmbed,
              guint         chromemask)
{
	GeckoBrowser *browser;

	browser = gecko_browser_create_window(GECKO_BROWSER(embed));

	*newEmbed = GTK_MOZ_EMBED(browser);
}

static void
gecko_browser_set_progress(GeckoBrowser *browser, float progress)
{
	g_return_if_fail(GECKO_IS_BROWSER(browser));

	browser->progress = progress;
	g_object_notify (G_OBJECT(browser), "progress");
}

static void
net_state_cb(GtkMozEmbed *embed, const char *aURI, gint state, guint status)
{
	GeckoBrowser *browser = GECKO_BROWSER(embed);

	if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK) {
		if (state & GTK_MOZ_EMBED_FLAG_START) {
			browser->total_requests = 0;
			browser->current_requests = 0;
		}
	}

	if (state & GTK_MOZ_EMBED_FLAG_IS_REQUEST) {
		float progress;

		if (state & GTK_MOZ_EMBED_FLAG_START) {
			browser->total_requests++;
		}
		else if (state & GTK_MOZ_EMBED_FLAG_STOP)
		{
			browser->current_requests++;
		}

		progress = float(browser->current_requests) /
				   float(browser->total_requests);
		gecko_browser_set_progress(browser, progress);
	}
}

static void
gecko_browser_init(GeckoBrowser *browser)
{
	browser->progress = 0.0;

	g_signal_connect(G_OBJECT(browser), "new-window",
					 G_CALLBACK(new_window_cb), NULL);
	g_signal_connect(G_OBJECT(browser), "net-state-all",
					 G_CALLBACK(net_state_cb), NULL);
}
<commit_msg>Avoid flickering of the progress bar.<commit_after>/*
 * Copyright (C) 2006 Red Hat, Inc
 *
 * Sugar is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Sugar 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include "gecko-browser.h"

#include <nsCOMPtr.h>
#include <nsIPrefService.h>
#include <nsServiceManagerUtils.h>

enum {
	PROP_0,
	PROP_PROGRESS
};

void
gecko_browser_startup(void)
{
	nsCOMPtr<nsIPrefService> prefService;

	prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
	NS_ENSURE_TRUE(prefService, );

	nsCOMPtr<nsIPrefBranch> pref;
	prefService->GetBranch("", getter_AddRefs(pref));
	NS_ENSURE_TRUE(pref, );

	pref->SetBoolPref ("dom.disable_open_during_load", TRUE);
}

G_DEFINE_TYPE(GeckoBrowser, gecko_browser, GTK_TYPE_MOZ_EMBED)

//static guint signals[N_SIGNALS];

GeckoBrowser *
gecko_browser_new(void)
{
	return GECKO_BROWSER(g_object_new(GECKO_TYPE_BROWSER, NULL));
}

static void
gecko_browser_get_property(GObject         *object,
						   guint            prop_id,
						   GValue          *value,
						   GParamSpec      *pspec)
{
	GeckoBrowser *browser = GECKO_BROWSER(object);

	switch (prop_id) {
	    case PROP_PROGRESS:
			g_value_set_double(value, browser->progress);
		break;

		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
gecko_browser_class_init(GeckoBrowserClass *browser_class)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS(browser_class);

	gobject_class->get_property = gecko_browser_get_property;

	g_object_class_install_property (gobject_class, PROP_PROGRESS,
                                     g_param_spec_double ("progress",
                                                          "Progress",
                                                          "Progress",
                                                          0.0, 1.0, 0.0,
                                                          G_PARAM_READABLE));
}

GeckoBrowser *
gecko_browser_create_window(GeckoBrowser *browser)
{
	return GECKO_BROWSER_GET_CLASS(browser)->create_window(browser);
}

static void
new_window_cb(GtkMozEmbed  *embed,
			  GtkMozEmbed **newEmbed,
              guint         chromemask)
{
	GeckoBrowser *browser;

	browser = gecko_browser_create_window(GECKO_BROWSER(embed));

	*newEmbed = GTK_MOZ_EMBED(browser);
}

static void
gecko_browser_set_progress(GeckoBrowser *browser, float progress)
{
	g_return_if_fail(GECKO_IS_BROWSER(browser));

	browser->progress = progress;
	g_object_notify (G_OBJECT(browser), "progress");
}

static void
net_state_cb(GtkMozEmbed *embed, const char *aURI, gint state, guint status)
{
	GeckoBrowser *browser = GECKO_BROWSER(embed);

	if (state & GTK_MOZ_EMBED_FLAG_IS_NETWORK) {
		if (state & GTK_MOZ_EMBED_FLAG_START) {
			browser->total_requests = 0;
			browser->current_requests = 0;
			browser->progress = 0.0;
		}
	}

	if (state & GTK_MOZ_EMBED_FLAG_IS_REQUEST) {
		float progress;

		if (state & GTK_MOZ_EMBED_FLAG_START) {
			browser->total_requests++;
		}
		else if (state & GTK_MOZ_EMBED_FLAG_STOP)
		{
			browser->current_requests++;
		}

		progress = float(browser->current_requests) /
				   float(browser->total_requests);
		if (progress > browser->progress) {
			gecko_browser_set_progress(browser, progress);
		}
	}
}

static void
gecko_browser_init(GeckoBrowser *browser)
{
	browser->progress = 0.0;

	g_signal_connect(G_OBJECT(browser), "new-window",
					 G_CALLBACK(new_window_cb), NULL);
	g_signal_connect(G_OBJECT(browser), "net-state-all",
					 G_CALLBACK(net_state_cb), NULL);
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>

#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/random.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

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

#include <ir/index_manager/index/Indexer.h>
#include <ir/index_manager/index/LAInput.h>
#include <ir/index_manager/index/IndexerDocument.h>
#include <ir/index_manager/index/IndexReader.h>
#include <ir/index_manager/index/AbsTermReader.h>

#define LOG_DOC_OPERATION
//#define LOG_CHECK_OPERATION
//#define LOG_TERM_ID

using namespace std;
using namespace boost;

using namespace izenelib::ir::indexmanager;

namespace
{
const char* INDEX_FILE_DIR = "./index";

const unsigned int COLLECTION_ID = 1;
};

class IndexerTest
{
private:
    std::map<std::string, unsigned int> propertyMap_;

    Indexer* indexer_;

    unsigned int newDocNum_; ///< the number of documents created when each time createDocument() is called
    boost::mt19937 randEngine_;
    boost::variate_generator<mt19937, uniform_int<> > docLenRand_;
    boost::variate_generator<mt19937, uniform_int<> > termIDRand_;
    boost::variate_generator<mt19937, uniform_int<> > docIDSkipRand_;
    boost::variate_generator<mt19937, uniform_int<> > docNumRand_;

    typedef map<docid_t, size_t> DocIdLenMapT;
    DocIdLenMapT mapDocIdLen_;

    /**
     * as the max doc id in indexer is the max doc id ever indexed,
     * no matter whether that doc is deleted,
     * we have to maintain that max doc id here.
     */
    docid_t maxDocID_;

public:
    IndexerTest(unsigned int docNum, unsigned int docIDSkipMax = 1)
        : indexer_(0)
          ,newDocNum_(docNum)
          ,docLenRand_(randEngine_, uniform_int<>(1, 40*newDocNum_))
          ,termIDRand_(randEngine_, uniform_int<>(1, 400*newDocNum_))
          ,docIDSkipRand_(randEngine_, uniform_int<>(1, docIDSkipMax))
          ,docNumRand_(randEngine_, uniform_int<>(1, newDocNum_))
          ,maxDocID_(0)
    {}

    void setUp(bool isRemoveIndexFiles = true, const string& indexmode = "default") {
        if(isRemoveIndexFiles)
            removeIndexFiles();

        initIndexer(indexmode);
    }

    void tearDown() {
        delete indexer_;
    }

    bool isDocEmpty() const {
        return mapDocIdLen_.empty();
    }

    /**
     * Get a randum number between [1, mapDocIdLen_.size()].
     * @return if mapDocIdLen_ is empty, it returns 0 instead.
     */
    int randDocNum() const {
        if(mapDocIdLen_.empty())
            return 0;

        boost::variate_generator<mt19937, uniform_int<> > numRand(randEngine_, uniform_int<>(1, mapDocIdLen_.size()));
        return numRand();
    }

    /** Only create \e newDocNum_ documents. */
    void createDocument(bool isRandom = false) {
        docid_t docID = maxDocID_;
        for(unsigned int i = 1; i <= (isRandom ? docNumRand_() : newDocNum_); i++)
        {
            docID += docIDSkipRand_();
#ifdef LOG_DOC_OPERATION
            cout << "create doc id: " << docID << endl;
#endif
            IndexerDocument document;
            prepareDocument(document, docID);
            BOOST_CHECK_EQUAL(indexer_->insertDocument(document), 1);
        }

        indexer_->flush();
    }

    /** Update all exsting documents. */
    void updateDocument() {
        docid_t newDocID = maxDocID_;
        DocIdLenMapT oldMap;
        oldMap.swap(mapDocIdLen_);
        for(DocIdLenMapT::const_iterator it=oldMap.begin(); it!=oldMap.end(); ++it)
        {
            newDocID += docIDSkipRand_();
#ifdef LOG_DOC_OPERATION
            cout << "update doc id: " << it->first << " to new doc id: " << newDocID << endl;
#endif
            IndexerDocument document;
            document.setId(it->first);
            prepareDocument(document, newDocID);
            BOOST_CHECK_EQUAL(indexer_->updateDocument(document), 1);
        }

        indexer_->flush();
    }

    /**
     * Remove random number of documents, and also remove documents exceed max doc id.
     */
    void removeDocument() {
        if(mapDocIdLen_.empty())
            return;

        const int removeNum = randDocNum(); // range [1, size]
#ifdef LOG_DOC_OPERATION
        cout << "start removing " << removeNum << " docs..." << endl;
#endif
        for(int i=0; i<removeNum; ++i)
        {
            const int removePos = randDocNum() - 1; // range [0, size-1]
            DocIdLenMapT::iterator it = mapDocIdLen_.begin();
            for(int j=0; j<removePos; ++j)
                ++it;

#ifdef LOG_DOC_OPERATION
            cout << "remove doc id: " << it->first << endl;
#endif
            indexer_->removeDocument(COLLECTION_ID, it->first);
            mapDocIdLen_.erase(it);
        }

        // remove doc id exceed the range
        docid_t overId = maxDocID_ + 1;
#ifdef LOG_DOC_OPERATION
        cout << "remove exceed doc id: " << overId << endl;
#endif
        indexer_->removeDocument(COLLECTION_ID, overId);

        indexer_->flush();
    }

    void checkDocLength() {
        IndexReader* pIndexReader = indexer_->getIndexReader();

        BOOST_CHECK_EQUAL(pIndexReader->numDocs(), mapDocIdLen_.size());
        BOOST_CHECK_EQUAL(pIndexReader->maxDoc(), maxDocID_);

        DocIdLenMapT::const_iterator mapIt = mapDocIdLen_.begin();
        DocIdLenMapT::const_iterator mapItEnd = mapDocIdLen_.end();

        for(; mapIt!=mapItEnd; ++mapIt)
        {
#ifdef LOG_CHECK_OPERATION
            cout << "check: " << mapIt->first << endl;
#endif
            BOOST_CHECK_EQUAL(pIndexReader->docLength(mapIt->first, indexer_->getPropertyIDByName(COLLECTION_ID, "content")), mapIt->second);
        }

        //TermReader* pTermReader = pIndexReader->getTermReader(COLLECTION_ID);
        //delete pTermReader;
    }

    /**
     * Create barrels and check barrel status.
     * @param barrelNum the number of barrels to create
     */
    void checkBarrel(int barrelNum, bool isRealTime, bool isOptimize = false) {
        for(int i=0; i<barrelNum; ++i)
            createDocument(false); // create barrel i
            //createDocument(isRealTime); // create barrel i

        if(isOptimize)
            indexer_->optimizeIndex();

        IndexReader* pIndexReader = indexer_->getIndexReader();
        BarrelsInfo* pBarrelsInfo = pIndexReader->getBarrelsInfo();

        BOOST_CHECK_EQUAL(pBarrelsInfo->getDocCount(), mapDocIdLen_.size());
        BOOST_CHECK_EQUAL(pBarrelsInfo->maxDocId(), maxDocID_);

        if(isOptimize)
        {
            // wait for merge finish
            boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(1000));
            BOOST_CHECK_EQUAL(pBarrelsInfo->getBarrelCount(), 1);
        }
        else if(! isRealTime)
        {
            BOOST_CHECK_EQUAL(pBarrelsInfo->getBarrelCount(), barrelNum);

            for(int i=0; i<barrelNum; ++i)
            {
                BarrelInfo* pBarrelInfo = (*pBarrelsInfo)[i];
                BOOST_CHECK_EQUAL(pBarrelInfo->getDocCount(), newDocNum_);
                BOOST_CHECK_EQUAL(pBarrelInfo->getBaseDocID(), i*newDocNum_+1);
                BOOST_CHECK_EQUAL(pBarrelInfo->getMaxDocID(), (i+1)*newDocNum_);
            }
        }

        DVLOG(2) << "<= t_IndexReader.cpp::checkBarrel()";
    }

private:
    void removeIndexFiles() {
        boost::filesystem::path indexPath(INDEX_FILE_DIR);
        boost::filesystem::remove_all(indexPath);
    }

    void initIndexer(const string& indexmode, bool btree = true, int skipinterval = 0, int skiplevel = 0) {
        if (btree)
            indexer_ = new Indexer();
        else
            indexer_ = new Indexer(MANAGER_PURE_INDEX);

        IndexManagerConfig indexManagerConfig;

        boost::filesystem::path path(INDEX_FILE_DIR);

        indexManagerConfig.indexStrategy_.indexLocation_ = path.string();
        indexManagerConfig.indexStrategy_.indexMode_ = indexmode;
        indexManagerConfig.indexStrategy_.memory_ = 30000000;
        indexManagerConfig.indexStrategy_.indexDocLength_ = true;
        indexManagerConfig.indexStrategy_.skipInterval_ = skipinterval;
        indexManagerConfig.indexStrategy_.maxSkipLevel_ = skiplevel;
        indexManagerConfig.mergeStrategy_.param_ = "dbt";
        indexManagerConfig.storeStrategy_.param_ = "mmap";
        std::map<std::string, unsigned int> collectionIdMapping;
        collectionIdMapping.insert(std::pair<std::string, unsigned int>("testcoll", COLLECTION_ID));

        std::vector<std::string> propertyList(1, "content");
        if(btree)
        {
            std::string date("date");
            propertyList.push_back(date);
            std::string url("provider");
            propertyList.push_back(url);
        }
        std::sort(propertyList.begin(),propertyList.end());
        IndexerCollectionMeta indexCollectionMeta;
        indexCollectionMeta.setName("testcoll");
        for (std::size_t i=0;i<propertyList.size();i++)
        {
            IndexerPropertyConfig indexerPropertyConfig(1+i, propertyList[i], true, true);
            propertyMap_[propertyList[i]] = 1+i;
            if(propertyList[i] != "content")
            {
                indexerPropertyConfig.setIsForward(false);
                indexerPropertyConfig.setIsFilter(true);
            }
            indexCollectionMeta.addPropertyConfig(indexerPropertyConfig);
        }
        indexManagerConfig.addCollectionMeta(indexCollectionMeta);

        indexer_->setIndexManagerConfig(indexManagerConfig, collectionIdMapping);
    }

    void prepareDocument(IndexerDocument& document, unsigned int docId, bool filter = true) {
        document.setDocId(docId, COLLECTION_ID);

        IndexerPropertyConfig propertyConfig(propertyMap_["content"],"content",true,true);
        propertyConfig.setIsLAInput(true);

        boost::shared_ptr<LAInput> laInput(new LAInput);
        document.insertProperty(propertyConfig, laInput);

        const unsigned int docLen = docLenRand_();
        mapDocIdLen_[docId] = docLen;
        maxDocID_ = docId;
        for(unsigned int i = 0; i < docLen; ++i)
        {
            LAInputUnit unit;
            unit.termid_ = termIDRand_();
#ifdef LOG_TERM_ID
            cout << "term id: " << unit.termid_ << endl;
#endif
            unit.wordOffset_ = i;
            document.add_to_property(unit);
        }
#ifdef LOG_TERM_ID
        cout << endl;
#endif

        if(filter)
        {
            using namespace boost::posix_time;
            using namespace boost::gregorian;

            propertyConfig.setPropertyId(propertyMap_["date"]);
            propertyConfig.setName("date");
            propertyConfig.setIsForward(false);
            propertyConfig.setIsFilter(true);
            propertyConfig.setIsLAInput(false);

            struct tm atm;
            ptime now = second_clock::local_time();
            atm = to_tm(now);
            int64_t time = mktime(&atm);

            document.insertProperty(propertyConfig, time);
        }
    }
};

BOOST_AUTO_TEST_SUITE( t_IndexReader )

//BOOST_AUTO_TEST_CASE(index)
//{
    //IndexerTest indexerTest(10);

    //indexerTest.setUp();

    //// create barrel 0
    //indexerTest.createDocument();
    //indexerTest.checkDocLength();

    //// create barrel 1, 2, 3
    //for(int i=0; i<3; ++i)
    //{
        //indexerTest.createDocument();
        //indexerTest.checkDocLength();
    //}
    //indexerTest.tearDown();

    //// new Indexer instance, create barrel 4, 5, 6
    //indexerTest.setUp(false);
    //indexerTest.checkDocLength();
    //for(int i=0; i<3; ++i)
    //{
        //indexerTest.createDocument();
        //indexerTest.checkDocLength();
    //}
    //indexerTest.tearDown();
//}

//BOOST_AUTO_TEST_CASE(update)
//{
    //IndexerTest indexerTest(10);

    //indexerTest.setUp();
    //indexerTest.createDocument();

    //for(int i=0; i<2; ++i)
    //{
        //indexerTest.updateDocument();
        //indexerTest.checkDocLength();
    //}
    //indexerTest.tearDown();
//}

//BOOST_AUTO_TEST_CASE(remove)
//{
    //IndexerTest indexerTest(10);

    //indexerTest.setUp();
    //indexerTest.createDocument();

    //while(! indexerTest.isDocEmpty())
    //{
        //indexerTest.removeDocument();
        //indexerTest.checkDocLength();
    //}
    //indexerTest.checkDocLength();

    //indexerTest.tearDown();
//}

//BOOST_AUTO_TEST_CASE(barrelInfo_offline)
//{
    //IndexerTest indexerTest(10);

    //indexerTest.setUp();

    //indexerTest.checkBarrel(10, false);
    //indexerTest.tearDown();
//}

BOOST_AUTO_TEST_CASE(barrelInfo_optimize)
{
    IndexerTest indexerTest(10);

    indexerTest.setUp();

    indexerTest.checkBarrel(10, false, true);
    indexerTest.tearDown();
}

//BOOST_AUTO_TEST_CASE(barrelInfo_realtime)
//{
    //IndexerTest indexerTest(100);
    //indexerTest.setUp(true, "realtime");
    //indexerTest.checkBarrel(10, true);
    //indexerTest.tearDown();
//}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>update t_IndexReader.<commit_after>#include <boost/test/unit_test.hpp>

#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/random.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

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

#include <ir/index_manager/index/Indexer.h>
#include <ir/index_manager/index/LAInput.h>
#include <ir/index_manager/index/IndexerDocument.h>
#include <ir/index_manager/index/IndexReader.h>
#include <ir/index_manager/index/AbsTermReader.h>

#define LOG_DOC_OPERATION
//#define LOG_CHECK_OPERATION
//#define LOG_TERM_ID

using namespace std;
using namespace boost;

using namespace izenelib::ir::indexmanager;

namespace
{
const char* INDEX_FILE_DIR = "./index";

const unsigned int COLLECTION_ID = 1;

const char* INDEX_MODE_REALTIME = "realtime";

const int TEST_DOC_NUM = 3000;

const int TEST_BARREL_NUM = 10;
};

class IndexerTest
{
private:
    std::map<std::string, unsigned int> propertyMap_;

    Indexer* indexer_;

    unsigned int newDocNum_; ///< the max number of documents created in createDocument()
    bool isDocNumRand_; ///< true for doc number range [1, rand(newDocNum_)], false for range [1, newDocNum_]
    boost::mt19937 randEngine_;
    boost::variate_generator<mt19937, uniform_int<> > docLenRand_;
    boost::variate_generator<mt19937, uniform_int<> > termIDRand_;
    boost::variate_generator<mt19937, uniform_int<> > docIDSkipRand_;
    boost::variate_generator<mt19937, uniform_int<> > docNumRand_;

    typedef map<docid_t, size_t> DocIdLenMapT;
    DocIdLenMapT mapDocIdLen_;

    /**
     * as the max doc id in indexer is the max doc id ever indexed,
     * no matter whether that doc is deleted,
     * we have to maintain that max doc id here.
     */
    docid_t maxDocID_;

public:
    IndexerTest(unsigned int docNum, bool isDocNumRand = false, unsigned int docIDSkipMax = 1)
        : indexer_(0)
          ,newDocNum_(docNum)
          ,isDocNumRand_(isDocNumRand)
          ,docLenRand_(randEngine_, uniform_int<>(1, 40*newDocNum_))
          ,termIDRand_(randEngine_, uniform_int<>(1, 400*newDocNum_))
          ,docIDSkipRand_(randEngine_, uniform_int<>(1, docIDSkipMax))
          ,docNumRand_(randEngine_, uniform_int<>(1, newDocNum_))
          ,maxDocID_(0)
    {}

    void setUp(bool isRemoveIndexFiles = true, const string& indexmode = "default") {
        if(isRemoveIndexFiles)
            removeIndexFiles();

        initIndexer(indexmode);
    }

    void tearDown() {
        delete indexer_;
    }

    bool isDocEmpty() const {
        return mapDocIdLen_.empty();
    }

    /**
     * Get a randum number between [1, mapDocIdLen_.size()].
     * @return if mapDocIdLen_ is empty, it returns 0 instead.
     */
    int randDocNum() const {
        if(mapDocIdLen_.empty())
            return 0;

        boost::variate_generator<mt19937, uniform_int<> > numRand(randEngine_, uniform_int<>(1, mapDocIdLen_.size()));
        return numRand();
    }

    /** Only create \e newDocNum_ documents. */
    void createDocument() {
        DVLOG(2) << "=> IndexerTest::createDocument()";

        docid_t docID = maxDocID_;
        for(unsigned int i = 1; i <= (isDocNumRand_ ? docNumRand_() : newDocNum_); i++)
        {
            docID += docIDSkipRand_();
#ifdef LOG_DOC_OPERATION
            cout << "create doc id: " << docID << endl;
#endif
            IndexerDocument document;
            prepareDocument(document, docID);
            BOOST_CHECK_EQUAL(indexer_->insertDocument(document), 1);
        }

        indexer_->flush();
        DVLOG(2) << "<= IndexerTest::createDocument()";
    }

    /** Update all exsting documents. */
    void updateDocument() {
        DVLOG(2) << "=> IndexerTest::updateDocument()";

        docid_t newDocID = maxDocID_;
        DocIdLenMapT oldMap;
        oldMap.swap(mapDocIdLen_);
        for(DocIdLenMapT::const_iterator it=oldMap.begin(); it!=oldMap.end(); ++it)
        {
            newDocID += docIDSkipRand_();
#ifdef LOG_DOC_OPERATION
            cout << "update doc id: " << it->first << " to new doc id: " << newDocID << endl;
#endif
            IndexerDocument document;
            document.setId(it->first);
            prepareDocument(document, newDocID);
            BOOST_CHECK_EQUAL(indexer_->updateDocument(document), 1);
        }

        indexer_->flush();
        DVLOG(2) << "<= IndexerTest::updateDocument()";
    }

    /**
     * Remove random number of documents, and also remove documents exceed max doc id.
     */
    void removeDocument() {
        DVLOG(2) << "=> IndexerTest::removeDocument()";

        if(mapDocIdLen_.empty())
            return;

        const int removeNum = randDocNum(); // range [1, size]
#ifdef LOG_DOC_OPERATION
        cout << "start removing " << removeNum << " docs..." << endl;
#endif
        for(int i=0; i<removeNum; ++i)
        {
            const int removePos = randDocNum() - 1; // range [0, size-1]
            DocIdLenMapT::iterator it = mapDocIdLen_.begin();
            for(int j=0; j<removePos; ++j)
                ++it;

#ifdef LOG_DOC_OPERATION
            cout << "remove doc id: " << it->first << endl;
#endif
            indexer_->removeDocument(COLLECTION_ID, it->first);
            mapDocIdLen_.erase(it);
        }

        // remove doc id exceed the range
        docid_t overId = maxDocID_ + 1;
#ifdef LOG_DOC_OPERATION
        cout << "remove exceed doc id: " << overId << endl;
#endif
        indexer_->removeDocument(COLLECTION_ID, overId);

        indexer_->flush();
        DVLOG(2) << "<= IndexerTest::removeDocument()";
    }

    void checkDocLength() {
        DVLOG(2) << "=> IndexerTest::checkDocLength()";

        IndexReader* pIndexReader = indexer_->getIndexReader();

        BOOST_CHECK_EQUAL(pIndexReader->numDocs(), mapDocIdLen_.size());
        BOOST_CHECK_EQUAL(pIndexReader->maxDoc(), maxDocID_);

        DocIdLenMapT::const_iterator mapIt = mapDocIdLen_.begin();
        DocIdLenMapT::const_iterator mapItEnd = mapDocIdLen_.end();

        for(; mapIt!=mapItEnd; ++mapIt)
        {
#ifdef LOG_CHECK_OPERATION
            cout << "check: " << mapIt->first << endl;
#endif
            BOOST_CHECK_EQUAL(pIndexReader->docLength(mapIt->first, indexer_->getPropertyIDByName(COLLECTION_ID, "content")), mapIt->second);
        }

        //TermReader* pTermReader = pIndexReader->getTermReader(COLLECTION_ID);
        //delete pTermReader;

        DVLOG(2) << "<= IndexerTest::checkDocLength()";
    }

    /**
     * Create barrels and check barrel status.
     * @param barrelNum the number of barrels to create
     */
    void checkBarrel(int barrelNum) {
        DVLOG(2) << "=> IndexerTest::checkBarrel()";

        for(int i=0; i<barrelNum; ++i)
            createDocument(); // create barrel i

        IndexReader* pIndexReader = indexer_->getIndexReader();
        BarrelsInfo* pBarrelsInfo = pIndexReader->getBarrelsInfo();

        BOOST_CHECK_EQUAL(pBarrelsInfo->maxDocId(), maxDocID_);

        if(indexer_->getIndexManagerConfig()->indexStrategy_.indexMode_ != INDEX_MODE_REALTIME)
        {
            BOOST_CHECK_EQUAL(pBarrelsInfo->getBarrelCount(), barrelNum);
            BOOST_CHECK_EQUAL(pBarrelsInfo->getDocCount(), mapDocIdLen_.size());

            for(int i=0; i<barrelNum; ++i)
            {
                BarrelInfo* pBarrelInfo = (*pBarrelsInfo)[i];
                BOOST_CHECK_EQUAL(pBarrelInfo->getDocCount(), newDocNum_);
                BOOST_CHECK_EQUAL(pBarrelInfo->getBaseDocID(), i*newDocNum_+1);
                BOOST_CHECK_EQUAL(pBarrelInfo->getMaxDocID(), (i+1)*newDocNum_);
            }
        }

        DVLOG(2) << "<= IndexerTest::checkBarrel()";
    }

    /**
     * Create barrels, optimize barrels (merge them into one), and check barrel status.
     * @param barrelNum the number of barrels to create
     */
    void optimizeBarrel(int barrelNum) {
        DVLOG(2) << "=> IndexerTest::optimizeBarrel()";

        for(int i=0; i<barrelNum; ++i)
            createDocument(); // create barrel i

        indexer_->optimizeIndex();

        IndexReader* pIndexReader = indexer_->getIndexReader();
        BarrelsInfo* pBarrelsInfo = pIndexReader->getBarrelsInfo();

        BOOST_CHECK_EQUAL(pBarrelsInfo->maxDocId(), maxDocID_);
        BOOST_CHECK_EQUAL(pBarrelsInfo->getDocCount(), mapDocIdLen_.size());

        DVLOG(2) << "<= IndexerTest::optimizeBarrel()";
    }

    /**
     * Check optimize barrels result.
     */
    void checkOptimize() {
        DVLOG(2) << "=> IndexerTest::checkOptimize()";

        IndexReader* pIndexReader = indexer_->getIndexReader();
        BarrelsInfo* pBarrelsInfo = pIndexReader->getBarrelsInfo();

        BOOST_CHECK_EQUAL(pBarrelsInfo->maxDocId(), maxDocID_);
        BOOST_CHECK_EQUAL(pBarrelsInfo->getBarrelCount(), 1);
        BOOST_CHECK_EQUAL(pBarrelsInfo->getDocCount(), mapDocIdLen_.size());

        DVLOG(2) << "<= IndexerTest::checkOptimize()";
    }

    /**
     * Create barrels, optimize barrels (merge them into one), and check barrel status.
     * @param barrelNum the number of barrels to create
     */
    void createAfterOptimizeBarrel(int barrelNum) {
        DVLOG(2) << "=> IndexerTest::createAfterOptimizeBarrel()";

        for(int i=0; i<barrelNum; ++i)
            createDocument(); // create barrel i

        indexer_->optimizeIndex();

        for(int i=0; i<barrelNum; ++i)
            createDocument(); // create barrel i

        IndexReader* pIndexReader = indexer_->getIndexReader();
        BarrelsInfo* pBarrelsInfo = pIndexReader->getBarrelsInfo();

        BOOST_CHECK_EQUAL(pBarrelsInfo->maxDocId(), maxDocID_);
        BOOST_CHECK(pBarrelsInfo->getBarrelCount() >= 1 && pBarrelsInfo->getBarrelCount() <= 2*barrelNum);
        BOOST_CHECK_EQUAL(pBarrelsInfo->getDocCount(), mapDocIdLen_.size());

        DVLOG(2) << "<= IndexerTest::createAfterOptimizeBarrel()";
    }

private:
    void removeIndexFiles() {
        boost::filesystem::path indexPath(INDEX_FILE_DIR);
        boost::filesystem::remove_all(indexPath);
    }

    void initIndexer(const string& indexmode, bool btree = true, int skipinterval = 0, int skiplevel = 0) {
        if (btree)
            indexer_ = new Indexer();
        else
            indexer_ = new Indexer(MANAGER_PURE_INDEX);

        IndexManagerConfig indexManagerConfig;

        boost::filesystem::path path(INDEX_FILE_DIR);

        indexManagerConfig.indexStrategy_.indexLocation_ = path.string();
        indexManagerConfig.indexStrategy_.indexMode_ = indexmode;
        indexManagerConfig.indexStrategy_.memory_ = 30000000;
        indexManagerConfig.indexStrategy_.indexDocLength_ = true;
        indexManagerConfig.indexStrategy_.skipInterval_ = skipinterval;
        indexManagerConfig.indexStrategy_.maxSkipLevel_ = skiplevel;
        indexManagerConfig.mergeStrategy_.param_ = "dbt";
        indexManagerConfig.storeStrategy_.param_ = "mmap";
        std::map<std::string, unsigned int> collectionIdMapping;
        collectionIdMapping.insert(std::pair<std::string, unsigned int>("testcoll", COLLECTION_ID));

        std::vector<std::string> propertyList(1, "content");
        if(btree)
        {
            std::string date("date");
            propertyList.push_back(date);
            std::string url("provider");
            propertyList.push_back(url);
        }
        std::sort(propertyList.begin(),propertyList.end());
        IndexerCollectionMeta indexCollectionMeta;
        indexCollectionMeta.setName("testcoll");
        for (std::size_t i=0;i<propertyList.size();i++)
        {
            IndexerPropertyConfig indexerPropertyConfig(1+i, propertyList[i], true, true);
            propertyMap_[propertyList[i]] = 1+i;
            if(propertyList[i] != "content")
            {
                indexerPropertyConfig.setIsForward(false);
                indexerPropertyConfig.setIsFilter(true);
            }
            indexCollectionMeta.addPropertyConfig(indexerPropertyConfig);
        }
        indexManagerConfig.addCollectionMeta(indexCollectionMeta);

        indexer_->setIndexManagerConfig(indexManagerConfig, collectionIdMapping);
    }

    void prepareDocument(IndexerDocument& document, unsigned int docId, bool filter = true) {
        document.setDocId(docId, COLLECTION_ID);

        IndexerPropertyConfig propertyConfig(propertyMap_["content"],"content",true,true);
        propertyConfig.setIsLAInput(true);

        boost::shared_ptr<LAInput> laInput(new LAInput);
        document.insertProperty(propertyConfig, laInput);

        const unsigned int docLen = docLenRand_();
        mapDocIdLen_[docId] = docLen;
        maxDocID_ = docId;
        for(unsigned int i = 0; i < docLen; ++i)
        {
            LAInputUnit unit;
            unit.termid_ = termIDRand_();
#ifdef LOG_TERM_ID
            cout << "term id: " << unit.termid_ << endl;
#endif
            unit.wordOffset_ = i;
            document.add_to_property(unit);
        }
#ifdef LOG_TERM_ID
        cout << endl;
#endif

        if(filter)
        {
            using namespace boost::posix_time;
            using namespace boost::gregorian;

            propertyConfig.setPropertyId(propertyMap_["date"]);
            propertyConfig.setName("date");
            propertyConfig.setIsForward(false);
            propertyConfig.setIsFilter(true);
            propertyConfig.setIsLAInput(false);

            struct tm atm;
            ptime now = second_clock::local_time();
            atm = to_tm(now);
            int64_t time = mktime(&atm);

            document.insertProperty(propertyConfig, time);
        }
    }
};

BOOST_AUTO_TEST_SUITE( t_IndexReader )

BOOST_AUTO_TEST_CASE(index)
{
    IndexerTest indexerTest(TEST_DOC_NUM);

    indexerTest.setUp();

    // create barrel 0
    indexerTest.createDocument();
    indexerTest.checkDocLength();

    // create barrel 1, 2, 3
    for(int i=0; i<TEST_BARREL_NUM; ++i)
    {
        indexerTest.createDocument();
        indexerTest.checkDocLength();
    }
    indexerTest.tearDown();

    // new Indexer instance, create barrel 4, 5, 6
    indexerTest.setUp(false);
    indexerTest.checkDocLength();
    for(int i=0; i<TEST_BARREL_NUM; ++i)
    {
        indexerTest.createDocument();
        indexerTest.checkDocLength();
    }
    indexerTest.tearDown();
}

BOOST_AUTO_TEST_CASE(update)
{
    IndexerTest indexerTest(TEST_DOC_NUM);

    indexerTest.setUp();
    indexerTest.createDocument();

    for(int i=0; i<TEST_BARREL_NUM; ++i)
    {
        indexerTest.updateDocument();
        indexerTest.checkDocLength();
    }
    indexerTest.tearDown();
}

BOOST_AUTO_TEST_CASE(remove)
{
    IndexerTest indexerTest(TEST_DOC_NUM);

    indexerTest.setUp();
    indexerTest.createDocument();

    while(! indexerTest.isDocEmpty())
    {
        indexerTest.removeDocument();
        indexerTest.checkDocLength();
    }
    indexerTest.checkDocLength();

    indexerTest.tearDown();
}

BOOST_AUTO_TEST_CASE(barrelInfo_check)
{
    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp();
        indexerTest.checkBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();
    }

    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp(true, INDEX_MODE_REALTIME);
        indexerTest.checkBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();
    }
}

BOOST_AUTO_TEST_CASE(barrelInfo_optimize)
{
    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp();
        indexerTest.optimizeBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();

        indexerTest.setUp(false);
        indexerTest.checkOptimize();
        indexerTest.tearDown();
    }

    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp(true, INDEX_MODE_REALTIME);
        indexerTest.optimizeBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();

        indexerTest.setUp(false);
        indexerTest.checkOptimize();
        indexerTest.tearDown();
    }
}

BOOST_AUTO_TEST_CASE(barrelInfo_create_after_optimize)
{
    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp();
        indexerTest.createAfterOptimizeBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();
    }

    {
        IndexerTest indexerTest(TEST_DOC_NUM);
        indexerTest.setUp(true, INDEX_MODE_REALTIME);
        indexerTest.createAfterOptimizeBarrel(TEST_BARREL_NUM);
        indexerTest.tearDown();
    }
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before><commit_msg>fix DHT logging build error<commit_after><|endoftext|>


<commit_before>/* Copyright 2013-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"

class NameExpr : public QueryExpr {
  w_string name;
  w_ht_t *map;
  bool caseless;
  bool wholename;
  explicit NameExpr(w_ht_t* map, bool caseless, bool wholename)
      : map(map), caseless(caseless), wholename(wholename) {}

  ~NameExpr() {
    if (map) {
      w_ht_free(map);
    }
  }

 public:
  bool evaluate(struct w_query_ctx* ctx, const watchman_file* file) override {
    w_string_t* str;

    if (wholename) {
      str = w_query_ctx_get_wholename(ctx);
    } else {
      str = w_file_get_name(file);
    }

    if (map) {
      bool matched;
      w_ht_val_t val;

      if (caseless) {
        str = w_string_dup_lower(str);
        if (!str) {
          return false;
        }
      }

      matched = w_ht_lookup(map, w_ht_ptr_val(str), &val, false);

      if (caseless) {
        w_string_delref(str);
      }

      return matched;
    }

    if (caseless) {
      return w_string_equal_caseless(str, name);
    }
    return w_string_equal(str, name);
  }

  static std::unique_ptr<QueryExpr>
  parse(w_query* query, json_t* term, bool caseless) {
    const char *pattern = nullptr, *scope = "basename";
    const char* which = caseless ? "iname" : "name";
    json_t* name;
    w_ht_t* map = nullptr;

    if (!json_is_array(term)) {
      ignore_result(
          asprintf(&query->errmsg, "Expected array for '%s' term", which));
      return nullptr;
    }

    if (json_array_size(term) > 3) {
      ignore_result(asprintf(
          &query->errmsg, "Invalid number of arguments for '%s' term", which));
      return nullptr;
    }

    if (json_array_size(term) == 3) {
      json_t* jscope;

      jscope = json_array_get(term, 2);
      if (!json_is_string(jscope)) {
        ignore_result(asprintf(
            &query->errmsg, "Argument 3 to '%s' must be a string", which));
        return nullptr;
      }

      scope = json_string_value(jscope);

      if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
        ignore_result(asprintf(
            &query->errmsg,
            "Invalid scope '%s' for %s expression",
            scope,
            which));
        return nullptr;
      }
    }

    name = json_array_get(term, 1);

    if (json_is_array(name)) {
      uint32_t i;

      for (i = 0; i < json_array_size(name); i++) {
        if (!json_is_string(json_array_get(name, i))) {
          ignore_result(asprintf(
              &query->errmsg,
              "Argument 2 to '%s' must be "
              "either a string or an "
              "array of string",
              which));
          return nullptr;
        }
      }

      map = w_ht_new((uint32_t)json_array_size(name), &w_ht_string_funcs);
      for (i = 0; i < json_array_size(name); i++) {
        w_string_t* element;
        const char* ele;
        const json_t* jele = json_array_get(name, i);
        ele = json_string_value(jele);
        // We need to make a copy of the string since we do in-place separator
        // normalization on the paths.
        if (caseless) {
          element =
              w_string_new_lower_typed(ele, json_to_w_string(jele).type());
        } else {
          element = w_string_new_typed(ele, json_to_w_string(jele).type());
        }

        w_string_in_place_normalize_separators(&element, WATCHMAN_DIR_SEP);

        w_ht_set(map, w_ht_ptr_val(element), 1);
        w_string_delref(element);
      }

    } else if (json_is_string(name)) {
      pattern = json_string_value(name);
    } else {
      ignore_result(asprintf(
          &query->errmsg,
          "Argument 2 to '%s' must be either a string or an array of string",
          which));
      return nullptr;
    }

    auto data = new NameExpr(map, caseless, !strcmp(scope, "wholename"));

    if (pattern) {
      // We need to make a copy of the string since we do in-place separator
      // normalization on the paths.
      w_string pat(pattern, json_to_w_string(name).type());
      data->name = w_string_normalize_separators(pat, WATCHMAN_DIR_SEP);
    }

    return std::unique_ptr<QueryExpr>(data);
  }

  static std::unique_ptr<QueryExpr> parseName(w_query* query, json_t* term) {
    return parse(query, term, !query->case_sensitive);
  }
  static std::unique_ptr<QueryExpr> parseIName(w_query* query, json_t* term) {
    return parse(query, term, true);
  }
};

W_TERM_PARSER("name", NameExpr::parseName)
W_TERM_PARSER("iname", NameExpr::parseIName)

/* vim:ts=2:sw=2:et:
 */
<commit_msg>name term: w_ht_t -> unordered_set<commit_after>/* Copyright 2013-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */

#include "watchman.h"

class NameExpr : public QueryExpr {
  w_string name;
  std::unordered_set<w_string> set;
  bool caseless;
  bool wholename;
  explicit NameExpr(
      std::unordered_set<w_string>&& set,
      bool caseless,
      bool wholename)
      : set(std::move(set)), caseless(caseless), wholename(wholename) {}

 public:
  bool evaluate(struct w_query_ctx* ctx, const watchman_file* file) override {
    w_string_t* str;

    if (wholename) {
      str = w_query_ctx_get_wholename(ctx);
    } else {
      str = w_file_get_name(file);
    }

    if (!set.empty()) {
      bool matched;

      if (caseless) {
        str = w_string_dup_lower(str);
        if (!str) {
          return false;
        }
      }

      matched = set.find(str) != set.end();

      if (caseless) {
        w_string_delref(str);
      }

      return matched;
    }

    if (caseless) {
      return w_string_equal_caseless(str, name);
    }
    return w_string_equal(str, name);
  }

  static std::unique_ptr<QueryExpr>
  parse(w_query* query, json_t* term, bool caseless) {
    const char *pattern = nullptr, *scope = "basename";
    const char* which = caseless ? "iname" : "name";
    json_t* name;
    std::unordered_set<w_string> set;

    if (!json_is_array(term)) {
      ignore_result(
          asprintf(&query->errmsg, "Expected array for '%s' term", which));
      return nullptr;
    }

    if (json_array_size(term) > 3) {
      ignore_result(asprintf(
          &query->errmsg, "Invalid number of arguments for '%s' term", which));
      return nullptr;
    }

    if (json_array_size(term) == 3) {
      json_t* jscope;

      jscope = json_array_get(term, 2);
      if (!json_is_string(jscope)) {
        ignore_result(asprintf(
            &query->errmsg, "Argument 3 to '%s' must be a string", which));
        return nullptr;
      }

      scope = json_string_value(jscope);

      if (strcmp(scope, "basename") && strcmp(scope, "wholename")) {
        ignore_result(asprintf(
            &query->errmsg,
            "Invalid scope '%s' for %s expression",
            scope,
            which));
        return nullptr;
      }
    }

    name = json_array_get(term, 1);

    if (json_is_array(name)) {
      uint32_t i;

      for (i = 0; i < json_array_size(name); i++) {
        if (!json_is_string(json_array_get(name, i))) {
          ignore_result(asprintf(
              &query->errmsg,
              "Argument 2 to '%s' must be "
              "either a string or an "
              "array of string",
              which));
          return nullptr;
        }
      }

      set.reserve(json_array_size(name));
      for (i = 0; i < json_array_size(name); i++) {
        w_string_t* element;
        const char* ele;
        const json_t* jele = json_array_get(name, i);
        ele = json_string_value(jele);
        // We need to make a copy of the string since we do in-place separator
        // normalization on the paths.
        if (caseless) {
          element =
              w_string_new_lower_typed(ele, json_to_w_string(jele).type());
        } else {
          element = w_string_new_typed(ele, json_to_w_string(jele).type());
        }

        w_string_in_place_normalize_separators(&element, WATCHMAN_DIR_SEP);

        set.insert(element);
        w_string_delref(element);
      }

    } else if (json_is_string(name)) {
      pattern = json_string_value(name);
    } else {
      ignore_result(asprintf(
          &query->errmsg,
          "Argument 2 to '%s' must be either a string or an array of string",
          which));
      return nullptr;
    }

    auto data =
        new NameExpr(std::move(set), caseless, !strcmp(scope, "wholename"));

    if (pattern) {
      // We need to make a copy of the string since we do in-place separator
      // normalization on the paths.
      w_string pat(pattern, json_to_w_string(name).type());
      data->name = w_string_normalize_separators(pat, WATCHMAN_DIR_SEP);
    }

    return std::unique_ptr<QueryExpr>(data);
  }

  static std::unique_ptr<QueryExpr> parseName(w_query* query, json_t* term) {
    return parse(query, term, !query->case_sensitive);
  }
  static std::unique_ptr<QueryExpr> parseIName(w_query* query, json_t* term) {
    return parse(query, term, true);
  }
};

W_TERM_PARSER("name", NameExpr::parseName)
W_TERM_PARSER("iname", NameExpr::parseIName)

/* vim:ts=2:sw=2:et:
 */
<|endoftext|>


<commit_before>/*  ===========================================================================
#  This is the library for Hover.
#
#  Hover is a development kit that lets you control your hardware projects in a whole new way.
#  Wave goodbye to physical buttons. Hover detects hand movements in the air for touch-less interaction.
#  It also features five touch-sensitive regions for even more options.
#  Hover uses I2C and 2 digital pins. It is compatible with Arduino, Raspberry Pi and more.
#
#  Hover can be purchased here: http://www.justhover.com
#
#  Written by Emran Mahbub and Jonathan Li for Gearseven Studios.
#  BSD license, all text above must be included in any redistribution
#  ===========================================================================
#
#
#  SUPPORT
#  For questions and comments, email us at support@gearseven.com
#  v1.0
#  ===========================================================================*/

#include "Hover.h"

void Hover::begin(ts, rst) {
	Wire.begin();
	pinMode(ts, INPUT);    //Used by TS line on MGC3130
	pinMode(rst, OUTPUT);    //Used by TS line on MGC3130
	digitalWrite(rst, LOW);
	pinMode(rst, INPUT);
	delay(3000);
	Serial.println("Hover is ready");
}

void Hover::setRelease(int ts) {
    digitalWrite(ts, HIGH);
    pinMode(ts, INPUT);
}

boolean Hover::getStatus(int ts) {
	if (digitalRead(ts) == 0) {
		pinMode(ts, OUTPUT);
		digitalWrite(ts, LOW);
		return 0;
	}
	return 1;
}

byte Hover::getEvent(void) {
	byte data;
	byte event;
	int c = 0;
    WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)18);    // request 20 bytes from slave device at 0x42
    while(WIRE.available())    // slave may send less than requested
    {
		data = WIRE.read(); // receive a byte as character
		if (c == 10 && data > 1) {
			event = (B00000001 << (data-1)) | B00100000;
			return event;
		}
		if (c == 14 && data > B11111) {
			event = ((data & B11100000) >> 5) | B01000000 ;
			return event;
		}
		if (c == 15 && data > 0) {
			event = (((data & B0011) << 3) | B01000000);
			return event;
		}
        c++;
    }
}

String Hover::getEventString(byte eventByte) {

	//Serial.println("inside string fcn");
	//return "Test";
	//Serial.println(eventByte);
    if (eventByte == B00100010) {
        //Serial.println("Right swipe");
		return "Right Swipe";
    } else if (eventByte == B00100100) {
        //Serial.println("Left swipe");
		return "Left Swipe";

    } else if (eventByte == B00101000) {
        //Serial.println("Up swipe");
		return "Up Swipe";

    } else if (eventByte == B00110000) {
        //Serial.println("Down swipe");
		return "Down Swipe";

    } else if (eventByte == B01000001) {
        //Serial.println("Tap south");
		return "Tap South";

    } else if (eventByte == B01000010) {
        //Serial.println("Tap West");
		return "Tap West";

    } else if (eventByte == B01010000) {
        //Serial.println("Tap Center");
		return "Tap Center";

    } else if (eventByte == B01001000) {
        //Serial.println("Tap East");
		return "Tap East";

    } else if (eventByte == B01000100) {
        //Serial.println("Tap NORTH");
		return "Tap North";

    }
	return "";
}
<commit_msg>Added i2caddr+ addr<commit_after>/*  ===========================================================================
#  This is the library for Hover.
#
#  Hover is a development kit that lets you control your hardware projects in a whole new way.
#  Wave goodbye to physical buttons. Hover detects hand movements in the air for touch-less interaction.
#  It also features five touch-sensitive regions for even more options.
#  Hover uses I2C and 2 digital pins. It is compatible with Arduino, Raspberry Pi and more.
#
#  Hover can be purchased here: http://www.justhover.com
#
#  Written by Emran Mahbub and Jonathan Li for Gearseven Studios.
#  BSD license, all text above must be included in any redistribution
#  ===========================================================================
#
#
#  SUPPORT
#  For questions and comments, email us at support@gearseven.com
#  v1.0
#  ===========================================================================*/

#include "Hover.h"

Hover::Hover(uint8_t addr) {
 _i2caddr = addr;
}

void Hover::begin(ts, rst) {
	Wire.begin();
	pinMode(ts, INPUT);    //Used by TS line on MGC3130
	pinMode(rst, OUTPUT);    //Used by TS line on MGC3130
	digitalWrite(rst, LOW);
	pinMode(rst, INPUT);
	delay(3000);
	Serial.println("Hover is ready");
}

void Hover::setRelease(int ts) {
    digitalWrite(ts, HIGH);
    pinMode(ts, INPUT);
}

boolean Hover::getStatus(int ts) {
	if (digitalRead(ts) == 0) {
		pinMode(ts, OUTPUT);
		digitalWrite(ts, LOW);
		return 0;
	}
	return 1;
}

byte Hover::getEvent(void) {
	byte data;
	byte event;
	int c = 0;
    WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)18);    // request 20 bytes from slave device at 0x42
    while(WIRE.available())    // slave may send less than requested
    {
		data = WIRE.read(); // receive a byte as character
		if (c == 10 && data > 1) {
			event = (B00000001 << (data-1)) | B00100000;
			return event;
		}
		if (c == 14 && data > B11111) {
			event = ((data & B11100000) >> 5) | B01000000 ;
			return event;
		}
		if (c == 15 && data > 0) {
			event = (((data & B0011) << 3) | B01000000);
			return event;
		}
        c++;
    }
}

String Hover::getEventString(byte eventByte) {

	//Serial.println("inside string fcn");
	//return "Test";
	//Serial.println(eventByte);
    if (eventByte == B00100010) {
        //Serial.println("Right swipe");
		return "Right Swipe";
    } else if (eventByte == B00100100) {
        //Serial.println("Left swipe");
		return "Left Swipe";

    } else if (eventByte == B00101000) {
        //Serial.println("Up swipe");
		return "Up Swipe";

    } else if (eventByte == B00110000) {
        //Serial.println("Down swipe");
		return "Down Swipe";

    } else if (eventByte == B01000001) {
        //Serial.println("Tap south");
		return "Tap South";

    } else if (eventByte == B01000010) {
        //Serial.println("Tap West");
		return "Tap West";

    } else if (eventByte == B01010000) {
        //Serial.println("Tap Center");
		return "Tap Center";

    } else if (eventByte == B01001000) {
        //Serial.println("Tap East");
		return "Tap East";

    } else if (eventByte == B01000100) {
        //Serial.println("Tap NORTH");
		return "Tap North";

    }
	return "";
}
<|endoftext|>


<commit_before>#pragma once

#include <iomanip>

#include "common.hpp"
#include "utils/string.hpp"

LEMONBUDDY_NS

union rgba {
  struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
  };
  uint32_t v;
};

class color;
static map<string, color> g_colorstore;

class color {
 public:
  explicit color(string hex) : m_hex(string_util::upper(hex)) {
    m_rgba.v = static_cast<uint32_t>(strtoul(&hex[1], nullptr, 16));
    // premultiply alpha
    m_rgba.r = m_rgba.r * m_rgba.a / 255;
    m_rgba.g = m_rgba.g * m_rgba.a / 255;
    m_rgba.b = m_rgba.b * m_rgba.a / 255;
  }

  explicit color(uint32_t v) {
    char buffer[7];
    snprintf(buffer, sizeof(buffer), "%06x", v);
    m_hex = "#" + string{buffer};
    m_rgba.v = v;
  }

  uint32_t value() const {
    return m_rgba.v;
  }

  string rgb() const {
    // clang-format off
    return string_util::from_stream(stringstream()
        << "#"
        << std::setw(6)
        << std::setfill('0')
        << std::hex
        << std::uppercase
        << (m_rgba.v & 0x00FFFFFF));
    // clang-format on
  }

  string hex() const {
    return m_hex;
  }

  static auto parse(string input, color fallback) {
    auto it = g_colorstore.find(input);
    if (it != g_colorstore.end()) {
      return it->second;
    }
    string hex{input};
    if (hex.substr(0, 1) != "#")
      hex = "#" + hex;
    if (hex.length() == 4)
      hex = {'#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]};
    if (hex.length() == 7)
      hex = "#FF" + hex.substr(1);
    if (hex.length() != 9)
      return fallback;
    color result{hex};
    g_colorstore.emplace(input, result);
    return result;
  }

  static auto parse(string input) {
    static color none{0};
    return parse(input, none);
  }

 protected:
  rgba m_rgba;
  string m_hex;
};

static color g_colorblack{"#ff000000"};
static color g_colorwhite{"#ffffffff"};

LEMONBUDDY_NS_END
<commit_msg>fix(ci): Forward decl. error<commit_after>#pragma once

#include <iomanip>

#include "common.hpp"
#include "utils/string.hpp"

LEMONBUDDY_NS

union rgba {
  struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
    uint8_t a;
  };
  uint32_t v;
};

static map<string, class color> g_colorstore;

class color {
 public:
  explicit color(string hex) : m_hex(string_util::upper(hex)) {
    m_rgba.v = static_cast<uint32_t>(strtoul(&hex[1], nullptr, 16));
    // premultiply alpha
    m_rgba.r = m_rgba.r * m_rgba.a / 255;
    m_rgba.g = m_rgba.g * m_rgba.a / 255;
    m_rgba.b = m_rgba.b * m_rgba.a / 255;
  }

  explicit color(uint32_t v) {
    char buffer[7];
    snprintf(buffer, sizeof(buffer), "%06x", v);
    m_hex = "#" + string{buffer};
    m_rgba.v = v;
  }

  uint32_t value() const {
    return m_rgba.v;
  }

  string rgb() const {
    // clang-format off
    return string_util::from_stream(stringstream()
        << "#"
        << std::setw(6)
        << std::setfill('0')
        << std::hex
        << std::uppercase
        << (m_rgba.v & 0x00FFFFFF));
    // clang-format on
  }

  string hex() const {
    return m_hex;
  }

  static auto parse(string input, color fallback) {
    auto it = g_colorstore.find(input);
    if (it != g_colorstore.end()) {
      return it->second;
    }
    string hex{input};
    if (hex.substr(0, 1) != "#")
      hex = "#" + hex;
    if (hex.length() == 4)
      hex = {'#', hex[1], hex[1], hex[2], hex[2], hex[3], hex[3]};
    if (hex.length() == 7)
      hex = "#FF" + hex.substr(1);
    if (hex.length() != 9)
      return fallback;
    color result{hex};
    g_colorstore.emplace(input, result);
    return result;
  }

  static auto parse(string input) {
    static color none{0};
    return parse(input, none);
  }

 protected:
  rgba m_rgba;
  string m_hex;
};

static color g_colorblack{"#ff000000"};
static color g_colorwhite{"#ffffffff"};

LEMONBUDDY_NS_END
<|endoftext|>