<commit_before>// Copyright (c) 2010 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 "chrome/browser/chromeos/login/network_selection_view.h"

#include <signal.h>
#include <sys/types.h>
#include <string>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/native_button.h"
#include "views/controls/combobox/combobox.h"
#include "views/controls/label.h"
#include "views/controls/throbber.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"
#include "views/window/non_client_view.h"
#include "views/window/window.h"
#include "views/window/window_gtk.h"

using views::Background;
using views::Label;
using views::SmoothedThrobber;
using views::View;
using views::Widget;
using views::WidgetGtk;

namespace {

const int kWelcomeLabelY = 150;
const int kContinueButtonSpacingX = 30;
const int kSpacing = 25;
const int kHorizontalSpacing = 25;
const int kSelectionBoxWidthMin = 200;
const int kSelectionBoxHeight = 29;
const int kSelectionBoxSpacing = 7;

// Menu button is drawn using our custom icons in resources. See
// TextButtonBorder::Paint() for details. So this offset compensate
// horizontal size, eaten by those icons.
const int kMenuButtonHorizontalOffset = 1;

// Vertical addition to the menu window to make it appear exactly below
// MenuButton.
const int kMenuButtonVerticalOffset = 3;

const SkColor kWelcomeColor = 0xFF1D6AB1;

const int kThrobberFrameMs = 60;
const int kThrobberStartDelayMs = 500;

}  // namespace

namespace chromeos {

NetworkSelectionView::NetworkSelectionView(NetworkScreenDelegate* delegate)
    : network_combobox_(NULL),
      languages_menubutton_(NULL),
      welcome_label_(NULL),
      select_language_label_(NULL),
      select_network_label_(NULL),
      connecting_network_label_(NULL),
      continue_button_(NULL),
      throbber_(NULL),
      delegate_(delegate) {
}

NetworkSelectionView::~NetworkSelectionView() {
  network_combobox_->set_listener(NULL);
  network_combobox_ = NULL;
  throbber_->Stop();
  throbber_ = NULL;
}

void NetworkSelectionView::Init() {
  // Use rounded rect background.
  views::Painter* painter = CreateWizardPainter(
      &BorderDefinition::kScreenBorder);
  set_background(
      views::Background::CreateBackgroundPainter(true, painter));

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  gfx::Font welcome_label_font =
      rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD);

  welcome_label_ = new views::Label();
  welcome_label_->SetColor(kWelcomeColor);
  welcome_label_->SetFont(welcome_label_font);

  select_language_label_ = new views::Label();
  select_language_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));

  select_network_label_ = new views::Label();
  select_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));

  connecting_network_label_ = new views::Label();
  connecting_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
  connecting_network_label_->SetVisible(false);

  throbber_ = new views::SmoothedThrobber(kThrobberFrameMs);
  throbber_->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  throbber_->set_start_delay_ms(kThrobberStartDelayMs);
  AddChildView(throbber_);

  network_combobox_ = new views::Combobox(delegate_);
  network_combobox_->set_listener(delegate_);

  languages_menubutton_ = new views::MenuButton(
      NULL, std::wstring(), delegate_->language_switch_menu(), true);
  languages_menubutton_->SetFocusable(true);
  languages_menubutton_->SetNormalHasBorder(true);
  delegate_->language_switch_menu()->set_menu_offset(
      kMenuButtonHorizontalOffset, kMenuButtonVerticalOffset);

  AddChildView(welcome_label_);
  AddChildView(select_language_label_);
  AddChildView(select_network_label_);
  AddChildView(connecting_network_label_);
  AddChildView(languages_menubutton_);
  AddChildView(network_combobox_);

  UpdateLocalizedStrings();
}

void NetworkSelectionView::UpdateLocalizedStrings() {
  RecreateNativeControls();
  languages_menubutton_->SetText(
      delegate_->language_switch_menu()->GetCurrentLocaleName());
  welcome_label_->SetText(l10n_util::GetStringF(IDS_NETWORK_SELECTION_TITLE,
                          l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
  select_language_label_->SetText(
      l10n_util::GetString(IDS_LANGUAGE_SELECTION_SELECT));
  select_network_label_->SetText(
      l10n_util::GetString(IDS_NETWORK_SELECTION_SELECT));
  continue_button_->SetLabel(
      l10n_util::GetString(IDS_NETWORK_SELECTION_CONTINUE_BUTTON));
  UpdateConnectingNetworkLabel();
}

////////////////////////////////////////////////////////////////////////////////
// views::View: implementation:

void NetworkSelectionView::ChildPreferredSizeChanged(View* child) {
  Layout();
  SchedulePaint();
}

void NetworkSelectionView::LocaleChanged() {
  UpdateLocalizedStrings();
  NetworkModelChanged();
  // Explicitly set selected item - index 0 is a localized string.
  if (GetSelectedNetworkItem() <= 0 &&
      delegate_->GetItemCount() > 0) {
    SetSelectedNetworkItem(0);
  }
  Layout();
  SchedulePaint();
}

gfx::Size NetworkSelectionView::GetPreferredSize() {
  return gfx::Size(width(), height());
}

void NetworkSelectionView::Layout() {
  int y = kWelcomeLabelY;
  welcome_label_->SetBounds(
      (width() - welcome_label_->GetPreferredSize().width()) / 2,
      y,
      welcome_label_->GetPreferredSize().width(),
      welcome_label_->GetPreferredSize().height());
  y += welcome_label_->GetPreferredSize().height() + kSpacing;

  // Use menu preffered size to calculate boxes width accordingly.
  int box_width = delegate_->language_switch_menu()->GetFirstLevelMenuWidth() +
      kMenuButtonHorizontalOffset * 2;
  const int widest_label = std::max(
      select_language_label_->GetPreferredSize().width(),
      select_network_label_->GetPreferredSize().width());
  if (box_width < kSelectionBoxWidthMin) {
    box_width = kSelectionBoxWidthMin;
    delegate_->language_switch_menu()->SetFirstLevelMenuWidth(
        box_width - kMenuButtonHorizontalOffset * 2);
  } else if (widest_label + box_width + 2 * kHorizontalSpacing > width()) {
    box_width = width() - widest_label - 2 * kHorizontalSpacing;
  }
  const int labels_x = (width() - widest_label - box_width) / 2;
  select_language_label_->SetBounds(
      labels_x,
      y,
      select_language_label_->GetPreferredSize().width(),
      select_language_label_->GetPreferredSize().height());

  const int selection_box_x = labels_x + widest_label + kHorizontalSpacing;
  const int label_y_offset =
      (kSelectionBoxHeight -
       select_language_label_->GetPreferredSize().height()) / 2;
  languages_menubutton_->SetBounds(selection_box_x, y - label_y_offset,
                                   box_width, kSelectionBoxHeight);

  y += kSelectionBoxHeight + kSelectionBoxSpacing;
  select_network_label_->SetBounds(
      labels_x,
      y,
      select_network_label_->GetPreferredSize().width(),
      select_network_label_->GetPreferredSize().height());

  connecting_network_label_->SetBounds(
      kHorizontalSpacing,
      y,
      width() - kHorizontalSpacing * 2,
      connecting_network_label_->GetPreferredSize().height());

  throbber_->SetBounds(
      width() / 2 + connecting_network_label_->GetPreferredSize().width() / 2 +
          kHorizontalSpacing,
      y + (connecting_network_label_->GetPreferredSize().height() -
           throbber_->GetPreferredSize().height()) / 2,
      throbber_->GetPreferredSize().width(),
      throbber_->GetPreferredSize().height());

  network_combobox_->SetBounds(selection_box_x, y - label_y_offset,
                               box_width, kSelectionBoxHeight);

  y = height() - continue_button_->GetPreferredSize().height() - kSpacing;
  continue_button_->SetBounds(
      width() - kContinueButtonSpacingX -
          continue_button_->GetPreferredSize().width(),
      y,
      continue_button_->GetPreferredSize().width(),
      continue_button_->GetPreferredSize().height());

  // Need to refresh combobox layout explicitly.
  network_combobox_->Layout();
  continue_button_->Layout();
}

////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, public:

int NetworkSelectionView::GetSelectedNetworkItem() const {
  return network_combobox_->selected_item();
}

void NetworkSelectionView::SetSelectedNetworkItem(int index) {
  network_combobox_->SetSelectedItem(index);
}

gfx::NativeWindow NetworkSelectionView::GetNativeWindow() {
  return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
}

void NetworkSelectionView::NetworkModelChanged() {
  network_combobox_->ModelChanged();
}

void NetworkSelectionView::ShowConnectingStatus(bool connecting,
                                                const string16& network_id) {
  network_id_ = network_id;
  UpdateConnectingNetworkLabel();
  select_language_label_->SetVisible(!connecting);
  languages_menubutton_->SetVisible(!connecting);
  select_network_label_->SetVisible(!connecting);
  network_combobox_->SetVisible(!connecting);
  connecting_network_label_->SetVisible(connecting);
  Layout();
  if (connecting) {
    throbber_->Start();
  } else {
    throbber_->Stop();
  }
}

void NetworkSelectionView::EnableContinue(bool enabled) {
  if (continue_button_)
    continue_button_->SetEnabled(enabled);
}

////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, private:

void NetworkSelectionView::RecreateNativeControls() {
  // There is no way to get native button preferred size after the button was
  // sized so delete and recreate the button on text update.
  delete continue_button_;
  continue_button_ = new views::NativeButton(delegate_, std::wstring());
  continue_button_->SetEnabled(false);
  AddChildView(continue_button_);
}

void NetworkSelectionView::UpdateConnectingNetworkLabel() {
  connecting_network_label_->SetText(l10n_util::GetStringF(
      IDS_NETWORK_SELECTION_CONNECTING, UTF16ToWide(network_id_)));
}

}  // namespace chromeos
<commit_msg>Make welcome message multiline if needed.<commit_after>// Copyright (c) 2010 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 "chrome/browser/chromeos/login/network_selection_view.h"

#include <signal.h>
#include <sys/types.h>
#include <string>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/login/network_screen_delegate.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/native_button.h"
#include "views/controls/combobox/combobox.h"
#include "views/controls/label.h"
#include "views/controls/throbber.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"
#include "views/window/non_client_view.h"
#include "views/window/window.h"
#include "views/window/window_gtk.h"

using views::Background;
using views::Label;
using views::SmoothedThrobber;
using views::View;
using views::Widget;
using views::WidgetGtk;

namespace {

const int kWelcomeLabelY = 170;
const int kContinueButtonSpacingX = 30;
const int kSpacing = 25;
const int kHorizontalSpacing = 25;
const int kSelectionBoxWidthMin = 200;
const int kSelectionBoxHeight = 29;
const int kSelectionBoxSpacing = 7;

// Menu button is drawn using our custom icons in resources. See
// TextButtonBorder::Paint() for details. So this offset compensate
// horizontal size, eaten by those icons.
const int kMenuButtonHorizontalOffset = 1;

// Vertical addition to the menu window to make it appear exactly below
// MenuButton.
const int kMenuButtonVerticalOffset = 3;

const SkColor kWelcomeColor = 0xFF1D6AB1;

const int kThrobberFrameMs = 60;
const int kThrobberStartDelayMs = 500;

}  // namespace

namespace chromeos {

NetworkSelectionView::NetworkSelectionView(NetworkScreenDelegate* delegate)
    : network_combobox_(NULL),
      languages_menubutton_(NULL),
      welcome_label_(NULL),
      select_language_label_(NULL),
      select_network_label_(NULL),
      connecting_network_label_(NULL),
      continue_button_(NULL),
      throbber_(NULL),
      delegate_(delegate) {
}

NetworkSelectionView::~NetworkSelectionView() {
  network_combobox_->set_listener(NULL);
  network_combobox_ = NULL;
  throbber_->Stop();
  throbber_ = NULL;
}

void NetworkSelectionView::Init() {
  // Use rounded rect background.
  views::Painter* painter = CreateWizardPainter(
      &BorderDefinition::kScreenBorder);
  set_background(
      views::Background::CreateBackgroundPainter(true, painter));

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  gfx::Font welcome_label_font =
      rb.GetFont(ResourceBundle::LargeFont).DeriveFont(0, gfx::Font::BOLD);

  welcome_label_ = new views::Label();
  welcome_label_->SetColor(kWelcomeColor);
  welcome_label_->SetFont(welcome_label_font);
  welcome_label_->SetMultiLine(true);

  select_language_label_ = new views::Label();
  select_language_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));

  select_network_label_ = new views::Label();
  select_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));

  connecting_network_label_ = new views::Label();
  connecting_network_label_->SetFont(rb.GetFont(ResourceBundle::MediumFont));
  connecting_network_label_->SetVisible(false);

  throbber_ = new views::SmoothedThrobber(kThrobberFrameMs);
  throbber_->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  throbber_->set_start_delay_ms(kThrobberStartDelayMs);
  AddChildView(throbber_);

  network_combobox_ = new views::Combobox(delegate_);
  network_combobox_->set_listener(delegate_);

  languages_menubutton_ = new views::MenuButton(
      NULL, std::wstring(), delegate_->language_switch_menu(), true);
  languages_menubutton_->SetFocusable(true);
  languages_menubutton_->SetNormalHasBorder(true);
  delegate_->language_switch_menu()->set_menu_offset(
      kMenuButtonHorizontalOffset, kMenuButtonVerticalOffset);

  AddChildView(welcome_label_);
  AddChildView(select_language_label_);
  AddChildView(select_network_label_);
  AddChildView(connecting_network_label_);
  AddChildView(languages_menubutton_);
  AddChildView(network_combobox_);

  UpdateLocalizedStrings();
}

void NetworkSelectionView::UpdateLocalizedStrings() {
  RecreateNativeControls();
  languages_menubutton_->SetText(
      delegate_->language_switch_menu()->GetCurrentLocaleName());
  welcome_label_->SetText(l10n_util::GetStringF(IDS_NETWORK_SELECTION_TITLE,
                          l10n_util::GetString(IDS_PRODUCT_OS_NAME)));
  select_language_label_->SetText(
      l10n_util::GetString(IDS_LANGUAGE_SELECTION_SELECT));
  select_network_label_->SetText(
      l10n_util::GetString(IDS_NETWORK_SELECTION_SELECT));
  continue_button_->SetLabel(
      l10n_util::GetString(IDS_NETWORK_SELECTION_CONTINUE_BUTTON));
  UpdateConnectingNetworkLabel();
}

////////////////////////////////////////////////////////////////////////////////
// views::View: implementation:

void NetworkSelectionView::ChildPreferredSizeChanged(View* child) {
  Layout();
  SchedulePaint();
}

void NetworkSelectionView::LocaleChanged() {
  UpdateLocalizedStrings();
  NetworkModelChanged();
  // Explicitly set selected item - index 0 is a localized string.
  if (GetSelectedNetworkItem() <= 0 &&
      delegate_->GetItemCount() > 0) {
    SetSelectedNetworkItem(0);
  }
  Layout();
  SchedulePaint();
}

gfx::Size NetworkSelectionView::GetPreferredSize() {
  return gfx::Size(width(), height());
}

void NetworkSelectionView::Layout() {
  gfx::Insets insets = GetInsets();
  int max_width = this->width() - insets.width() - 2 * kHorizontalSpacing;
  welcome_label_->SizeToFit(max_width);
  int y = kWelcomeLabelY;
  y -= welcome_label_->GetPreferredSize().height() / 2;

  welcome_label_->SetBounds(
      (width() - welcome_label_->GetPreferredSize().width()) / 2,
      y,
      welcome_label_->GetPreferredSize().width(),
      welcome_label_->GetPreferredSize().height());
  y += welcome_label_->GetPreferredSize().height() + kSpacing;

  // Use menu preffered size to calculate boxes width accordingly.
  int box_width = delegate_->language_switch_menu()->GetFirstLevelMenuWidth() +
      kMenuButtonHorizontalOffset * 2;
  const int widest_label = std::max(
      select_language_label_->GetPreferredSize().width(),
      select_network_label_->GetPreferredSize().width());
  if (box_width < kSelectionBoxWidthMin) {
    box_width = kSelectionBoxWidthMin;
    delegate_->language_switch_menu()->SetFirstLevelMenuWidth(
        box_width - kMenuButtonHorizontalOffset * 2);
  } else if (widest_label + box_width + 2 * kHorizontalSpacing > width()) {
    box_width = width() - widest_label - 2 * kHorizontalSpacing;
  }
  const int labels_x = (width() - widest_label - box_width) / 2;
  select_language_label_->SetBounds(
      labels_x,
      y,
      select_language_label_->GetPreferredSize().width(),
      select_language_label_->GetPreferredSize().height());

  const int selection_box_x = labels_x + widest_label + kHorizontalSpacing;
  const int label_y_offset =
      (kSelectionBoxHeight -
       select_language_label_->GetPreferredSize().height()) / 2;
  languages_menubutton_->SetBounds(selection_box_x, y - label_y_offset,
                                   box_width, kSelectionBoxHeight);

  y += kSelectionBoxHeight + kSelectionBoxSpacing;
  select_network_label_->SetBounds(
      labels_x,
      y,
      select_network_label_->GetPreferredSize().width(),
      select_network_label_->GetPreferredSize().height());

  connecting_network_label_->SetBounds(
      kHorizontalSpacing,
      y,
      width() - kHorizontalSpacing * 2,
      connecting_network_label_->GetPreferredSize().height());

  throbber_->SetBounds(
      width() / 2 + connecting_network_label_->GetPreferredSize().width() / 2 +
          kHorizontalSpacing,
      y + (connecting_network_label_->GetPreferredSize().height() -
           throbber_->GetPreferredSize().height()) / 2,
      throbber_->GetPreferredSize().width(),
      throbber_->GetPreferredSize().height());

  network_combobox_->SetBounds(selection_box_x, y - label_y_offset,
                               box_width, kSelectionBoxHeight);

  y = height() - continue_button_->GetPreferredSize().height() - kSpacing;
  continue_button_->SetBounds(
      width() - kContinueButtonSpacingX -
          continue_button_->GetPreferredSize().width(),
      y,
      continue_button_->GetPreferredSize().width(),
      continue_button_->GetPreferredSize().height());

  // Need to refresh combobox layout explicitly.
  network_combobox_->Layout();
  continue_button_->Layout();
}

////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, public:

int NetworkSelectionView::GetSelectedNetworkItem() const {
  return network_combobox_->selected_item();
}

void NetworkSelectionView::SetSelectedNetworkItem(int index) {
  network_combobox_->SetSelectedItem(index);
}

gfx::NativeWindow NetworkSelectionView::GetNativeWindow() {
  return GTK_WINDOW(static_cast<WidgetGtk*>(GetWidget())->GetNativeView());
}

void NetworkSelectionView::NetworkModelChanged() {
  network_combobox_->ModelChanged();
}

void NetworkSelectionView::ShowConnectingStatus(bool connecting,
                                                const string16& network_id) {
  network_id_ = network_id;
  UpdateConnectingNetworkLabel();
  select_language_label_->SetVisible(!connecting);
  languages_menubutton_->SetVisible(!connecting);
  select_network_label_->SetVisible(!connecting);
  network_combobox_->SetVisible(!connecting);
  connecting_network_label_->SetVisible(connecting);
  Layout();
  if (connecting) {
    throbber_->Start();
  } else {
    throbber_->Stop();
  }
}

void NetworkSelectionView::EnableContinue(bool enabled) {
  if (continue_button_)
    continue_button_->SetEnabled(enabled);
}

////////////////////////////////////////////////////////////////////////////////
// NetworkSelectionView, private:

void NetworkSelectionView::RecreateNativeControls() {
  // There is no way to get native button preferred size after the button was
  // sized so delete and recreate the button on text update.
  delete continue_button_;
  continue_button_ = new views::NativeButton(delegate_, std::wstring());
  continue_button_->SetEnabled(false);
  AddChildView(continue_button_);
}

void NetworkSelectionView::UpdateConnectingNetworkLabel() {
  connecting_network_label_->SetText(l10n_util::GetStringF(
      IDS_NETWORK_SELECTION_CONNECTING, UTF16ToWide(network_id_)));
}

}  // namespace chromeos
<|endoftext|>


<commit_before>#include <map>
#include <string>
#include <list>
#include <functional>
#include <algorithm>
#include "boost\crc.hpp"
#include "boost\format\free_funcs.hpp"

#ifndef __CONSISTENT_HASH_H__
#define __CONSISTENT_HASH_H__

//ڵ
class NFIVirtualNode
{
public:

    //IPĵڼڵ
    NFIVirtualNode(const int nVirID)
        :nVirtualIndex(nVirID)
    {

    }

	NFIVirtualNode()
	{
		nVirtualIndex = 0;
	}

	virtual ~NFIVirtualNode()
	{
		nVirtualIndex = 0;
	}

	virtual std::string GetDataStr() = 0;

    std::string ToStr() const
    {
        return boost::str(boost::format("%1%-%2%") % GetDataStr() % nVirtualIndex);
    }

private:

    int nVirtualIndex;//ڵ
};

class NFCMachineNode : public NFIVirtualNode
{
	NFCMachineNode(const int nVirID) : NFIVirtualNode(nVirID)
	{
		strIP = "";
		nPort = 0;
		nWeight = 0;//ܹȨؼǶڵ
		nMachineID = 0;
	}

	NFCMachineNode()
	{
		strIP = "";
		nPort = 0;
		nWeight = 0;//ܹȨؼǶڵ
		nMachineID = 0;
	}

	virtual std::string GetDataStr()
	{
		return strIP;
	}

	std::string strIP;
	int nPort;
	int nWeight;
	int nMachineID;
};

class NFIHasher
{
public:
    virtual uint32_t GetHashValue(const NFIVirtualNode& vNode) = 0;
};

class NFCHasher : public NFIHasher
{
public:
    virtual uint32_t GetHashValue(const NFIVirtualNode& vNode)
    {
        boost::crc_32_type ret;
        std::string vnode = vNode.ToStr();
        ret.process_bytes(vnode.c_str(), vnode.size());

        return ret.checksum();
    }
};

class NFCConsistentHash
{
public:

public:

    NFCConsistentHash()
    {
        m_pHasher = new NFCHasher();
    }

    virtual ~NFCConsistentHash()
    {
        delete m_pHasher;
        m_pHasher = NULL;
    }

public:
    std::size_t Size() const
    {
        return mxNodes.size();
    }

    bool Empty() const
    {
        return mxNodes.empty();
    }

    void Insert(const NFIVirtualNode& xNode)
    {
        uint32_t hash = m_pHasher->GetHashValue(xNode);
        auto it = mxNodes.find(hash);
        if (it == mxNodes.end())
        {
            mxNodes.insert(TMAP_TYPE::value_type(hash,xNode));
        }
    }

    std::size_t Erase(const NFIVirtualNode& xNode)
    {
        uint32_t hash = m_pHasher->GetHashValue(xNode);
        return mxNodes.erase(hash);
    }

	bool SuitNode(uint32_t hashValue, NFIVirtualNode& node)
	{
		if(mxNodes.empty())
		{
			return false;
		}

		TMAP_TYPE::iterator it = mxNodes.lower_bound(hashValue);

		if (it == mxNodes.end())
		{
			it = mxNodes.begin();
		}

		node = it->second;

		return true;
	}
private:
	typedef std::map<uint32_t, NFIVirtualNode> TMAP_TYPE;
	typedef TMAP_TYPE::iterator iterator;

    NFIHasher* m_pHasher;
    TMAP_TYPE mxNodes;
};

#endif
<commit_msg>modified consistent hash<commit_after>#include <map>
#include <string>
#include <list>
#include <functional>
#include <algorithm>
#include "boost/crc.hpp"
#include "boost/format/free_funcs.hpp"

#ifndef __CONSISTENT_HASH_H__
#define __CONSISTENT_HASH_H__

//ڵ
class NFIVirtualNode
{
public:

    //IPĵڼڵ
    NFIVirtualNode(const int nVirID)
        :nVirtualIndex(nVirID)
    {

    }

	NFIVirtualNode()
	{
		nVirtualIndex = 0;
	}

	virtual ~NFIVirtualNode()
	{
		nVirtualIndex = 0;
	}

	virtual std::string GetDataStr() = 0;

    std::string ToStr() const
    {
        return boost::str(boost::format("%1%-%2%") % GetDataStr() % nVirtualIndex);
    }

private:

    int nVirtualIndex;//ڵ
};

class NFCMachineNode : public NFIVirtualNode
{
	NFCMachineNode(const int nVirID) : NFIVirtualNode(nVirID)
	{
		strIP = "";
		nPort = 0;
		nWeight = 0;//ܹȨؼǶڵ
		nMachineID = 0;
	}

	NFCMachineNode()
	{
		strIP = "";
		nPort = 0;
		nWeight = 0;//ܹȨؼǶڵ
		nMachineID = 0;
	}

	virtual std::string GetDataStr()
	{
		return strIP;
	}

	std::string strIP;
	int nPort;
	int nWeight;
	int nMachineID;
};

class NFIHasher
{
public:
    virtual uint32_t GetHashValue(const NFIVirtualNode& vNode) = 0;
};

class NFCHasher : public NFIHasher
{
public:
    virtual uint32_t GetHashValue(const NFIVirtualNode& vNode)
    {
        boost::crc_32_type ret;
        std::string vnode = vNode.ToStr();
        ret.process_bytes(vnode.c_str(), vnode.size());

        return ret.checksum();
    }
};

class NFCConsistentHash
{
public:

public:

    NFCConsistentHash()
    {
        m_pHasher = new NFCHasher();
    }

    virtual ~NFCConsistentHash()
    {
        delete m_pHasher;
        m_pHasher = NULL;
    }

public:
    std::size_t Size() const
    {
        return mxNodes.size();
    }

    bool Empty() const
    {
        return mxNodes.empty();
    }

    void Insert(const NFIVirtualNode& xNode)
    {
        uint32_t hash = m_pHasher->GetHashValue(xNode);
        auto it = mxNodes.find(hash);
        if (it == mxNodes.end())
        {
            mxNodes.insert(TMAP_TYPE::value_type(hash,xNode));
        }
    }

    std::size_t Erase(const NFIVirtualNode& xNode)
    {
        uint32_t hash = m_pHasher->GetHashValue(xNode);
        return mxNodes.erase(hash);
    }

	bool SuitNode(uint32_t hashValue, NFIVirtualNode& node)
	{
		if(mxNodes.empty())
		{
			return false;
		}

		TMAP_TYPE::iterator it = mxNodes.lower_bound(hashValue);

		if (it == mxNodes.end())
		{
			it = mxNodes.begin();
		}

		node = it->second;

		return true;
	}
private:
	typedef std::map<uint32_t, NFIVirtualNode> TMAP_TYPE;
	typedef TMAP_TYPE::iterator iterator;

    NFIHasher* m_pHasher;
    TMAP_TYPE mxNodes;
};

#endif
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " | " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " | " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<commit_msg>log bug fix<commit_after>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " | " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " | " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), stream.str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), stream.str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<|endoftext|>


<commit_before>#pragma sw require header org.sw.demo.google.protobuf.protoc
#pragma sw require header org.sw.demo.qtproject.qt.base.tools.moc-5

#define QT_VERSION "-5"

/*void configure(Build &s)
{
    if (s.isConfigSelected("mt"))
    {
        auto ss = s.createSettings();
        ss.Native.LibrariesType = LibraryType::Static;
        ss.Native.MT = true;
        s.addSettings(ss);
    }
}*/

void build(Solution &s)
{
    auto &aspia = s.addProject("aspia", "master");
    aspia += Git("https://github.com/dchapyshev/aspia", "", "{v}");

    constexpr auto cppstd = cpp17;

    auto setup_target = [&aspia](auto &t, const String &name, bool add_tests = false, String dir = {}) -> decltype(auto)
    {
        if (dir.empty())
            dir = name;

        t += cppstd;
        t.Public += "."_idir;
        t.setRootDirectory(dir);
        t += IncludeDirectory("."s);
        t += ".*"_rr;

        //
        t.AllowEmptyRegexes = true;

        // os specific
        t -= ".*_win.*"_rr;
        t -= ".*_linux.*"_rr;
        t -= ".*/linux/.*"_rr;
        t -= ".*_pulse.*"_rr;
        t -= ".*_mac.*"_rr;
        t -= ".*_posix.*"_rr;
        t -= ".*_x11.*"_rr;
        if (t.getBuildSettings().TargetOS.Type == OSType::Windows)
            t += ".*_win.*"_rr;
        else if (t.getBuildSettings().TargetOS.isApple())
            t += ".*_mac.*"_rr;
        else
        {
            t += ".*_pulse.*"_rr;
            t += ".*_linux.*"_rr;
            t += ".*/linux/.*"_rr;
            t += ".*_x11.*"_rr;
        }
        if (t.getBuildSettings().TargetOS.Type != OSType::Windows)
            t += ".*_posix.*"_rr;

        t -= ".*_unittest.*"_rr;
        t -= ".*tests.*"_rr;

        //
        t.AllowEmptyRegexes = false;

        // test
        if (add_tests)
        {
            auto &bt = t.addExecutable("test");
            bt += cppstd;
            bt += FileRegex(dir, ".*_unittest.*", true);
            bt += t;
            bt += "org.sw.demo.google.googletest.gmock"_dep;
            bt += "org.sw.demo.google.googletest.gtest.main"_dep;
            t.addTest(bt);
        }

        return t;
    };

    auto add_lib = [&aspia, &setup_target](const String &name, bool add_tests = false, String dir = {}) -> decltype(auto)
    {
        return setup_target(aspia.addStaticLibrary(name), name, add_tests, dir);
    };

    auto &protocol = aspia.addStaticLibrary("proto");
    protocol += "proto/.*\\.proto"_rr;
    for (const auto &[p, _] : protocol[FileRegex(protocol.SourceDir / "proto", ".*\\.proto", false)])
    {
        ProtobufData d;
        d.outdir = protocol.BinaryDir / "proto";
        d.public_protobuf = true;
        d.addIncludeDirectory(protocol.SourceDir / "proto");
        gen_protobuf_cpp("org.sw.demo.google.protobuf"_dep, protocol, p, d);
    }

    auto &base = aspia.addStaticLibrary("base");
    base += "third_party/modp_b64/.*\\.[hc]"_rr;
    base += "third_party/x11region/.*\\.[hc]"_rr;
    base += "third_party/tbb_c_allocator/.*"_rr;
    base -= "build/.*"_rr;
    setup_target(base, "base", false);
    base.Public += "UNICODE"_def;
    base.Public += "WIN32_LEAN_AND_MEAN"_def;
    base.Public += "NOMINMAX"_def;
    base.Public += protocol;
    base.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
    base.Public += "org.sw.demo.qtproject.qt.base.network" QT_VERSION ""_dep;
    base.Public += "org.sw.demo.qtproject.qt.base.xml" QT_VERSION ""_dep;
    base.Public += "org.sw.demo.boost.align"_dep;
    base.Public += "org.sw.demo.imneme.pcg_cpp-master"_dep;
    base.Public += "org.sw.demo.chriskohlhoff.asio"_dep;
    base.Public += "org.sw.demo.rapidxml"_dep;
    base.Public += "org.sw.demo.miloyip.rapidjson"_dep;
    base.Public += "org.sw.demo.google.protobuf.protobuf"_dep; // should be protobuf_lite actually?
    base.Public += "org.sw.demo.chromium.libyuv-master"_dep;
    base.Public += "org.sw.demo.webmproject.vpx"_dep;
    base.Public += "org.sw.demo.webmproject.webm"_dep;
    base.Public += "org.sw.demo.xiph.opus"_dep;
    if (base.getBuildSettings().TargetOS.Type == OSType::Windows)
    {
        base -= "x11/.*"_rr;
        base.Public += "com.Microsoft.Windows.SDK.winrt"_dep;
        base +=
            "Dbghelp.lib"_slib,
            "Mswsock.lib"_slib,
            "Avrt.lib"_slib,
            "comsuppw.lib"_slib,
            "Winspool.lib"_slib,
            "Setupapi.lib"_slib
            ;
    }
    automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, base);

    auto &relay = aspia.addExecutable("relay");
    relay += cppstd;
    relay += "relay/.*"_rr;
    relay += base;

    auto &router = aspia.addExecutable("router");
    router += cppstd;
    router += "router/.*"_rr;
    router += base;
    router += "org.sw.demo.sqlite3"_dep;

    auto qt_progs = [](auto &t, const String &name_override = {}, const path &path_override = {})
    {
        auto name = name_override.empty() ? t.getPackage().getPath().back() : name_override;

        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, t);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t, t.SourceDir / path_override / ("resources/" + name + ".qrc"));
        qt_uic("org.sw.demo.qtproject.qt.base.tools.uic" QT_VERSION ""_dep, t);
    };

    auto qt_progs2 = [](auto &t)
    {
        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, t);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t, t.SourceDir / "ui/resources.qrc");
        qt_uic("org.sw.demo.qtproject.qt.base.tools.uic" QT_VERSION ""_dep, t);
    };

    auto qt_progs_and_tr = [&qt_progs](auto &t, const String &name_override = {}, const path &path_override = {})
    {
        auto name = name_override.empty() ? t.getPackage().getPath().back() : name_override;

        qt_progs(t, name_override, path_override);

        // trs
        qt_tr("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, t);
        t.configureFile(t.SourceDir / path_override / ("translations/" + name + "_translations.qrc"),
            t.BinaryDir / (name + "_translations.qrc"), ConfigureFlags::CopyOnly);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t,
            t.BinaryDir / (name + "_translations.qrc"))
            ->working_directory = t.BinaryDir;
    };

    auto qt_progs_and_tr2 = [&qt_progs2](auto &t)
    {
        qt_progs2(t);

        // trs
        qt_tr("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, t);
        t.configureFile(t.SourceDir / "ui/translations.qrc",
            t.BinaryDir / "translations.qrc", ConfigureFlags::CopyOnly);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t,
            t.BinaryDir / "translations.qrc")->working_directory = t.BinaryDir;
    };

    auto &common = add_lib("common");
    if (common.getBuildSettings().TargetOS.Type == OSType::Windows)
    {
        common -= "file_enumerator_fs.cc";
        common.Public += "Shlwapi.lib"_slib;
    }
    common.Public += base, protocol;
    common.Public += "org.sw.demo.openssl.crypto"_dep;
    common.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
    common.Public += "org.sw.demo.qtproject.qt.winextras" QT_VERSION ""_dep;
    qt_progs_and_tr(common);

    auto &qt_base = add_lib("qt_base");
    qt_base.Public += base;
    qt_base.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
    automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, qt_base);
    qt_translations_rcc("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, aspia, qt_base, "qt_translations.qrc");

    auto setup_exe = [](auto &t) -> decltype(auto)
    {
        if (auto L = t.getSelectedTool()->template as<VisualStudioLinker*>(); L)
            L->Subsystem = vs::Subsystem::Windows;
        t += "org.sw.demo.qtproject.qt.base.winmain" QT_VERSION ""_dep;
        return t;
    };

    //
    auto &client_core = add_lib("client");
    client_core.Public += common;
    if (client_core.getBuildSettings().TargetOS.Type == OSType::Windows)
        client_core.Public += "org.sw.demo.qtproject.qt.base.plugins.printsupport.windows" QT_VERSION ""_dep;
    qt_progs_and_tr(client_core);

    auto add_exe = [&setup_exe](auto &base, const String &name) -> decltype(auto)
    {
        return setup_exe(base.addExecutable(name));
    };

    //
    auto &console = add_exe(aspia, "console");
    setup_target(console, "console");
    console.Public += client_core, qt_base;
    if (console.getBuildSettings().TargetOS.Type == OSType::Windows)
    {
        console.Public += "org.sw.demo.qtproject.qt.base.plugins.platforms.windows" QT_VERSION ""_dep;
        console.Public += "org.sw.demo.qtproject.qt.base.plugins.styles.windowsvista" QT_VERSION ""_dep;
    }
    qt_progs_and_tr(console);

    auto &host = aspia.addExecutable("host");
    auto &core = host.addSharedLibrary("core");
    setup_target(core, "host");
    core -= ".*_entry_point.cc"_rr, ".*\\.rc"_rr;
    core += "HOST_IMPLEMENTATION"_def;
    if (core.getBuildSettings().TargetOS.Type == OSType::Windows)
        core.Public += "sas.lib"_slib;
    core.Public += common, qt_base;
    core.Public += "org.sw.demo.boost.property_tree"_dep;
    core.Public += "org.sw.demo.qtproject.qt.base.plugins.platforms.windows" QT_VERSION ""_dep;
    core.Public += "org.sw.demo.qtproject.qt.base.plugins.styles.windowsvista" QT_VERSION ""_dep;
    qt_progs_and_tr2(core);

    setup_exe(host);
    host += "host/ui/host_entry_point.cc";
    host += "host/ui/host.rc";
    host += core;

    auto &service = add_exe(host, "service");
    service += "host/win/service_entry_point.cc";
    service += "host/win/service.rc";
    service += core;

    auto &desktop_agent = add_exe(aspia, "desktop_agent");
    desktop_agent += "host/desktop_agent_entry_point.cc";
    desktop_agent += "host/desktop_agent.rc";
    desktop_agent += core;

    auto &client = add_exe(aspia, "client_exe");
    client += "client/client_entry_point.cc";
    client += "client/client.rc";
    client += client_core, qt_base;
}
<commit_msg>[sw] Initial linux build.<commit_after>#pragma sw require header org.sw.demo.google.protobuf.protoc
#pragma sw require header org.sw.demo.qtproject.qt.base.tools.moc-6

#define QT_VERSION "-6"

/*void configure(Build &s)
{
    if (s.isConfigSelected("mt"))
    {
        auto ss = s.createSettings();
        ss.Native.LibrariesType = LibraryType::Static;
        ss.Native.MT = true;
        s.addSettings(ss);
    }
}*/

void build(Solution &s) {
    auto &aspia = s.addProject("aspia", "master");
    aspia += Git("https://github.com/dchapyshev/aspia", "", "{v}");

    constexpr auto cppstd = cpp17;

    auto setup_target = [&](auto &t, const String &name, bool add_tests = false, String dir = {}) -> decltype(auto) {
        if (dir.empty())
            dir = name;

        t += cppstd;
        t.Public += "."_idir;
        t.setRootDirectory(dir);
        t += IncludeDirectory("."s);
        t += ".*"_rr;

        //
        t.AllowEmptyRegexes = true;

        // os specific
        t -= ".*_win\\..*"_rr;
        t -= ".*/win/.*"_rr;
        t -= ".*_linux.*"_rr;
        t -= ".*/linux/.*"_rr;
        t -= ".*_pulse.*"_rr;
        t -= ".*_mac.*"_rr;
        t -= ".*_posix.*"_rr;
        t -= ".*_x11.*"_rr;
        if (t.getBuildSettings().TargetOS.Type == OSType::Windows) {
            t += ".*_win.*"_rr;
            t += ".*/win/.*"_rr;
        } else if (t.getBuildSettings().TargetOS.isApple()) {
            t += ".*_mac.*"_rr;
        } else         {
            t += ".*_pulse.*"_rr;
            t += ".*_linux.*"_rr;
            t += ".*/linux/.*"_rr;
            t += ".*_x11.*"_rr;
        }
        if (t.getBuildSettings().TargetOS.Type != OSType::Windows) {
            t.ExportAllSymbols = true;
            t += ".*_posix.*"_rr;
        }

        t -= ".*_unittest.*"_rr;
        t -= ".*tests.*"_rr;

        //
        t.AllowEmptyRegexes = false;

        // test
        if (add_tests) {
            auto &bt = t.addExecutable("test");
            bt += cppstd;
            bt += FileRegex(dir, ".*_unittest.*", true);
            bt += t;
            bt += "org.sw.demo.google.googletest.gmock"_dep;
            bt += "org.sw.demo.google.googletest.gtest.main"_dep;
            t.addTest(bt);
        }

        return t;
    };

    auto add_lib = [&aspia, &setup_target](const String &name, bool add_tests = false, String dir = {}) -> decltype(auto) {
        return setup_target(aspia.addStaticLibrary(name), name, add_tests, dir);
    };

    auto &protocol = aspia.addStaticLibrary("proto");
    protocol += "proto/.*\\.proto"_rr;
    for (const auto &[p, _] : protocol[FileRegex(protocol.SourceDir / "proto", ".*\\.proto", false)]) {
        ProtobufData d;
        d.outdir = protocol.BinaryDir / "proto";
        d.public_protobuf = true;
        d.addIncludeDirectory(protocol.SourceDir / "proto");
        gen_protobuf_cpp("org.sw.demo.google.protobuf"_dep, protocol, p, d);
    }

    auto &base = aspia.addStaticLibrary("base");
    {
        base += "third_party/modp_b64/.*\\.[hc]"_rr;
        base += "third_party/x11region/.*\\.[hc]"_rr;
        base -= "third_party/xdg_user_dirs/.*"_rr;
        if (base.getBuildSettings().TargetOS.Type == OSType::Linux)
            base += "third_party/xdg_user_dirs/.*"_rr;
        base += "third_party/tbb_c_allocator/.*"_rr;
        base -= "build/.*"_rr;
        setup_target(base, "base", false);
        if (base.getBuildSettings().TargetOS.Type == OSType::Windows) {
            base.Public += "UNICODE"_def;
            base.Public += "WIN32_LEAN_AND_MEAN"_def;
            base.Public += "NOMINMAX"_def;
        }
        base.Public += protocol;
        base.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
        base.Public += "org.sw.demo.qtproject.qt.base.network" QT_VERSION ""_dep;
        base.Public += "org.sw.demo.qtproject.qt.base.xml" QT_VERSION ""_dep;
        base.Public += "org.sw.demo.boost.align"_dep;
        base.Public += "org.sw.demo.imneme.pcg_cpp-master"_dep;
        base.Public += "org.sw.demo.chriskohlhoff.asio"_dep;
        base.Public += "org.sw.demo.rapidxml"_dep;
        base.Public += "org.sw.demo.miloyip.rapidjson"_dep;
        base.Public += "org.sw.demo.google.protobuf.protobuf"_dep; // should be protobuf_lite actually?
        base.Public += "org.sw.demo.chromium.libyuv-master"_dep;
        base.Public += "org.sw.demo.webmproject.vpx"_dep;
        base.Public += "org.sw.demo.webmproject.webm"_dep;
        base.Public += "org.sw.demo.xiph.opus"_dep;
        if (base.getBuildSettings().TargetOS.Type == OSType::Windows) {
            base.Public += "com.Microsoft.Windows.SDK.winrt"_dep;
            base +=
                "Dbghelp.lib"_slib,
                "Mswsock.lib"_slib,
                "Avrt.lib"_slib,
                "comsuppw.lib"_slib,
                "Winspool.lib"_slib,
                "Setupapi.lib"_slib
                ;
        } else {
            base -= "win/.*"_rr;
            base -= "desktop/frame_dib.cc";
            base -= "desktop/screen_capturer_dxgi.cc";
            base -= "desktop/screen_capturer_wrapper.cc";
            base -= "desktop/screen_capturer_mirror.cc";
            base -= "desktop/screen_capturer_gdi.cc";
            base -= "net/connect_enumerator.cc";
            base -= "net/firewall_manager.cc";
            base -= "net/route_enumerator.cc";
            base += "X11"_slib;
            base += "Xext"_slib;
            //base += "Xdamage"_slib;
            base += "Xfixes"_slib;
            base += "Xtst"_slib;
        }
        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, base);
    }

    auto &relay = aspia.addExecutable("relay");
    {
        relay += cppstd;
        relay -= "relay/.*"_rr;
        relay += "relay/.*"_r;
        if (relay.getBuildSettings().TargetOS.Type == OSType::Windows) {
            relay += "relay/win/.*"_rr;
        } else if (relay.getBuildSettings().TargetOS.Type == OSType::Linux) {
            relay += "relay/linux/.*"_rr;
        }
        relay += base;
    }

    auto &router = aspia.addExecutable("router");
    {
        router += cppstd;
        router -= "router/.*"_rr;
        router += "router/.*"_r;
        if (router.getBuildSettings().TargetOS.Type == OSType::Windows) {
            router += "router/win/.*"_rr;
        } else if (router.getBuildSettings().TargetOS.Type == OSType::Linux) {
            router += "router/linux/.*"_rr;
        }
        router += base;
        router += "org.sw.demo.sqlite3"_dep;
    }

    auto qt_progs = [](auto &t, const String &name_override = {}, const path &path_override = {}) {
        auto name = name_override.empty() ? t.getPackage().getPath().back() : name_override;
        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, t);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t, t.SourceDir / path_override / ("resources/" + name + ".qrc"));
        qt_uic("org.sw.demo.qtproject.qt.base.tools.uic" QT_VERSION ""_dep, t);
    };

    auto qt_progs2 = [](auto &t) {
        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, t);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t, t.SourceDir / "ui/resources.qrc");
        qt_uic("org.sw.demo.qtproject.qt.base.tools.uic" QT_VERSION ""_dep, t);
    };

    auto qt_progs_and_tr = [&qt_progs](auto &t, const String &name_override = {}, const path &path_override = {}) {
        auto name = name_override.empty() ? t.getPackage().getPath().back() : name_override;

        qt_progs(t, name_override, path_override);

        // trs
        qt_tr("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, t);
        t.configureFile(t.SourceDir / path_override / ("translations/" + name + "_translations.qrc"),
            t.BinaryDir / (name + "_translations.qrc"), ConfigureFlags::CopyOnly);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t,
            t.BinaryDir / (name + "_translations.qrc"))
            ->working_directory = t.BinaryDir;
    };

    auto qt_progs_and_tr2 = [&qt_progs2](auto &t) {
        qt_progs2(t);
        // trs
        qt_tr("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, t);
        t.configureFile(t.SourceDir / "ui/translations.qrc",
            t.BinaryDir / "translations.qrc", ConfigureFlags::CopyOnly);
        rcc("org.sw.demo.qtproject.qt.base.tools.rcc" QT_VERSION ""_dep, t,
            t.BinaryDir / "translations.qrc")->working_directory = t.BinaryDir;
    };

    auto &common = add_lib("common");
    {
        if (common.getBuildSettings().TargetOS.Type == OSType::Windows) {
            common -= "file_enumerator_fs.cc";
            common.Public += "Shlwapi.lib"_slib;
        }
        common.Public += base, protocol;
        common.Public += "org.sw.demo.openssl.crypto"_dep;
        common.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
        if (common.getBuildSettings().TargetOS.Type == OSType::Windows) {
            common.Public += "org.sw.demo.qtproject.qt.winextras" QT_VERSION ""_dep;
        }
        qt_progs_and_tr(common);
    }

    auto &qt_base = add_lib("qt_base");
    {
        qt_base.Public += base;
        qt_base.Public += "org.sw.demo.qtproject.qt.base.widgets" QT_VERSION ""_dep;
        automoc("org.sw.demo.qtproject.qt.base.tools.moc" QT_VERSION ""_dep, qt_base);
        qt_translations_rcc("org.sw.demo.qtproject.qt" QT_VERSION ""_dep, aspia, qt_base, "qt_translations.qrc");
    }

    auto setup_exe = [](auto &t) -> decltype(auto) {
        if (t.getBuildSettings().TargetOS.Type == OSType::Windows) {
            if (auto L = t.getSelectedTool()->template as<VisualStudioLinker*>(); L)
                L->Subsystem = vs::Subsystem::Windows;
            t += "org.sw.demo.qtproject.qt.base.winmain" QT_VERSION ""_dep;
        }
        return t;
    };

    //
    auto &client_core = add_lib("client");
    {
        client_core += ".*"_rr;
        client_core.Public += common;
        client_core.Public += "org.sw.demo.qtproject.qt.base.printsupport" QT_VERSION ""_dep;
        if (client_core.getBuildSettings().TargetOS.Type == OSType::Windows)
            client_core.Public += "org.sw.demo.qtproject.qt.base.plugins.printsupport.windows" QT_VERSION ""_dep;
        else if (client_core.getBuildSettings().TargetOS.Type == OSType::Linux)
            client_core.Public += "org.sw.demo.qtproject.qt.base.plugins.printsupport.cups" QT_VERSION ""_dep;
        qt_progs_and_tr(client_core);
    }

    auto add_exe = [&setup_exe](auto &base, const String &name) -> decltype(auto) {
        return setup_exe(base.addExecutable(name));
    };

    //
    auto &console = add_exe(aspia, "console");
    setup_target(console, "console");
    console.Public += client_core, qt_base;
    if (console.getBuildSettings().TargetOS.Type == OSType::Windows) {
        console.Public += "org.sw.demo.qtproject.qt.base.plugins.platforms.windows" QT_VERSION ""_dep;
        console.Public += "org.sw.demo.qtproject.qt.base.plugins.styles.windowsvista" QT_VERSION ""_dep;
    }
    qt_progs_and_tr(console);

    auto &client = add_exe(aspia, "client_exe");
    client += "client/client_entry_point.cc";
    client += "client/client.rc";
    client += client_core, qt_base;

    if (router.getBuildSettings().TargetOS.Type == OSType::Windows) {
        auto &host = aspia.addExecutable("host");
        auto &core = host.addSharedLibrary("core");
        setup_target(core, "host");
        core -= ".*_entry_point.cc"_rr, ".*\\.rc"_rr;
        core += "HOST_IMPLEMENTATION"_def;
        if (core.getBuildSettings().TargetOS.Type == OSType::Windows)
            core.Public += "sas.lib"_slib;
        core.Public += common, qt_base;
        core.Public += "org.sw.demo.boost.property_tree"_dep;
        if (core.getBuildSettings().TargetOS.Type == OSType::Windows)
        {
            core.Public += "org.sw.demo.qtproject.qt.base.plugins.platforms.windows" QT_VERSION ""_dep;
            core.Public += "org.sw.demo.qtproject.qt.base.plugins.styles.windowsvista" QT_VERSION ""_dep;
        }
        qt_progs_and_tr2(core);

        setup_exe(host);
        host += "host/ui/host_entry_point.cc";
        host += "host/ui/host.rc";
        host += core;

        auto &service = add_exe(host, "service");
        service += "host/win/service_entry_point.cc";
        service += "host/win/service.rc";
        service += core;

        auto &desktop_agent = add_exe(aspia, "desktop_agent");
        desktop_agent += "host/desktop_agent_entry_point.cc";
        desktop_agent += "host/desktop_agent.rc";
        desktop_agent += core;
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QtCore>
#include <QtNetwork/QtNetwork>
#include <QtTest/QtTest>

#include "../network-settings.h"

//TESTED_CLASS=
//TESTED_FILES=

class tst_QIODevice : public QObject
{
    Q_OBJECT

public:
    tst_QIODevice();
    virtual ~tst_QIODevice();

public slots:
    void init();
    void cleanup();
private slots:
    void getSetCheck();
    void constructing_QTcpSocket();
    void constructing_QFile();
    void read_QByteArray();
    void unget();
    void peek();
    void getch();
    void putch();

    void readLine_data();
    void readLine();
};

// Testing get/set functions
void tst_QIODevice::getSetCheck()
{
    // OpenMode QIODevice::openMode()
    // void QIODevice::setOpenMode(OpenMode)
    class MyIODevice : public QIODevice {
    public:
        void setOpenMode(OpenMode openMode) { QIODevice::setOpenMode(openMode); }
    };
    QTcpSocket var1;
    MyIODevice *obj1 = reinterpret_cast<MyIODevice*>(&var1);
    obj1->setOpenMode(QIODevice::OpenMode(QIODevice::NotOpen));
    QCOMPARE(QIODevice::OpenMode(QIODevice::NotOpen), obj1->openMode());
    obj1->setOpenMode(QIODevice::OpenMode(QIODevice::ReadWrite));
    QCOMPARE(QIODevice::OpenMode(QIODevice::ReadWrite), obj1->openMode());
}

tst_QIODevice::tst_QIODevice()
{
}

tst_QIODevice::~tst_QIODevice()
{

}

void tst_QIODevice::init()
{
}

void tst_QIODevice::cleanup()
{
}

//----------------------------------------------------------------------------------
void tst_QIODevice::constructing_QTcpSocket()
{
#if defined(Q_OS_WINCE) && defined(WINCE_EMULATOR_TEST)
    QSKIP("Networking tests in a WinCE emulator are unstable", SkipAll);
#endif
    QTcpSocket socket;
    QIODevice *device = &socket;

    QVERIFY(!device->isOpen());

    socket.connectToHost("imap.troll.no", 143);
    QVERIFY(socket.waitForConnected(5000));
    QVERIFY(device->isOpen());

    while (!device->canReadLine())
        QVERIFY(device->waitForReadyRead(5000));

    char buf[1024];
    memset(buf, 0, sizeof(buf));
    qlonglong lineLength = device->readLine(buf, sizeof(buf));
    QVERIFY(lineLength > 0);
    QCOMPARE(socket.pos(), qlonglong(0));

    socket.close();
    socket.connectToHost("imap.troll.no", 143);
    QVERIFY(socket.waitForConnected(5000));

    while (!device->canReadLine())
        QVERIFY(device->waitForReadyRead(5000));

    char buf2[1024];
    memset(buf2, 0, sizeof(buf2));
    QCOMPARE(socket.readLine(buf2, sizeof(buf2)), lineLength);

    char *c1 = buf;
    char *c2 = buf2;
    while (*c1 && *c2) {
        QCOMPARE(*c1, *c2);
        ++c1;
        ++c2;
    }
    QCOMPARE(*c1, *c2);
}

//----------------------------------------------------------------------------------
void tst_QIODevice::constructing_QFile()
{
    QFile file;
    QIODevice *device = &file;

    QVERIFY(!device->isOpen());

    file.setFileName(SRCDIR "tst_qiodevice.cpp");
    QVERIFY(file.open(QFile::ReadOnly));
    QVERIFY(device->isOpen());
    QCOMPARE((int) device->openMode(), (int) QFile::ReadOnly);

    char buf[1024];
    memset(buf, 0, sizeof(buf));
    qlonglong lineLength = device->readLine(buf, sizeof(buf));
    QVERIFY(lineLength > 0);
    QCOMPARE(file.pos(), lineLength);

    file.seek(0);
    char buf2[1024];
    memset(buf2, 0, sizeof(buf2));
    QCOMPARE(file.readLine(buf2, sizeof(buf2)), lineLength);

    char *c1 = buf;
    char *c2 = buf2;
    while (*c1 && *c2) {
        QCOMPARE(*c1, *c2);
        ++c1;
        ++c2;
    }
    QCOMPARE(*c1, *c2);
}

void tst_QIODevice::read_QByteArray()
{
    QFile f(SRCDIR "tst_qiodevice.cpp");
    f.open(QIODevice::ReadOnly);

    QByteArray b = f.read(10);
    QCOMPARE(b.length(), 10);

    b = f.read(256);
    QCOMPARE(b.length(), 256);

    b = f.read(0);
    QCOMPARE(b.length(), 0);
}

//--------------------------------------------------------------------
void tst_QIODevice::unget()
{
#if defined(Q_OS_WINCE) && defined(WINCE_EMULATOR_TEST)
    QSKIP("Networking tests in a WinCE emulator are unstable", SkipAll);
#endif
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.write("ZXCV");
    buffer.seek(0);
    QCOMPARE(buffer.read(4), QByteArray("ZXCV"));
    QCOMPARE(buffer.pos(), qint64(4));

    buffer.ungetChar('a');
    buffer.ungetChar('b');
    buffer.ungetChar('c');
    buffer.ungetChar('d');

    QCOMPARE(buffer.pos(), qint64(0));

    char buf[6];
    QCOMPARE(buffer.readLine(buf, 5), qint64(4));
    QCOMPARE(buffer.pos(), qint64(4));
    QCOMPARE(static_cast<const char*>(buf), "dcba");

    buffer.ungetChar('a');
    buffer.ungetChar('b');
    buffer.ungetChar('c');
    buffer.ungetChar('d');

    QCOMPARE(buffer.pos(), qint64(0));

    for (int i = 0; i < 5; ++i) {
        buf[0] = '@';
        buf[1] = '@';
        QTest::ignoreMessage(QtWarningMsg,
                              "QIODevice::readLine: Called with maxSize < 2");
        QCOMPARE(buffer.readLine(buf, 1), qint64(-1));
        QCOMPARE(buffer.readLine(buf, 2), qint64(i < 4 ? 1 : -1));
        switch (i) {
        case 0: QCOMPARE(buf[0], 'd'); break;
        case 1: QCOMPARE(buf[0], 'c'); break;
        case 2: QCOMPARE(buf[0], 'b'); break;
        case 3: QCOMPARE(buf[0], 'a'); break;
        case 4: QCOMPARE(buf[0], '\0'); break;
        }
        QCOMPARE(buf[1], i < 4 ? '\0' : '@');
    }

    buffer.ungetChar('\n');
    QCOMPARE(buffer.readLine(), QByteArray("\n"));

    buffer.seek(1);
    buffer.readLine(buf, 3);
    QCOMPARE(static_cast<const char*>(buf), "XC");

    buffer.seek(4);
    buffer.ungetChar('Q');
    QCOMPARE(buffer.readLine(buf, 3), qint64(1));

    for (int i = 0; i < 2; ++i) {
        QTcpSocket socket;
	QIODevice *dev;
	QByteArray result;
	const char *lineResult;
	if (i == 0) {
            dev = &buffer;
            result = QByteArray("ZXCV");
            lineResult = "ZXCV";
        } else {
            socket.connectToHost(QtNetworkSettings::serverName(), 80);
            socket.write("GET / HTTP/1.0\r\n\r\n");
            QVERIFY(socket.waitForReadyRead());
            dev = &socket;
            result = QByteArray("HTTP");
            lineResult = "Date";
	}
	char ch, ch2;
	dev->seek(0);
	dev->getChar(&ch);
	dev->ungetChar(ch);
	QCOMPARE(dev->peek(4), result);
	dev->getChar(&ch);
	dev->getChar(&ch2);
	dev->ungetChar(ch2);
	dev->ungetChar(ch);
	QCOMPARE(dev->read(1), result.left(1));
	QCOMPARE(dev->read(3), result.right(3));

        if (i == 0)
	    dev->seek(0);
        else
            dev->readLine();
        dev->getChar(&ch);
        dev->ungetChar(ch);
        dev->readLine(buf, 5);
        QCOMPARE(static_cast<const char*>(buf), lineResult);

        if (i == 1)
            socket.close();
    }
}

//--------------------------------------------------------------------
void tst_QIODevice::peek()
{
    QBuffer buffer;
    QFile::remove("peektestfile");
    QFile file("peektestfile");

    for (int i = 0; i < 2; ++i) {
	QIODevice *device = i ? (QIODevice *)&file : (QIODevice *)&buffer;

	device->open(QBuffer::ReadWrite);
	device->write("ZXCV");

	device->seek(0);
	QCOMPARE(device->peek(4), QByteArray("ZXCV"));
	QCOMPARE(device->pos(), qint64(0));
	device->write("ABCDE");
	device->seek(3);
	QCOMPARE(device->peek(1), QByteArray("D"));
	QCOMPARE(device->peek(5), QByteArray("DE"));
	device->seek(0);
	QCOMPARE(device->read(4), QByteArray("ABCD"));
	QCOMPARE(device->pos(), qint64(4));

	device->seek(0);
	device->write("ZXCV");
	device->seek(0);
	char buf[5];
	buf[4] = 0;
	device->peek(buf, 4);
	QCOMPARE(static_cast<const char *>(buf), "ZXCV");
	QCOMPARE(device->pos(), qint64(0));
	device->read(buf, 4);
	QCOMPARE(static_cast<const char *>(buf), "ZXCV");
	QCOMPARE(device->pos(), qint64(4));
    }
    QFile::remove("peektestfile");
}

void tst_QIODevice::getch()
{
#ifdef QT3_SUPPORT
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.write("\xff\x7f\x80\x00", 4);
    buffer.reset();
    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);

    buffer.ungetch(0x00);
    buffer.ungetch(0x80);
    buffer.ungetch(0x7f);
    buffer.ungetch(0xff);

    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);
#endif
}

void tst_QIODevice::putch()
{
#ifdef QT3_SUPPORT
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.putch(0xff);
    buffer.putch(0x7f);
    buffer.putch(0x80);
    buffer.putch(0x00);
    buffer.reset();
    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);
#endif
}

void tst_QIODevice::readLine_data()
{
    QTest::addColumn<QByteArray>("data");

    QTest::newRow("0") << QByteArray("\nAA");
    QTest::newRow("1") << QByteArray("A\nAA");

    QByteArray data(9000, 'A');
    data[8193] = '\n';
    QTest::newRow("8194") << data;
    data[8193] = 'A';
    data[8192] = '\n';
    QTest::newRow("8193") << data;
    data[8192] = 'A';
    data[8191] = '\n';
    QTest::newRow("8192") << data;
    data[8191] = 'A';
    data[8190] = '\n';
    QTest::newRow("8191") << data;

    data[5999] = '\n';
    QTest::newRow("6000") << data;

    data[4095] = '\n';
    QTest::newRow("4096") << data;

    data[4094] = '\n';
    data[4095] = 'A';
    QTest::newRow("4095") << data;
}

void tst_QIODevice::readLine()
{
    QFETCH(QByteArray, data);
    QBuffer buffer(&data);
    QVERIFY(buffer.open(QIODevice::ReadWrite));
    QVERIFY(buffer.canReadLine());

    int linelen = data.indexOf('\n') + 1;
    QByteArray line;
    line.reserve(linelen + 100);

    int result = buffer.readLine(line.data(), linelen + 100);
    QCOMPARE(result, linelen);

    // try the exact length of the line (plus terminating \0)
    QVERIFY(buffer.seek(0));
    result = buffer.readLine(line.data(), linelen + 1);
    QCOMPARE(result, linelen);

    // try with a line length limit
    QVERIFY(buffer.seek(0));
    line = buffer.readLine(linelen + 100);
    QCOMPARE(line.size(), linelen);

    // try without a length limit
    QVERIFY(buffer.seek(0));
    line = buffer.readLine();
    QCOMPARE(line.size(), linelen);
}

QTEST_MAIN(tst_QIODevice)
#include "tst_qiodevice.moc"
<commit_msg>Use QtNetworkSettings, don't hard code IMAP host name. This should fix failures in Berlin.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QtCore>
#include <QtNetwork/QtNetwork>
#include <QtTest/QtTest>

#include "../network-settings.h"

//TESTED_CLASS=
//TESTED_FILES=

class tst_QIODevice : public QObject
{
    Q_OBJECT

public:
    tst_QIODevice();
    virtual ~tst_QIODevice();

public slots:
    void init();
    void cleanup();
private slots:
    void getSetCheck();
    void constructing_QTcpSocket();
    void constructing_QFile();
    void read_QByteArray();
    void unget();
    void peek();
    void getch();
    void putch();

    void readLine_data();
    void readLine();
};

// Testing get/set functions
void tst_QIODevice::getSetCheck()
{
    // OpenMode QIODevice::openMode()
    // void QIODevice::setOpenMode(OpenMode)
    class MyIODevice : public QIODevice {
    public:
        void setOpenMode(OpenMode openMode) { QIODevice::setOpenMode(openMode); }
    };
    QTcpSocket var1;
    MyIODevice *obj1 = reinterpret_cast<MyIODevice*>(&var1);
    obj1->setOpenMode(QIODevice::OpenMode(QIODevice::NotOpen));
    QCOMPARE(QIODevice::OpenMode(QIODevice::NotOpen), obj1->openMode());
    obj1->setOpenMode(QIODevice::OpenMode(QIODevice::ReadWrite));
    QCOMPARE(QIODevice::OpenMode(QIODevice::ReadWrite), obj1->openMode());
}

tst_QIODevice::tst_QIODevice()
{
}

tst_QIODevice::~tst_QIODevice()
{

}

void tst_QIODevice::init()
{
}

void tst_QIODevice::cleanup()
{
}

//----------------------------------------------------------------------------------
void tst_QIODevice::constructing_QTcpSocket()
{
#if defined(Q_OS_WINCE) && defined(WINCE_EMULATOR_TEST)
    QSKIP("Networking tests in a WinCE emulator are unstable", SkipAll);
#endif
    QTcpSocket socket;
    QIODevice *device = &socket;

    QVERIFY(!device->isOpen());

    socket.connectToHost(QtNetworkSettings::serverName(), 143);
    QVERIFY(socket.waitForConnected(5000));
    QVERIFY(device->isOpen());

    while (!device->canReadLine())
        QVERIFY(device->waitForReadyRead(5000));

    char buf[1024];
    memset(buf, 0, sizeof(buf));
    qlonglong lineLength = device->readLine(buf, sizeof(buf));
    QVERIFY(lineLength > 0);
    QCOMPARE(socket.pos(), qlonglong(0));

    socket.close();
    socket.connectToHost(QtNetworkSettings::serverName(), 143);
    QVERIFY(socket.waitForConnected(5000));

    while (!device->canReadLine())
        QVERIFY(device->waitForReadyRead(5000));

    char buf2[1024];
    memset(buf2, 0, sizeof(buf2));
    QCOMPARE(socket.readLine(buf2, sizeof(buf2)), lineLength);

    char *c1 = buf;
    char *c2 = buf2;
    while (*c1 && *c2) {
        QCOMPARE(*c1, *c2);
        ++c1;
        ++c2;
    }
    QCOMPARE(*c1, *c2);
}

//----------------------------------------------------------------------------------
void tst_QIODevice::constructing_QFile()
{
    QFile file;
    QIODevice *device = &file;

    QVERIFY(!device->isOpen());

    file.setFileName(SRCDIR "tst_qiodevice.cpp");
    QVERIFY(file.open(QFile::ReadOnly));
    QVERIFY(device->isOpen());
    QCOMPARE((int) device->openMode(), (int) QFile::ReadOnly);

    char buf[1024];
    memset(buf, 0, sizeof(buf));
    qlonglong lineLength = device->readLine(buf, sizeof(buf));
    QVERIFY(lineLength > 0);
    QCOMPARE(file.pos(), lineLength);

    file.seek(0);
    char buf2[1024];
    memset(buf2, 0, sizeof(buf2));
    QCOMPARE(file.readLine(buf2, sizeof(buf2)), lineLength);

    char *c1 = buf;
    char *c2 = buf2;
    while (*c1 && *c2) {
        QCOMPARE(*c1, *c2);
        ++c1;
        ++c2;
    }
    QCOMPARE(*c1, *c2);
}

void tst_QIODevice::read_QByteArray()
{
    QFile f(SRCDIR "tst_qiodevice.cpp");
    f.open(QIODevice::ReadOnly);

    QByteArray b = f.read(10);
    QCOMPARE(b.length(), 10);

    b = f.read(256);
    QCOMPARE(b.length(), 256);

    b = f.read(0);
    QCOMPARE(b.length(), 0);
}

//--------------------------------------------------------------------
void tst_QIODevice::unget()
{
#if defined(Q_OS_WINCE) && defined(WINCE_EMULATOR_TEST)
    QSKIP("Networking tests in a WinCE emulator are unstable", SkipAll);
#endif
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.write("ZXCV");
    buffer.seek(0);
    QCOMPARE(buffer.read(4), QByteArray("ZXCV"));
    QCOMPARE(buffer.pos(), qint64(4));

    buffer.ungetChar('a');
    buffer.ungetChar('b');
    buffer.ungetChar('c');
    buffer.ungetChar('d');

    QCOMPARE(buffer.pos(), qint64(0));

    char buf[6];
    QCOMPARE(buffer.readLine(buf, 5), qint64(4));
    QCOMPARE(buffer.pos(), qint64(4));
    QCOMPARE(static_cast<const char*>(buf), "dcba");

    buffer.ungetChar('a');
    buffer.ungetChar('b');
    buffer.ungetChar('c');
    buffer.ungetChar('d');

    QCOMPARE(buffer.pos(), qint64(0));

    for (int i = 0; i < 5; ++i) {
        buf[0] = '@';
        buf[1] = '@';
        QTest::ignoreMessage(QtWarningMsg,
                              "QIODevice::readLine: Called with maxSize < 2");
        QCOMPARE(buffer.readLine(buf, 1), qint64(-1));
        QCOMPARE(buffer.readLine(buf, 2), qint64(i < 4 ? 1 : -1));
        switch (i) {
        case 0: QCOMPARE(buf[0], 'd'); break;
        case 1: QCOMPARE(buf[0], 'c'); break;
        case 2: QCOMPARE(buf[0], 'b'); break;
        case 3: QCOMPARE(buf[0], 'a'); break;
        case 4: QCOMPARE(buf[0], '\0'); break;
        }
        QCOMPARE(buf[1], i < 4 ? '\0' : '@');
    }

    buffer.ungetChar('\n');
    QCOMPARE(buffer.readLine(), QByteArray("\n"));

    buffer.seek(1);
    buffer.readLine(buf, 3);
    QCOMPARE(static_cast<const char*>(buf), "XC");

    buffer.seek(4);
    buffer.ungetChar('Q');
    QCOMPARE(buffer.readLine(buf, 3), qint64(1));

    for (int i = 0; i < 2; ++i) {
        QTcpSocket socket;
	QIODevice *dev;
	QByteArray result;
	const char *lineResult;
	if (i == 0) {
            dev = &buffer;
            result = QByteArray("ZXCV");
            lineResult = "ZXCV";
        } else {
            socket.connectToHost(QtNetworkSettings::serverName(), 80);
            socket.write("GET / HTTP/1.0\r\n\r\n");
            QVERIFY(socket.waitForReadyRead());
            dev = &socket;
            result = QByteArray("HTTP");
            lineResult = "Date";
	}
	char ch, ch2;
	dev->seek(0);
	dev->getChar(&ch);
	dev->ungetChar(ch);
	QCOMPARE(dev->peek(4), result);
	dev->getChar(&ch);
	dev->getChar(&ch2);
	dev->ungetChar(ch2);
	dev->ungetChar(ch);
	QCOMPARE(dev->read(1), result.left(1));
	QCOMPARE(dev->read(3), result.right(3));

        if (i == 0)
	    dev->seek(0);
        else
            dev->readLine();
        dev->getChar(&ch);
        dev->ungetChar(ch);
        dev->readLine(buf, 5);
        QCOMPARE(static_cast<const char*>(buf), lineResult);

        if (i == 1)
            socket.close();
    }
}

//--------------------------------------------------------------------
void tst_QIODevice::peek()
{
    QBuffer buffer;
    QFile::remove("peektestfile");
    QFile file("peektestfile");

    for (int i = 0; i < 2; ++i) {
	QIODevice *device = i ? (QIODevice *)&file : (QIODevice *)&buffer;

	device->open(QBuffer::ReadWrite);
	device->write("ZXCV");

	device->seek(0);
	QCOMPARE(device->peek(4), QByteArray("ZXCV"));
	QCOMPARE(device->pos(), qint64(0));
	device->write("ABCDE");
	device->seek(3);
	QCOMPARE(device->peek(1), QByteArray("D"));
	QCOMPARE(device->peek(5), QByteArray("DE"));
	device->seek(0);
	QCOMPARE(device->read(4), QByteArray("ABCD"));
	QCOMPARE(device->pos(), qint64(4));

	device->seek(0);
	device->write("ZXCV");
	device->seek(0);
	char buf[5];
	buf[4] = 0;
	device->peek(buf, 4);
	QCOMPARE(static_cast<const char *>(buf), "ZXCV");
	QCOMPARE(device->pos(), qint64(0));
	device->read(buf, 4);
	QCOMPARE(static_cast<const char *>(buf), "ZXCV");
	QCOMPARE(device->pos(), qint64(4));
    }
    QFile::remove("peektestfile");
}

void tst_QIODevice::getch()
{
#ifdef QT3_SUPPORT
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.write("\xff\x7f\x80\x00", 4);
    buffer.reset();
    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);

    buffer.ungetch(0x00);
    buffer.ungetch(0x80);
    buffer.ungetch(0x7f);
    buffer.ungetch(0xff);

    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);
#endif
}

void tst_QIODevice::putch()
{
#ifdef QT3_SUPPORT
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    buffer.putch(0xff);
    buffer.putch(0x7f);
    buffer.putch(0x80);
    buffer.putch(0x00);
    buffer.reset();
    QCOMPARE(buffer.getch(), 0xff);
    QCOMPARE(buffer.getch(), 0x7f);
    QCOMPARE(buffer.getch(), 0x80);
    QCOMPARE(buffer.getch(), 0x00);
#endif
}

void tst_QIODevice::readLine_data()
{
    QTest::addColumn<QByteArray>("data");

    QTest::newRow("0") << QByteArray("\nAA");
    QTest::newRow("1") << QByteArray("A\nAA");

    QByteArray data(9000, 'A');
    data[8193] = '\n';
    QTest::newRow("8194") << data;
    data[8193] = 'A';
    data[8192] = '\n';
    QTest::newRow("8193") << data;
    data[8192] = 'A';
    data[8191] = '\n';
    QTest::newRow("8192") << data;
    data[8191] = 'A';
    data[8190] = '\n';
    QTest::newRow("8191") << data;

    data[5999] = '\n';
    QTest::newRow("6000") << data;

    data[4095] = '\n';
    QTest::newRow("4096") << data;

    data[4094] = '\n';
    data[4095] = 'A';
    QTest::newRow("4095") << data;
}

void tst_QIODevice::readLine()
{
    QFETCH(QByteArray, data);
    QBuffer buffer(&data);
    QVERIFY(buffer.open(QIODevice::ReadWrite));
    QVERIFY(buffer.canReadLine());

    int linelen = data.indexOf('\n') + 1;
    QByteArray line;
    line.reserve(linelen + 100);

    int result = buffer.readLine(line.data(), linelen + 100);
    QCOMPARE(result, linelen);

    // try the exact length of the line (plus terminating \0)
    QVERIFY(buffer.seek(0));
    result = buffer.readLine(line.data(), linelen + 1);
    QCOMPARE(result, linelen);

    // try with a line length limit
    QVERIFY(buffer.seek(0));
    line = buffer.readLine(linelen + 100);
    QCOMPARE(line.size(), linelen);

    // try without a length limit
    QVERIFY(buffer.seek(0));
    line = buffer.readLine();
    QCOMPARE(line.size(), linelen);
}

QTEST_MAIN(tst_QIODevice)
#include "tst_qiodevice.moc"
<|endoftext|>