<commit_before>// Copyright (c) 2009 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/gtk/bookmark_utils_gtk.h"

#include "app/gtk_dnd_util.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/gfx/gtk_util.h"
#include "base/pickle.h"
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/common/gtk_util.h"

namespace {

// Used in gtk_selection_data_set(). (I assume from this parameter that gtk has
// to some really exotic hardware...)
const int kBitsInAByte = 8;

// Maximum number of characters on a bookmark button.
const size_t kMaxCharsOnAButton = 15;

// Max size of each component of the button tooltips.
const size_t kMaxTooltipTitleLength = 100;
const size_t kMaxTooltipURLLength = 400;

// Only used for the background of the drag widget.
const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xe6, 0xed, 0xf4);

// Padding between the chrome button highlight border and the contents (favicon,
// text).
// TODO(estade): we need to adjust the top and bottom padding, but first we need
// to give the bookmark bar more space (at the expense of the toolbar).
const int kButtonPaddingTop = 0;
const int kButtonPaddingBottom = 0;
const int kButtonPaddingLeft = 2;
const int kButtonPaddingRight = 0;

void* AsVoid(const BookmarkNode* node) {
  return const_cast<BookmarkNode*>(node);
}

}  // namespace

namespace bookmark_utils {

const char kBookmarkNode[] = "bookmark-node";

// Spacing between the buttons on the bar.
const int kBarButtonPadding = 4;

GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
                            bool native) {
  GdkPixbuf* pixbuf;

  if (node->is_url()) {
    if (model->GetFavIcon(node).width() != 0) {
      pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node));
    } else {
      pixbuf = GtkThemeProvider::GetDefaultFavicon(native);
      g_object_ref(pixbuf);
    }
  } else {
    pixbuf = GtkThemeProvider::GetFolderIcon(native);
    g_object_ref(pixbuf);
  }

  return pixbuf;
}

GtkWidget* GetDragRepresentation(const BookmarkNode* node,
                                 BookmarkModel* model,
                                 GtkThemeProvider* provider) {
  // Build a windowed representation for our button.
  GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
  if (!provider->UseGtkTheme()) {
    // TODO(erg): Theme wise, which color should I be picking here?
    // COLOR_BUTTON_BACKGROUND doesn't match the default theme!
    gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &kBackgroundColor);
  }
  gtk_widget_realize(window);

  GtkWidget* frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
  gtk_container_add(GTK_CONTAINER(window), frame);
  gtk_widget_show(frame);

  GtkWidget* floating_button = provider->BuildChromeButton();
  bookmark_utils::ConfigureButtonForNode(node, model, floating_button,
                                         provider);
  gtk_container_add(GTK_CONTAINER(frame), floating_button);
  gtk_widget_show(floating_button);

  return window;
}

void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
                            GtkWidget* button, GtkThemeProvider* provider) {
  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
  if (former_child)
    gtk_container_remove(GTK_CONTAINER(button), former_child);

  std::string tooltip = BuildTooltipFor(node);
  if (!tooltip.empty())
    gtk_widget_set_tooltip_markup(button, tooltip.c_str());

  // We pack the button manually (rather than using gtk_button_set_*) so that
  // we can have finer control over its label.
  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model,
                                                       provider->UseGtkTheme());
  GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
  g_object_unref(pixbuf);

  GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding);
  gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);

  std::string label_string = WideToUTF8(node->GetTitle());
  if (!label_string.empty()) {
    GtkWidget* label = gtk_label_new(label_string.c_str());
    gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton);
    gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
    SetButtonTextColors(label, provider);
  }

  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
  // If we are not showing the label, don't set any padding, so that the icon
  // will just be centered.
  if (label_string.c_str()) {
    gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
        kButtonPaddingTop, kButtonPaddingBottom,
        kButtonPaddingLeft, kButtonPaddingRight);
  }
  gtk_container_add(GTK_CONTAINER(alignment), box);
  gtk_container_add(GTK_CONTAINER(button), alignment);

  g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode,
                    AsVoid(node));

  gtk_widget_show_all(alignment);
}

std::string BuildTooltipFor(const BookmarkNode* node) {
  const std::string& url = node->GetURL().possibly_invalid_spec();
  const std::string& title = WideToUTF8(node->GetTitle());

  std::string truncated_url = WideToUTF8(l10n_util::TruncateString(
      UTF8ToWide(url), kMaxTooltipURLLength));
  gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(),
                                                 truncated_url.size());
  std::string escaped_url(escaped_url_cstr);
  g_free(escaped_url_cstr);

  std::string tooltip;
  if (url == title) {
    return escaped_url;
  } else {
    std::string truncated_title = WideToUTF8(l10n_util::TruncateString(
      node->GetTitle(), kMaxTooltipTitleLength));
    gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(),
                                                     truncated_title.size());
    std::string escaped_title(escaped_title_cstr);
    g_free(escaped_title_cstr);

    if (!escaped_url.empty())
      return std::string("") + escaped_title + "\n" + escaped_url;
    else
      return std::string("") + escaped_title + "";
  }
}

const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) {
  return reinterpret_cast<const BookmarkNode*>(
      g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode));
}

void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) {
  if (provider->UseGtkTheme()) {
    gtk_util::SetLabelColor(label, NULL);
  } else {
    GdkColor color = provider->GetGdkColor(
        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
    gtk_util::SetLabelColor(label, &color);
  }
}

// DnD-related -----------------------------------------------------------------

void WriteBookmarkToSelection(const BookmarkNode* node,
                              GtkSelectionData* selection_data,
                              guint target_type,
                              Profile* profile) {
  DCHECK(node);
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(node);
  WriteBookmarksToSelection(nodes, selection_data, target_type, profile);
}

void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
                               GtkSelectionData* selection_data,
                               guint target_type,
                               Profile* profile) {
  switch (target_type) {
    case GtkDndUtil::CHROME_BOOKMARK_ITEM: {
      BookmarkDragData data(nodes);
      Pickle pickle;
      data.WriteToPickle(profile, &pickle);

      gtk_selection_data_set(selection_data, selection_data->target,
                             kBitsInAByte,
                             static_cast<const guchar*>(pickle.data()),
                             pickle.size());
      break;
    }
    case GtkDndUtil::TEXT_URI_LIST: {
      gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) *
                                               (nodes.size() + 1)));
      for (size_t i = 0; i < nodes.size(); ++i) {
        // If the node is a folder, this will be empty. TODO(estade): figure out
        // if there are any ramifications to passing an empty URI. After a
        // little testing, it seems fine.
        const GURL& url = nodes[i]->GetURL();
        // This const cast should be safe as gtk_selection_data_set_uris()
        // makes copies.
        uris[i] = const_cast<gchar*>(url.spec().c_str());
      }
      uris[nodes.size()] = NULL;

      gtk_selection_data_set_uris(selection_data, uris);
      free(uris);
      break;
    }
    default: {
      DLOG(ERROR) << "Unsupported drag get type!";
    }
  }
}

std::vector<const BookmarkNode*> GetNodesFromSelection(
    GdkDragContext* context,
    GtkSelectionData* selection_data,
    guint target_type,
    Profile* profile,
    gboolean* delete_selection_data,
    gboolean* dnd_success) {
  *delete_selection_data = FALSE;
  *dnd_success = FALSE;

  if ((selection_data != NULL) && (selection_data->length >= 0)) {
    if (context->action == GDK_ACTION_MOVE) {
      *delete_selection_data = TRUE;
    }

    switch (target_type) {
      case GtkDndUtil::CHROME_BOOKMARK_ITEM: {
        *dnd_success = TRUE;
        Pickle pickle(reinterpret_cast<char*>(selection_data->data),
                      selection_data->length);
        BookmarkDragData drag_data;
        drag_data.ReadFromPickle(&pickle);
        return drag_data.GetNodes(profile);
      }
      default: {
        DLOG(ERROR) << "Unsupported drag received type: " << target_type;
      }
    }
  }

  return std::vector<const BookmarkNode*>();
}

bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data,
    BookmarkModel* model, const BookmarkNode* parent, int idx) {
  GURL url;
  string16 title;
  if (!GtkDndUtil::ExtractNamedURL(selection_data, &url, &title))
    return false;

  model->AddURL(parent, idx, UTF16ToWideHack(title), url);
  return true;
}

bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data,
    BookmarkModel* model, const BookmarkNode* parent, int idx) {
  std::vector<GURL> urls;
  GtkDndUtil::ExtractURIList(selection_data, &urls);
  for (size_t i = 0; i < urls.size(); ++i) {
    std::string title = GetNameForURL(urls[i]);
    model->AddURL(parent, idx++, UTF8ToWide(title), urls[i]);
  }
  return true;
}

}  // namespace bookmark_utils
<commit_msg>GTK: Don't put a blank line in the tooltip for nameless bookmark bar bookmarks.<commit_after>// Copyright (c) 2009 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/gtk/bookmark_utils_gtk.h"

#include "app/gtk_dnd_util.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/gfx/gtk_util.h"
#include "base/pickle.h"
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/gtk/gtk_chrome_button.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/profile.h"
#include "chrome/common/gtk_util.h"

namespace {

// Used in gtk_selection_data_set(). (I assume from this parameter that gtk has
// to some really exotic hardware...)
const int kBitsInAByte = 8;

// Maximum number of characters on a bookmark button.
const size_t kMaxCharsOnAButton = 15;

// Max size of each component of the button tooltips.
const size_t kMaxTooltipTitleLength = 100;
const size_t kMaxTooltipURLLength = 400;

// Only used for the background of the drag widget.
const GdkColor kBackgroundColor = GDK_COLOR_RGB(0xe6, 0xed, 0xf4);

// Padding between the chrome button highlight border and the contents (favicon,
// text).
// TODO(estade): we need to adjust the top and bottom padding, but first we need
// to give the bookmark bar more space (at the expense of the toolbar).
const int kButtonPaddingTop = 0;
const int kButtonPaddingBottom = 0;
const int kButtonPaddingLeft = 2;
const int kButtonPaddingRight = 0;

void* AsVoid(const BookmarkNode* node) {
  return const_cast<BookmarkNode*>(node);
}

}  // namespace

namespace bookmark_utils {

const char kBookmarkNode[] = "bookmark-node";

// Spacing between the buttons on the bar.
const int kBarButtonPadding = 4;

GdkPixbuf* GetPixbufForNode(const BookmarkNode* node, BookmarkModel* model,
                            bool native) {
  GdkPixbuf* pixbuf;

  if (node->is_url()) {
    if (model->GetFavIcon(node).width() != 0) {
      pixbuf = gfx::GdkPixbufFromSkBitmap(&model->GetFavIcon(node));
    } else {
      pixbuf = GtkThemeProvider::GetDefaultFavicon(native);
      g_object_ref(pixbuf);
    }
  } else {
    pixbuf = GtkThemeProvider::GetFolderIcon(native);
    g_object_ref(pixbuf);
  }

  return pixbuf;
}

GtkWidget* GetDragRepresentation(const BookmarkNode* node,
                                 BookmarkModel* model,
                                 GtkThemeProvider* provider) {
  // Build a windowed representation for our button.
  GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
  if (!provider->UseGtkTheme()) {
    // TODO(erg): Theme wise, which color should I be picking here?
    // COLOR_BUTTON_BACKGROUND doesn't match the default theme!
    gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &kBackgroundColor);
  }
  gtk_widget_realize(window);

  GtkWidget* frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
  gtk_container_add(GTK_CONTAINER(window), frame);
  gtk_widget_show(frame);

  GtkWidget* floating_button = provider->BuildChromeButton();
  bookmark_utils::ConfigureButtonForNode(node, model, floating_button,
                                         provider);
  gtk_container_add(GTK_CONTAINER(frame), floating_button);
  gtk_widget_show(floating_button);

  return window;
}

void ConfigureButtonForNode(const BookmarkNode* node, BookmarkModel* model,
                            GtkWidget* button, GtkThemeProvider* provider) {
  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
  if (former_child)
    gtk_container_remove(GTK_CONTAINER(button), former_child);

  std::string tooltip = BuildTooltipFor(node);
  if (!tooltip.empty())
    gtk_widget_set_tooltip_markup(button, tooltip.c_str());

  // We pack the button manually (rather than using gtk_button_set_*) so that
  // we can have finer control over its label.
  GdkPixbuf* pixbuf = bookmark_utils::GetPixbufForNode(node, model,
                                                       provider->UseGtkTheme());
  GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
  g_object_unref(pixbuf);

  GtkWidget* box = gtk_hbox_new(FALSE, kBarButtonPadding);
  gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);

  std::string label_string = WideToUTF8(node->GetTitle());
  if (!label_string.empty()) {
    GtkWidget* label = gtk_label_new(label_string.c_str());
    gtk_label_set_max_width_chars(GTK_LABEL(label), kMaxCharsOnAButton);
    gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
    SetButtonTextColors(label, provider);
  }

  GtkWidget* alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
  // If we are not showing the label, don't set any padding, so that the icon
  // will just be centered.
  if (label_string.c_str()) {
    gtk_alignment_set_padding(GTK_ALIGNMENT(alignment),
        kButtonPaddingTop, kButtonPaddingBottom,
        kButtonPaddingLeft, kButtonPaddingRight);
  }
  gtk_container_add(GTK_CONTAINER(alignment), box);
  gtk_container_add(GTK_CONTAINER(button), alignment);

  g_object_set_data(G_OBJECT(button), bookmark_utils::kBookmarkNode,
                    AsVoid(node));

  gtk_widget_show_all(alignment);
}

std::string BuildTooltipFor(const BookmarkNode* node) {
  const std::string& url = node->GetURL().possibly_invalid_spec();
  const std::string& title = WideToUTF8(node->GetTitle());

  std::string truncated_url = WideToUTF8(l10n_util::TruncateString(
      UTF8ToWide(url), kMaxTooltipURLLength));
  gchar* escaped_url_cstr = g_markup_escape_text(truncated_url.c_str(),
                                                 truncated_url.size());
  std::string escaped_url(escaped_url_cstr);
  g_free(escaped_url_cstr);

  std::string tooltip;
  if (url == title || title.empty()) {
    return escaped_url;
  } else {
    std::string truncated_title = WideToUTF8(l10n_util::TruncateString(
      node->GetTitle(), kMaxTooltipTitleLength));
    gchar* escaped_title_cstr = g_markup_escape_text(truncated_title.c_str(),
                                                     truncated_title.size());
    std::string escaped_title(escaped_title_cstr);
    g_free(escaped_title_cstr);

    if (!escaped_url.empty())
      return std::string("") + escaped_title + "\n" + escaped_url;
    else
      return std::string("") + escaped_title + "";
  }
}

const BookmarkNode* BookmarkNodeForWidget(GtkWidget* widget) {
  return reinterpret_cast<const BookmarkNode*>(
      g_object_get_data(G_OBJECT(widget), bookmark_utils::kBookmarkNode));
}

void SetButtonTextColors(GtkWidget* label, GtkThemeProvider* provider) {
  if (provider->UseGtkTheme()) {
    gtk_util::SetLabelColor(label, NULL);
  } else {
    GdkColor color = provider->GetGdkColor(
        BrowserThemeProvider::COLOR_BOOKMARK_TEXT);
    gtk_util::SetLabelColor(label, &color);
  }
}

// DnD-related -----------------------------------------------------------------

void WriteBookmarkToSelection(const BookmarkNode* node,
                              GtkSelectionData* selection_data,
                              guint target_type,
                              Profile* profile) {
  DCHECK(node);
  std::vector<const BookmarkNode*> nodes;
  nodes.push_back(node);
  WriteBookmarksToSelection(nodes, selection_data, target_type, profile);
}

void WriteBookmarksToSelection(const std::vector<const BookmarkNode*>& nodes,
                               GtkSelectionData* selection_data,
                               guint target_type,
                               Profile* profile) {
  switch (target_type) {
    case GtkDndUtil::CHROME_BOOKMARK_ITEM: {
      BookmarkDragData data(nodes);
      Pickle pickle;
      data.WriteToPickle(profile, &pickle);

      gtk_selection_data_set(selection_data, selection_data->target,
                             kBitsInAByte,
                             static_cast<const guchar*>(pickle.data()),
                             pickle.size());
      break;
    }
    case GtkDndUtil::TEXT_URI_LIST: {
      gchar** uris = reinterpret_cast<gchar**>(malloc(sizeof(gchar*) *
                                               (nodes.size() + 1)));
      for (size_t i = 0; i < nodes.size(); ++i) {
        // If the node is a folder, this will be empty. TODO(estade): figure out
        // if there are any ramifications to passing an empty URI. After a
        // little testing, it seems fine.
        const GURL& url = nodes[i]->GetURL();
        // This const cast should be safe as gtk_selection_data_set_uris()
        // makes copies.
        uris[i] = const_cast<gchar*>(url.spec().c_str());
      }
      uris[nodes.size()] = NULL;

      gtk_selection_data_set_uris(selection_data, uris);
      free(uris);
      break;
    }
    default: {
      DLOG(ERROR) << "Unsupported drag get type!";
    }
  }
}

std::vector<const BookmarkNode*> GetNodesFromSelection(
    GdkDragContext* context,
    GtkSelectionData* selection_data,
    guint target_type,
    Profile* profile,
    gboolean* delete_selection_data,
    gboolean* dnd_success) {
  *delete_selection_data = FALSE;
  *dnd_success = FALSE;

  if ((selection_data != NULL) && (selection_data->length >= 0)) {
    if (context->action == GDK_ACTION_MOVE) {
      *delete_selection_data = TRUE;
    }

    switch (target_type) {
      case GtkDndUtil::CHROME_BOOKMARK_ITEM: {
        *dnd_success = TRUE;
        Pickle pickle(reinterpret_cast<char*>(selection_data->data),
                      selection_data->length);
        BookmarkDragData drag_data;
        drag_data.ReadFromPickle(&pickle);
        return drag_data.GetNodes(profile);
      }
      default: {
        DLOG(ERROR) << "Unsupported drag received type: " << target_type;
      }
    }
  }

  return std::vector<const BookmarkNode*>();
}

bool CreateNewBookmarkFromNamedUrl(GtkSelectionData* selection_data,
    BookmarkModel* model, const BookmarkNode* parent, int idx) {
  GURL url;
  string16 title;
  if (!GtkDndUtil::ExtractNamedURL(selection_data, &url, &title))
    return false;

  model->AddURL(parent, idx, UTF16ToWideHack(title), url);
  return true;
}

bool CreateNewBookmarksFromURIList(GtkSelectionData* selection_data,
    BookmarkModel* model, const BookmarkNode* parent, int idx) {
  std::vector<GURL> urls;
  GtkDndUtil::ExtractURIList(selection_data, &urls);
  for (size_t i = 0; i < urls.size(); ++i) {
    std::string title = GetNameForURL(urls[i]);
    model->AddURL(parent, idx++, UTF8ToWide(title), urls[i]);
  }
  return true;
}

}  // namespace bookmark_utils
<|endoftext|>


<commit_before>#include "unittest/gtest.hpp"
#include "clustering/immediate_consistency/branch/backfiller.hpp"
#include "clustering/immediate_consistency/branch/backfillee.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"
#include "containers/uuid.hpp"
#include "rpc/semilattice/view/field.hpp"
#include "mock/branch_history_manager.hpp"
#include "mock/clustering_utils.hpp"
#include "mock/dummy_protocol.hpp"
#include "mock/unittest_utils.hpp"

using mock::dummy_protocol_t;

namespace unittest {

namespace {

boost::optional<boost::optional<backfiller_business_card_t<dummy_protocol_t> > > wrap_in_optional(
        const boost::optional<backfiller_business_card_t<dummy_protocol_t> > &inner) {
    return boost::optional<boost::optional<backfiller_business_card_t<dummy_protocol_t> > >(inner);
}

}   /* anonymous namespace */

void run_backfill_test() {

    /* Set up two stores */

    dummy_protocol_t::region_t region;
    for (char c = 'a'; c <= 'z'; c++) {
        region.keys.insert(std::string(&c, 1));
    }

    dummy_protocol_t::store_t backfiller_store;
    dummy_protocol_t::store_t backfillee_store;

    mock::in_memory_branch_history_manager_t<mock::dummy_protocol_t> branch_history_manager;
    branch_id_t dummy_branch_id = generate_uuid();
    {
        branch_birth_certificate_t<dummy_protocol_t> dummy_branch;
        dummy_branch.region = region;
        dummy_branch.initial_timestamp = state_timestamp_t::zero();
        dummy_branch.origin = region_map_t<dummy_protocol_t, version_range_t>(
            region, version_range_t(version_t(nil_uuid(), state_timestamp_t::zero()))
            );
        cond_t non_interruptor;
        branch_history_manager.create_branch(dummy_branch_id, dummy_branch, &non_interruptor);
    }

    state_timestamp_t timestamp = state_timestamp_t::zero();

    // initialize the metainfo in a store
    store_view_t<dummy_protocol_t> *stores[] = { &backfiller_store, &backfillee_store };
    for (size_t i = 0; i < sizeof(stores) / sizeof(stores[0]); i++) {
        cond_t non_interruptor;
        scoped_ptr_t<fifo_enforcer_sink_t::exit_write_t> token;
        stores[i]->new_write_token(&token);
        stores[i]->set_metainfo(
            region_map_t<dummy_protocol_t, binary_blob_t>(region,
                                                          binary_blob_t(version_range_t(version_t(dummy_branch_id, timestamp)))),
            order_token_t::ignore,
            &token,
            &non_interruptor);
    }

    // Insert 10 values into both stores, then another 10 into only `backfiller_store` and not `backfillee_store`
    for (int i = 0; i < 20; i++) {
        dummy_protocol_t::write_t w;
        std::string key = std::string(1, 'a' + randint(26));
        w.values[key] = strprintf("%d", i);

        for (int j = 0; j < (i < 10 ? 2 : 1); j++) {
            transition_timestamp_t ts = transition_timestamp_t::starting_from(timestamp);
            timestamp = ts.timestamp_after();

            cond_t non_interruptor;
            scoped_ptr_t<fifo_enforcer_sink_t::exit_write_t> token;
            backfiller_store.new_write_token(&token);

#ifndef NDEBUG
            mock::equality_metainfo_checker_callback_t<dummy_protocol_t>
                metainfo_checker_callback(binary_blob_t(version_range_t(version_t(dummy_branch_id, ts.timestamp_before()))));
            metainfo_checker_t<dummy_protocol_t> metainfo_checker(&metainfo_checker_callback, region);
#endif

            backfiller_store.write(
                DEBUG_ONLY(metainfo_checker, )
                region_map_t<dummy_protocol_t, binary_blob_t>(
                    region,
                    binary_blob_t(version_range_t(version_t(dummy_branch_id, timestamp)))
                ),
                w, ts,
                order_token_t::ignore,
                &token,
                &non_interruptor
            );
        }
    }

    // Set up a cluster so mailboxes can be created

    mock::simple_mailbox_cluster_t cluster;

    /* Expose the backfiller to the cluster */

    store_view_t<dummy_protocol_t> *backfiller_store_ptr = &backfiller_store;
    multistore_ptr_t<dummy_protocol_t> backfiller_multistore(&backfiller_store_ptr, 1);

    backfiller_t<dummy_protocol_t> backfiller(
        cluster.get_mailbox_manager(),
        &branch_history_manager,
        &backfiller_multistore);

    watchable_variable_t<boost::optional<backfiller_business_card_t<dummy_protocol_t> > > pseudo_directory(
        boost::optional<backfiller_business_card_t<dummy_protocol_t> >(backfiller.get_business_card()));

    /* Run a backfill */

    // Uhh.. hehhehheh... this might be wrong.
    store_view_t<dummy_protocol_t> *backfillee_store_ptr = &backfillee_store;
    multistore_ptr_t<dummy_protocol_t> backfillee_multistore(&backfillee_store_ptr, 1);

    cond_t interruptor;
    backfillee<dummy_protocol_t>(
        cluster.get_mailbox_manager(),
        &branch_history_manager,
        &backfillee_multistore,
        backfillee_store.get_region(),
        pseudo_directory.get_watchable()->subview(&wrap_in_optional),
        generate_uuid(),
        &interruptor);

    /* Make sure everything got transferred properly */

    for (char c = 'a'; c <= 'z'; c++) {
        std::string key(1, c);
        EXPECT_EQ(backfiller_store.values[key], backfillee_store.values[key]);
        EXPECT_TRUE(backfiller_store.timestamps[key] == backfillee_store.timestamps[key]);
    }

    scoped_ptr_t<fifo_enforcer_sink_t::exit_read_t> token1;
    backfillee_store.new_read_token(&token1);

    region_map_t<dummy_protocol_t, binary_blob_t> untransformed_backfillee_metadata;
    backfillee_store.do_get_metainfo(order_token_t::ignore, &token1, &interruptor, &untransformed_backfillee_metadata);

    region_map_t<dummy_protocol_t, version_range_t> backfillee_metadata =
        region_map_transform<dummy_protocol_t, binary_blob_t, version_range_t>(
            untransformed_backfillee_metadata,
            &binary_blob_t::get<version_range_t>
        );

    scoped_ptr_t<fifo_enforcer_sink_t::exit_read_t> token2;
    backfiller_store.new_read_token(&token2);

    region_map_t<dummy_protocol_t, binary_blob_t> untransformed_backfiller_metadata;
    backfiller_store.do_get_metainfo(order_token_t::ignore, &token2, &interruptor, &untransformed_backfiller_metadata);

    region_map_t<dummy_protocol_t, version_range_t> backfiller_metadata =
        region_map_transform<dummy_protocol_t, binary_blob_t, version_range_t>(
            untransformed_backfiller_metadata,
            &binary_blob_t::get<version_range_t>
        );

    EXPECT_TRUE(backfillee_metadata == backfiller_metadata);

    //EXPECT_EQ(1, backfillee_metadata.size());
    //EXPECT_TRUE(backfillee_metadata[0].second.is_coherent());
    //EXPECT_EQ(timestamp, backfillee_metadata[0].second.earliest.timestamp);
}
TEST(ClusteringBackfill, BackfillTest) {
    mock::run_in_thread_pool(&run_backfill_test);
}

}   /* namespace unittest */
<commit_msg>Made clustering_backfill.cc not use order_token_t::ignore.<commit_after>#include "unittest/gtest.hpp"
#include "clustering/immediate_consistency/branch/backfiller.hpp"
#include "clustering/immediate_consistency/branch/backfillee.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"
#include "containers/uuid.hpp"
#include "rpc/semilattice/view/field.hpp"
#include "mock/branch_history_manager.hpp"
#include "mock/clustering_utils.hpp"
#include "mock/dummy_protocol.hpp"
#include "mock/unittest_utils.hpp"

using mock::dummy_protocol_t;

namespace unittest {

namespace {

boost::optional<boost::optional<backfiller_business_card_t<dummy_protocol_t> > > wrap_in_optional(
        const boost::optional<backfiller_business_card_t<dummy_protocol_t> > &inner) {
    return boost::optional<boost::optional<backfiller_business_card_t<dummy_protocol_t> > >(inner);
}

}   /* anonymous namespace */

void run_backfill_test() {

    order_source_t order_source;

    /* Set up two stores */

    dummy_protocol_t::region_t region;
    for (char c = 'a'; c <= 'z'; c++) {
        region.keys.insert(std::string(&c, 1));
    }

    dummy_protocol_t::store_t backfiller_store;
    dummy_protocol_t::store_t backfillee_store;

    mock::in_memory_branch_history_manager_t<mock::dummy_protocol_t> branch_history_manager;
    branch_id_t dummy_branch_id = generate_uuid();
    {
        branch_birth_certificate_t<dummy_protocol_t> dummy_branch;
        dummy_branch.region = region;
        dummy_branch.initial_timestamp = state_timestamp_t::zero();
        dummy_branch.origin = region_map_t<dummy_protocol_t, version_range_t>(
            region, version_range_t(version_t(nil_uuid(), state_timestamp_t::zero()))
            );
        cond_t non_interruptor;
        branch_history_manager.create_branch(dummy_branch_id, dummy_branch, &non_interruptor);
    }

    state_timestamp_t timestamp = state_timestamp_t::zero();

    // initialize the metainfo in a store
    store_view_t<dummy_protocol_t> *stores[] = { &backfiller_store, &backfillee_store };
    for (size_t i = 0; i < sizeof(stores) / sizeof(stores[0]); i++) {
        cond_t non_interruptor;
        scoped_ptr_t<fifo_enforcer_sink_t::exit_write_t> token;
        stores[i]->new_write_token(&token);
        stores[i]->set_metainfo(
            region_map_t<dummy_protocol_t, binary_blob_t>(region,
                                                          binary_blob_t(version_range_t(version_t(dummy_branch_id, timestamp)))),
            order_source.check_in(strprintf("set_metainfo(i=%zu)", i)),
            &token,
            &non_interruptor);
    }

    // Insert 10 values into both stores, then another 10 into only `backfiller_store` and not `backfillee_store`
    for (int i = 0; i < 20; i++) {
        dummy_protocol_t::write_t w;
        std::string key = std::string(1, 'a' + randint(26));
        w.values[key] = strprintf("%d", i);

        for (int j = 0; j < (i < 10 ? 2 : 1); j++) {
            transition_timestamp_t ts = transition_timestamp_t::starting_from(timestamp);
            timestamp = ts.timestamp_after();

            cond_t non_interruptor;
            scoped_ptr_t<fifo_enforcer_sink_t::exit_write_t> token;
            backfiller_store.new_write_token(&token);

#ifndef NDEBUG
            mock::equality_metainfo_checker_callback_t<dummy_protocol_t>
                metainfo_checker_callback(binary_blob_t(version_range_t(version_t(dummy_branch_id, ts.timestamp_before()))));
            metainfo_checker_t<dummy_protocol_t> metainfo_checker(&metainfo_checker_callback, region);
#endif

            backfiller_store.write(
                DEBUG_ONLY(metainfo_checker, )
                region_map_t<dummy_protocol_t, binary_blob_t>(
                    region,
                    binary_blob_t(version_range_t(version_t(dummy_branch_id, timestamp)))
                ),
                w, ts,
                order_source.check_in(strprintf("backfiller_store.write(j=%d)", j)),
                &token,
                &non_interruptor
            );
        }
    }

    // Set up a cluster so mailboxes can be created

    mock::simple_mailbox_cluster_t cluster;

    /* Expose the backfiller to the cluster */

    store_view_t<dummy_protocol_t> *backfiller_store_ptr = &backfiller_store;
    multistore_ptr_t<dummy_protocol_t> backfiller_multistore(&backfiller_store_ptr, 1);

    backfiller_t<dummy_protocol_t> backfiller(
        cluster.get_mailbox_manager(),
        &branch_history_manager,
        &backfiller_multistore);

    watchable_variable_t<boost::optional<backfiller_business_card_t<dummy_protocol_t> > > pseudo_directory(
        boost::optional<backfiller_business_card_t<dummy_protocol_t> >(backfiller.get_business_card()));

    /* Run a backfill */

    // Uhh.. hehhehheh... this might be wrong.
    store_view_t<dummy_protocol_t> *backfillee_store_ptr = &backfillee_store;
    multistore_ptr_t<dummy_protocol_t> backfillee_multistore(&backfillee_store_ptr, 1);

    cond_t interruptor;
    backfillee<dummy_protocol_t>(
        cluster.get_mailbox_manager(),
        &branch_history_manager,
        &backfillee_multistore,
        backfillee_store.get_region(),
        pseudo_directory.get_watchable()->subview(&wrap_in_optional),
        generate_uuid(),
        &interruptor);

    /* Make sure everything got transferred properly */

    for (char c = 'a'; c <= 'z'; c++) {
        std::string key(1, c);
        EXPECT_EQ(backfiller_store.values[key], backfillee_store.values[key]);
        EXPECT_TRUE(backfiller_store.timestamps[key] == backfillee_store.timestamps[key]);
    }

    scoped_ptr_t<fifo_enforcer_sink_t::exit_read_t> token1;
    backfillee_store.new_read_token(&token1);

    region_map_t<dummy_protocol_t, binary_blob_t> untransformed_backfillee_metadata;
    backfillee_store.do_get_metainfo(order_source.check_in("backfillee_store.do_get_metainfo").with_read_mode(),
                                     &token1, &interruptor, &untransformed_backfillee_metadata);

    region_map_t<dummy_protocol_t, version_range_t> backfillee_metadata =
        region_map_transform<dummy_protocol_t, binary_blob_t, version_range_t>(
            untransformed_backfillee_metadata,
            &binary_blob_t::get<version_range_t>
        );

    scoped_ptr_t<fifo_enforcer_sink_t::exit_read_t> token2;
    backfiller_store.new_read_token(&token2);

    region_map_t<dummy_protocol_t, binary_blob_t> untransformed_backfiller_metadata;
    backfiller_store.do_get_metainfo(order_source.check_in("backfiller_store.do_get_metainfo").with_read_mode(),
                                     &token2, &interruptor, &untransformed_backfiller_metadata);

    region_map_t<dummy_protocol_t, version_range_t> backfiller_metadata =
        region_map_transform<dummy_protocol_t, binary_blob_t, version_range_t>(
            untransformed_backfiller_metadata,
            &binary_blob_t::get<version_range_t>
        );

    EXPECT_TRUE(backfillee_metadata == backfiller_metadata);

    //EXPECT_EQ(1, backfillee_metadata.size());
    //EXPECT_TRUE(backfillee_metadata[0].second.is_coherent());
    //EXPECT_EQ(timestamp, backfillee_metadata[0].second.earliest.timestamp);
}
TEST(ClusteringBackfill, BackfillTest) {
    mock::run_in_thread_pool(&run_backfill_test);
}

}   /* namespace unittest */
<|endoftext|>


<commit_before>/*
Copyright (c) 2016 Bastien Durix

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

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

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

/**
 *  \brief Provides tests for skeleton library
 *  \author Bastien Durix
 */

#include <iostream>
#include <math.h>

#include <cstdlib>

#include <skeleton/GraphCurveSkeleton.h>
#include <skeleton/model/Classic.h>
#include <mathtools/geometry/euclidian/HyperSphere.h>

using namespace mathtools::affine;
using namespace mathtools::geometry::euclidian;

int main()
{
	unsigned int return_value = 0;

	// frame creation
	Frame<2>::Ptr frame = Frame<2>::CreateFrame(Eigen::Vector2d(1.0,0.0),Eigen::Vector2d(2.0,1.0),Eigen::Vector2d(1.0,0.0));

	// model creation
	skeleton::model::Classic<2>::Ptr modclass(new skeleton::model::Classic<2>{frame});

	// creating a random node
	Eigen::Vector3d vec3((double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0);

	// skeleton creation
	skeleton::GraphCurveSkeleton<skeleton::model::Classic<2> > skel(modclass);

	std::cout << "Adding Node test... ";

	// adding a node
	unsigned int ind = skel.addNode(vec3);

	// getting the node (vector form)
	Eigen::Vector3d vec3_2 = skel.getNode(ind);

	if(vec3_2.isApprox(vec3,std::numeric_limits<double>::epsilon()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Getter test... ";

	// getting the node (center form)
	Point<2> pt = skel.getNode<Point<2> >(ind);

	if(pt.getCoords().isApprox(frame->getBasis()->getMatrix()*vec3.block<2,1>(0,0)+frame->getOrigin()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// hypersphere creation
	HyperSphere<2> sph(Point<2>(1.0,0.0),5.0,frame);

	std::cout << "Adding Sphere test... ";

	// adding a node
	unsigned int ind2 = skel.addNode<HyperSphere<2> >(sph);

	// get the vector associated to the node
	Eigen::Vector3d vecsph = skel.getNode(ind2);

	// convert the node to a sphere
	HyperSphere<2> sphcpy = skel.getModel()->toObj<HyperSphere<2> >(vecsph);

	if(sphcpy.getCenter().getCoords().isApprox(sph.getCenter().getCoords(),std::numeric_limits<double>::epsilon() &&
	   sphcpy.getRadius() == sph.getRadius() &&
	   sphcpy.getFrame()->getBasis()->getMatrix().isApprox(sph.getFrame()->getBasis()->getMatrix(),std::numeric_limits<double>::epsilon())) &&
	   ind != ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// get all indices
	std::list<unsigned int> listnod;

	std::cout << "Get all nodes... ";
	skel.getAllNodes(listnod);

	listnod.unique();

	if(listnod.size() == 2 &&
	   std::find(listnod.begin(),listnod.end(),ind) != listnod.end() &&
	   std::find(listnod.begin(),listnod.end(),ind2) != listnod.end())
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Adding edge test... ";

	// adding an edge
	skel.addEdge(ind, ind2);

	std::list<unsigned int> neigh;
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 1 && *(neigh.begin()) == ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Removing edge test... ";

	// removing an edge
	skel.remEdge(ind, ind2);

	neigh.erase(neigh.begin(),neigh.end());
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 0)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	return return_value;
}
<commit_msg>Added removing node test<commit_after>/*
Copyright (c) 2016 Bastien Durix

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

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

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

/**
 *  \brief Provides tests for skeleton library
 *  \author Bastien Durix
 */

#include <iostream>
#include <math.h>

#include <cstdlib>

#include <skeleton/GraphCurveSkeleton.h>
#include <skeleton/model/Classic.h>
#include <mathtools/geometry/euclidian/HyperSphere.h>

using namespace mathtools::affine;
using namespace mathtools::geometry::euclidian;

int main()
{
	unsigned int return_value = 0;

	// frame creation
	Frame<2>::Ptr frame = Frame<2>::CreateFrame(Eigen::Vector2d(1.0,0.0),Eigen::Vector2d(2.0,1.0),Eigen::Vector2d(1.0,0.0));

	// model creation
	skeleton::model::Classic<2>::Ptr modclass(new skeleton::model::Classic<2>{frame});

	// creating a random node
	Eigen::Vector3d vec3((double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0-1.0,
						 (double)(rand()%201)/10.0);

	// skeleton creation
	skeleton::GraphCurveSkeleton<skeleton::model::Classic<2> > skel(modclass);

	std::cout << "Adding Node test... ";

	// adding a node
	unsigned int ind = skel.addNode(vec3);

	// getting the node (vector form)
	Eigen::Vector3d vec3_2 = skel.getNode(ind);

	if(vec3_2.isApprox(vec3,std::numeric_limits<double>::epsilon()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Getter test... ";

	// getting the node (center form)
	Point<2> pt = skel.getNode<Point<2> >(ind);

	if(pt.getCoords().isApprox(frame->getBasis()->getMatrix()*vec3.block<2,1>(0,0)+frame->getOrigin()))
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// hypersphere creation
	HyperSphere<2> sph(Point<2>(1.0,0.0),5.0,frame);

	std::cout << "Adding Sphere test... ";

	// adding a node
	unsigned int ind2 = skel.addNode<HyperSphere<2> >(sph);

	// get the vector associated to the node
	Eigen::Vector3d vecsph = skel.getNode(ind2);

	// convert the node to a sphere
	HyperSphere<2> sphcpy = skel.getModel()->toObj<HyperSphere<2> >(vecsph);

	if(sphcpy.getCenter().getCoords().isApprox(sph.getCenter().getCoords(),std::numeric_limits<double>::epsilon() &&
	   sphcpy.getRadius() == sph.getRadius() &&
	   sphcpy.getFrame()->getBasis()->getMatrix().isApprox(sph.getFrame()->getBasis()->getMatrix(),std::numeric_limits<double>::epsilon())) &&
	   ind != ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	// get all indices
	std::list<unsigned int> listnod;

	std::cout << "Get all nodes... ";
	skel.getAllNodes(listnod);

	listnod.unique();

	if(listnod.size() == 2 &&
	   std::find(listnod.begin(),listnod.end(),ind) != listnod.end() &&
	   std::find(listnod.begin(),listnod.end(),ind2) != listnod.end())
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Adding edge test... ";

	// adding an edge
	skel.addEdge(ind, ind2);

	std::list<unsigned int> neigh;
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 1 && *(neigh.begin()) == ind2)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Removing edge test... ";

	// removing an edge
	skel.remEdge(ind, ind2);

	neigh.erase(neigh.begin(),neigh.end());
	skel.getNeighbors(ind,neigh);

	if(neigh.size() == 0)
	{
		std::cout << "Success!" << std::endl;
	}
	else
	{
		return_value = -1;
		std::cout << "Fail!" << std::endl;
	}

	std::cout << "Removing node test... ";
	skel.remNode(ind);

	try
	{
		skel.getNode(ind);
		std::cout << "Fail!" << std::endl;
	}
	catch(...)
	{
		std::cout << "Success!" << std::endl;
	}

	return return_value;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP)
#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP

#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

class XMLBufferFullHandler;

/**
 *  XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is
 *  inherently theoretically unbounded in terms of the sizes of things, we
 *  very often need to have expandable buffers. The primary concern here is
 *  that appends of characters and other buffers or strings be very fast, so
 *  it always maintains the current buffer size.
 *
 *  The buffer is not null terminated until some asks to see the raw buffer
 *  contents. This also avoids overhead during append operations.
 */
class XMLPARSER_EXPORT XMLBuffer : public XMemory
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructor */
    //@{
    XMLBuffer(const XMLSize_t capacity = 1023
              , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :

        fIndex(0)
        , fCapacity(capacity)
        , fFullSize(0)
        , fUsed(false)
        , fMemoryManager(manager)
        , fFullHandler(0)
        , fBuffer(0)
    {
        // Buffer is one larger than capacity, to allow for zero term
        fBuffer = (XMLCh*) manager->allocate((capacity+1) * sizeof(XMLCh)); //new XMLCh[fCapacity+1];

        // Keep it null terminated
        fBuffer[0] = XMLCh(0);
    }
    //@}

    /** @name Destructor */
    //@{
    ~XMLBuffer()
    {
        fMemoryManager->deallocate(fBuffer); //delete [] fBuffer;
    }
    //@}

    // -----------------------------------------------------------------------
    //  Buffer Full Handler Management
    // -----------------------------------------------------------------------
    void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize)
    {
        if (handler && fullSize) {
            fFullHandler = handler;
            fFullSize = fullSize;

            // Need to consider the case that the fullsize is less than the current capacity.
            // For example, say fullSize = 100 and fCapacity is 1023 (the default).
            // If the fIndex is less than the fullSize, then no problem.  We can just carry
            // on by resetting fCapacity to fullsize and proceed business as usual.
            // If the fIndex is already bigger than the fullSize then we call insureCapacity
            // to see if it can handle emptying the current buffer (it will throw an
            // exception if it can't).
            if (fullSize < fCapacity) {
                fCapacity = fullSize;
                if (fIndex >= fullSize) {
                    insureCapacity(0);
                }
            }
        }
        else {
            // reset fFullHandler to zero because setFullHandler had bad input
            fFullHandler = 0;
        }
    }

    // -----------------------------------------------------------------------
    //  Buffer Management
    // -----------------------------------------------------------------------
    void append(const XMLCh toAppend)
    {
        // Put in char and bump the index
        if (fIndex == fCapacity)
            insureCapacity(1);
        fBuffer[fIndex++] = toAppend;
    }

    void append (const XMLCh* const chars, const XMLSize_t count)
    {
        if (count) {
            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
        else {
            append(chars);
        }
    }

    void append (const XMLCh* const chars)
    {
        if (chars != 0 && *chars != 0) {
            // get length of chars
            XMLSize_t count = 0;
            for (; *(chars+count); count++ );

            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
    }

    void set (const XMLCh* const chars, const XMLSize_t count)
    {
        fIndex = 0;
        append(chars, count);
    }

    void set (const XMLCh* const chars)
    {
        fIndex = 0;
        if (chars != 0 && *chars != 0)
            append(chars);
    }

    const XMLCh* getRawBuffer() const
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    XMLCh* getRawBuffer()
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    void reset()
    {
        fIndex = 0;
    }

    // -----------------------------------------------------------------------
    //  Getters
    // -----------------------------------------------------------------------
    bool getInUse() const
    {
        return fUsed;
    }

    XMLSize_t getLen() const
    {
        return fIndex;
    }

    bool isEmpty() const
    {
        return (fIndex == 0);
    }

    // -----------------------------------------------------------------------
    //  Setters
    // -----------------------------------------------------------------------
    void setInUse(const bool newValue)
    {
        fUsed = newValue;
    }

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    XMLBuffer(const XMLBuffer&);
    XMLBuffer& operator=(const XMLBuffer&);

    // -----------------------------------------------------------------------
    //  Declare our friends
    // -----------------------------------------------------------------------
    friend class XMLBufBid;

    // -----------------------------------------------------------------------
    //  Private helpers
    // -----------------------------------------------------------------------
    void insureCapacity(const XMLSize_t extraNeeded);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fBuffer
    //      The pointer to the buffer data. Its grown as needed. Its always
    //      one larger than fCapacity, to leave room for the null terminator.
    //
    //  fIndex
    //      The current index into the buffer, as characters are appended
    //      to it. If its zero, then the buffer is empty.
    //
    //  fCapacity
    //      The current capacity of the buffer. Its actually always one
    //      larger, to leave room for the null terminator.
    //
    //  fUsed
    //      Indicates whether this buffer is in use or not.
    //
    //  fFullHandler, fFullSize
    //      If fFullHandler is non-null, the buffer has a maximum size
    //      indicated by fFullSize. If writing to the buffer would exceed the
    //      buffer's maximum size, fFullHandler's bufferFull callback is
    //      invoked, to empty the buffer.
    // -----------------------------------------------------------------------
    XMLSize_t                   fIndex;
    XMLSize_t                   fCapacity;
    XMLSize_t                   fFullSize;
    bool                        fUsed;
    MemoryManager* const        fMemoryManager;
    XMLBufferFullHandler*       fFullHandler;
    XMLCh*                      fBuffer;
};

/**
 *  XMLBufferFullHandler is a callback interface for clients of
 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
 *  Note that this is intended solely as a mix-in for internal
 *  use, and therefore does not derive from XMemory (to avoid
 *  the ambiguous base class problem).
 */
class XMLPARSER_EXPORT XMLBufferFullHandler
{
public :

    virtual ~XMLBufferFullHandler() {}

    /**
     * Callback method, intended to allow clients of an XMLBuffer which has
     * become full to empty it appropriately.
     * @return true if the handler was able to empty the buffer (either
     * partially or completely), otherwise false to indicate an error.
     */
    virtual bool bufferFull(XMLBuffer&) = 0;

};

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>Suppress new warnings introduced in g++ 4.3.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP)
#define XERCESC_INCLUDE_GUARD_XMLBUFFER_HPP

#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

class XMLBufferFullHandler;

/**
 *  XMLBuffer is a lightweight, expandable Unicode text buffer. Since XML is
 *  inherently theoretically unbounded in terms of the sizes of things, we
 *  very often need to have expandable buffers. The primary concern here is
 *  that appends of characters and other buffers or strings be very fast, so
 *  it always maintains the current buffer size.
 *
 *  The buffer is not null terminated until some asks to see the raw buffer
 *  contents. This also avoids overhead during append operations.
 */
class XMLPARSER_EXPORT XMLBuffer : public XMemory
{
public :
    // -----------------------------------------------------------------------
    //  Constructors and Destructor
    // -----------------------------------------------------------------------

    /** @name Constructor */
    //@{
    XMLBuffer(const XMLSize_t capacity = 1023
              , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager) :

        fIndex(0)
        , fCapacity(capacity)
        , fFullSize(0)
        , fUsed(false)
        , fMemoryManager(manager)
        , fFullHandler(0)
        , fBuffer(0)
    {
        // Buffer is one larger than capacity, to allow for zero term
        fBuffer = (XMLCh*) manager->allocate((capacity+1) * sizeof(XMLCh)); //new XMLCh[fCapacity+1];

        // Keep it null terminated
        fBuffer[0] = XMLCh(0);
    }
    //@}

    /** @name Destructor */
    //@{
    ~XMLBuffer()
    {
        fMemoryManager->deallocate(fBuffer); //delete [] fBuffer;
    }
    //@}

    // -----------------------------------------------------------------------
    //  Buffer Full Handler Management
    // -----------------------------------------------------------------------
    void setFullHandler(XMLBufferFullHandler* handler, const XMLSize_t fullSize)
    {
        if (handler && fullSize) {
            fFullHandler = handler;
            fFullSize = fullSize;

            // Need to consider the case that the fullsize is less than the current capacity.
            // For example, say fullSize = 100 and fCapacity is 1023 (the default).
            // If the fIndex is less than the fullSize, then no problem.  We can just carry
            // on by resetting fCapacity to fullsize and proceed business as usual.
            // If the fIndex is already bigger than the fullSize then we call insureCapacity
            // to see if it can handle emptying the current buffer (it will throw an
            // exception if it can't).
            if (fullSize < fCapacity) {
                fCapacity = fullSize;
                if (fIndex >= fullSize) {
                    insureCapacity(0);
                }
            }
        }
        else {
            // reset fFullHandler to zero because setFullHandler had bad input
            fFullHandler = 0;
        }
    }

    // -----------------------------------------------------------------------
    //  Buffer Management
    // -----------------------------------------------------------------------
    void append(const XMLCh toAppend)
    {
        // Put in char and bump the index
        if (fIndex == fCapacity)
            insureCapacity(1);
        fBuffer[fIndex++] = toAppend;
    }

    void append (const XMLCh* const chars, const XMLSize_t count)
    {
        if (count) {
            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
        else {
            append(chars);
        }
    }

    void append (const XMLCh* const chars)
    {
        if (chars != 0 && *chars != 0) {
            // get length of chars
            XMLSize_t count = 0;
            for (; *(chars+count); count++ ) /*noop*/;

            if (fIndex + count >= fCapacity) {
                insureCapacity(count);
            }
            memcpy(&fBuffer[fIndex], chars, count * sizeof(XMLCh));
            fIndex += count;
        }
    }

    void set (const XMLCh* const chars, const XMLSize_t count)
    {
        fIndex = 0;
        append(chars, count);
    }

    void set (const XMLCh* const chars)
    {
        fIndex = 0;
        if (chars != 0 && *chars != 0)
            append(chars);
    }

    const XMLCh* getRawBuffer() const
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    XMLCh* getRawBuffer()
    {
        fBuffer[fIndex] = 0;
        return fBuffer;
    }

    void reset()
    {
        fIndex = 0;
    }

    // -----------------------------------------------------------------------
    //  Getters
    // -----------------------------------------------------------------------
    bool getInUse() const
    {
        return fUsed;
    }

    XMLSize_t getLen() const
    {
        return fIndex;
    }

    bool isEmpty() const
    {
        return (fIndex == 0);
    }

    // -----------------------------------------------------------------------
    //  Setters
    // -----------------------------------------------------------------------
    void setInUse(const bool newValue)
    {
        fUsed = newValue;
    }

private :
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    XMLBuffer(const XMLBuffer&);
    XMLBuffer& operator=(const XMLBuffer&);

    // -----------------------------------------------------------------------
    //  Declare our friends
    // -----------------------------------------------------------------------
    friend class XMLBufBid;

    // -----------------------------------------------------------------------
    //  Private helpers
    // -----------------------------------------------------------------------
    void insureCapacity(const XMLSize_t extraNeeded);

    // -----------------------------------------------------------------------
    //  Private data members
    //
    //  fBuffer
    //      The pointer to the buffer data. Its grown as needed. Its always
    //      one larger than fCapacity, to leave room for the null terminator.
    //
    //  fIndex
    //      The current index into the buffer, as characters are appended
    //      to it. If its zero, then the buffer is empty.
    //
    //  fCapacity
    //      The current capacity of the buffer. Its actually always one
    //      larger, to leave room for the null terminator.
    //
    //  fUsed
    //      Indicates whether this buffer is in use or not.
    //
    //  fFullHandler, fFullSize
    //      If fFullHandler is non-null, the buffer has a maximum size
    //      indicated by fFullSize. If writing to the buffer would exceed the
    //      buffer's maximum size, fFullHandler's bufferFull callback is
    //      invoked, to empty the buffer.
    // -----------------------------------------------------------------------
    XMLSize_t                   fIndex;
    XMLSize_t                   fCapacity;
    XMLSize_t                   fFullSize;
    bool                        fUsed;
    MemoryManager* const        fMemoryManager;
    XMLBufferFullHandler*       fFullHandler;
    XMLCh*                      fBuffer;
};

/**
 *  XMLBufferFullHandler is a callback interface for clients of
 *  XMLBuffers that impose a size restriction (e.g. XMLScanner).
 *  Note that this is intended solely as a mix-in for internal
 *  use, and therefore does not derive from XMemory (to avoid
 *  the ambiguous base class problem).
 */
class XMLPARSER_EXPORT XMLBufferFullHandler
{
public :

    virtual ~XMLBufferFullHandler() {}

    /**
     * Callback method, intended to allow clients of an XMLBuffer which has
     * become full to empty it appropriately.
     * @return true if the handler was able to empty the buffer (either
     * partially or completely), otherwise false to indicate an error.
     */
    virtual bool bufferFull(XMLBuffer&) = 0;

};

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2021 ScyllaDB Ltd.
 */

#include <iostream>
#include <seastar/websocket/server.hh>
#include <seastar/core/app-template.hh>
#include <seastar/core/fstream.hh>
#include <seastar/core/sleep.hh>
#include <seastar/core/seastar.hh>
#include <seastar/core/loop.hh>
#include <seastar/core/thread.hh>
#include <seastar/util/defer.hh>

using namespace seastar;
using namespace seastar::experimental;

int main(int argc, char** argv) {
    seastar::app_template app;
    app.run(argc, argv, [] () -> seastar::future<> {
        return async([] {
            websocket::server ws;
            ws.register_handler("echo", [] (temporary_buffer<char> &&buf, output_stream<char> &write_buf) {
                return write_buf.write(std::move(buf));
            });
            auto d = defer([&ws] () noexcept {
                ws.stop().get();
            });
            ws.listen(socket_address(ipv4_addr("127.0.0.1", 8123)));
            std::cout << "Listening on 127.0.0.1:8123 for 1 hour (interruptible, hit Ctrl-C to stop)..." << std::endl;
            seastar::sleep_abortable(std::chrono::hours(1)).get();
            std::cout << "Stopping the server, deepest thanks to all clients, hope we meet again" << std::endl;
        });
    });
}
<commit_msg>websocket: update websocket demo<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2021 ScyllaDB Ltd.
 */

#include <iostream>
#include <seastar/websocket/server.hh>
#include <seastar/core/app-template.hh>
#include <seastar/core/fstream.hh>
#include <seastar/core/sleep.hh>
#include <seastar/core/seastar.hh>
#include <seastar/core/loop.hh>
#include <seastar/core/thread.hh>
#include <seastar/util/defer.hh>

using namespace seastar;
using namespace seastar::experimental;

int main(int argc, char** argv) {
    seastar::app_template app;
    app.run(argc, argv, [] () -> seastar::future<> {
        return async([] {
            static websocket::server ws;
            ws.register_handler("echo", [] (input_stream<char>& in,
                        output_stream<char>& out) {
                return repeat([&in, &out]() {
                    return in.read().then([&out](temporary_buffer<char> f) {
                        std::cerr << "f.size(): " << f.size() << "\n";
                        if (f.empty()) {
                            return make_ready_future<stop_iteration>(stop_iteration::yes);
                        } else {
                            return out.write(std::move(f)).then([&out]() {
                                return out.flush().then([] {
                                    return make_ready_future<stop_iteration>(stop_iteration::no);
                                });
                            });
                        }
                    });
                });
            });
            auto d = defer([] () noexcept {
                ws.stop().get();
            });
            ws.listen(socket_address(ipv4_addr("127.0.0.1", 8123)));
            std::cout << "Listening on 127.0.0.1:8123 for 1 hour (interruptible, hit Ctrl-C to stop)..." << std::endl;
            seastar::sleep_abortable(std::chrono::hours(1)).get();
            std::cout << "Stopping the server, deepest thanks to all clients, hope we meet again" << std::endl;
        });
    });
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: giflzwc.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:31:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <tools/stream.hxx>
#include "giflzwc.hxx"

// ----------------------------
// - GIFImageDataOutputStream -
// ----------------------------

class GIFImageDataOutputStream
{
private:

    void        FlushBlockBuf();
    inline void FlushBitsBufsFullBytes();

    SvStream&   rStream;
    BYTE*       pBlockBuf;
    BYTE        nBlockBufSize;
    ULONG       nBitsBuf;
    USHORT      nBitsBufSize;

public:

                GIFImageDataOutputStream( SvStream & rGIF, BYTE nLZWDataSize );
                ~GIFImageDataOutputStream();

    inline void WriteBits( USHORT nCode, USHORT nCodeLen );
};

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

inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
{
    while (nBitsBufSize>=8)
    {
        if( nBlockBufSize==255 )
            FlushBlockBuf();

        pBlockBuf[nBlockBufSize++] = (BYTE) nBitsBuf;
        nBitsBuf >>= 8;
        nBitsBufSize -= 8;
    }
}

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

inline void GIFImageDataOutputStream::WriteBits( USHORT nCode, USHORT nCodeLen )
{
    if( nBitsBufSize+nCodeLen>32 )
        FlushBitsBufsFullBytes();

    nBitsBuf |= (ULONG) nCode << nBitsBufSize;
    nBitsBufSize += nCodeLen;
}

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

GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, BYTE nLZWDataSize ) :
        rStream(rGIF)
{
    pBlockBuf = new BYTE[ 255 ];
    nBlockBufSize = 0;
    nBitsBufSize = 0;
    nBitsBuf = 0;
    rStream << nLZWDataSize;
}

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

GIFImageDataOutputStream::~GIFImageDataOutputStream()
{
    WriteBits(0,7);
    FlushBitsBufsFullBytes();
    FlushBlockBuf();
    rStream << (BYTE)0;
    delete[] pBlockBuf;
}

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

void GIFImageDataOutputStream::FlushBlockBuf()
{
    if( nBlockBufSize )
    {
        rStream << (BYTE) nBlockBufSize;
        rStream.Write( pBlockBuf,nBlockBufSize );
        nBlockBufSize = 0;
    }
}

// -------------------
// - GIFLZWCTreeNode -
// -------------------

struct GIFLZWCTreeNode
{

    GIFLZWCTreeNode*    pBrother;       // naechster Knoten, der den selben Vater hat
    GIFLZWCTreeNode*    pFirstChild;    // erster Sohn
    USHORT              nCode;          // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
    USHORT              nValue;         // Der Pixelwert
};

// --------------------
// - GIFLZWCompressor -
// --------------------

GIFLZWCompressor::GIFLZWCompressor()
{
    pIDOS=NULL;
}

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

GIFLZWCompressor::~GIFLZWCompressor()
{
    if (pIDOS!=NULL) EndCompression();
}

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

void GIFLZWCompressor::StartCompression( SvStream& rGIF, USHORT nPixelSize )
{
    if( !pIDOS )
    {
        USHORT i;

        nDataSize = nPixelSize;

        if( nDataSize < 2 )
            nDataSize=2;

        nClearCode=1<<nDataSize;
        nEOICode=nClearCode+1;
        nTableSize=nEOICode+1;
        nCodeSize=nDataSize+1;

        pIDOS=new GIFImageDataOutputStream(rGIF,(BYTE)nDataSize);
        pTable=new GIFLZWCTreeNode[4096];

        for (i=0; i<4096; i++)
        {
            pTable[i].pBrother = pTable[i].pFirstChild = NULL;
            pTable[i].nValue = (BYTE) ( pTable[i].nCode = i );
        }

        pPrefix = NULL;
        pIDOS->WriteBits( nClearCode,nCodeSize );
    }
}

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

void GIFLZWCompressor::Compress( HPBYTE pSrc, ULONG nSize )
{
    if( pIDOS )
    {
        GIFLZWCTreeNode*    p;
        USHORT              i;
        BYTE                nV;

        if( !pPrefix && nSize )
        {
            pPrefix=pTable+(*pSrc++);
            nSize--;
        }

        while( nSize )
        {
            nSize--;
            nV=*pSrc++;
            for( p=pPrefix->pFirstChild; p!=NULL; p=p->pBrother )
            {
                if (p->nValue==nV)
                    break;
            }

            if( p)
                pPrefix=p;
            else
            {
                pIDOS->WriteBits(pPrefix->nCode,nCodeSize);

                if (nTableSize==4096)
                {
                    pIDOS->WriteBits(nClearCode,nCodeSize);

                    for (i=0; i<nClearCode; i++)
                        pTable[i].pFirstChild=NULL;

                    nCodeSize=nDataSize+1;
                    nTableSize=nEOICode+1;
                }
                else
                {
                    if(nTableSize==(USHORT)(1<<nCodeSize))
                        nCodeSize++;

                    p=pTable+(nTableSize++);
                    p->pBrother=pPrefix->pFirstChild;
                    pPrefix->pFirstChild=p;
                    p->nValue=nV;
                    p->pFirstChild=NULL;
                }

                pPrefix=pTable+nV;
            }
        }
    }
}

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

void GIFLZWCompressor::EndCompression()
{
    if( pIDOS )
    {
        if( pPrefix )
            pIDOS->WriteBits(pPrefix->nCode,nCodeSize);

        pIDOS->WriteBits( nEOICode,nCodeSize );
        delete[] pTable;
        delete pIDOS;
        pIDOS=NULL;
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.2.118); FILE MERGED 2006/09/01 17:30:02 kaib 1.2.118.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: giflzwc.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 15:41:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_goodies.hxx"

#include <tools/stream.hxx>
#include "giflzwc.hxx"

// ----------------------------
// - GIFImageDataOutputStream -
// ----------------------------

class GIFImageDataOutputStream
{
private:

    void        FlushBlockBuf();
    inline void FlushBitsBufsFullBytes();

    SvStream&   rStream;
    BYTE*       pBlockBuf;
    BYTE        nBlockBufSize;
    ULONG       nBitsBuf;
    USHORT      nBitsBufSize;

public:

                GIFImageDataOutputStream( SvStream & rGIF, BYTE nLZWDataSize );
                ~GIFImageDataOutputStream();

    inline void WriteBits( USHORT nCode, USHORT nCodeLen );
};

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

inline void GIFImageDataOutputStream::FlushBitsBufsFullBytes()
{
    while (nBitsBufSize>=8)
    {
        if( nBlockBufSize==255 )
            FlushBlockBuf();

        pBlockBuf[nBlockBufSize++] = (BYTE) nBitsBuf;
        nBitsBuf >>= 8;
        nBitsBufSize -= 8;
    }
}

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

inline void GIFImageDataOutputStream::WriteBits( USHORT nCode, USHORT nCodeLen )
{
    if( nBitsBufSize+nCodeLen>32 )
        FlushBitsBufsFullBytes();

    nBitsBuf |= (ULONG) nCode << nBitsBufSize;
    nBitsBufSize += nCodeLen;
}

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

GIFImageDataOutputStream::GIFImageDataOutputStream( SvStream & rGIF, BYTE nLZWDataSize ) :
        rStream(rGIF)
{
    pBlockBuf = new BYTE[ 255 ];
    nBlockBufSize = 0;
    nBitsBufSize = 0;
    nBitsBuf = 0;
    rStream << nLZWDataSize;
}

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

GIFImageDataOutputStream::~GIFImageDataOutputStream()
{
    WriteBits(0,7);
    FlushBitsBufsFullBytes();
    FlushBlockBuf();
    rStream << (BYTE)0;
    delete[] pBlockBuf;
}

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

void GIFImageDataOutputStream::FlushBlockBuf()
{
    if( nBlockBufSize )
    {
        rStream << (BYTE) nBlockBufSize;
        rStream.Write( pBlockBuf,nBlockBufSize );
        nBlockBufSize = 0;
    }
}

// -------------------
// - GIFLZWCTreeNode -
// -------------------

struct GIFLZWCTreeNode
{

    GIFLZWCTreeNode*    pBrother;       // naechster Knoten, der den selben Vater hat
    GIFLZWCTreeNode*    pFirstChild;    // erster Sohn
    USHORT              nCode;          // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
    USHORT              nValue;         // Der Pixelwert
};

// --------------------
// - GIFLZWCompressor -
// --------------------

GIFLZWCompressor::GIFLZWCompressor()
{
    pIDOS=NULL;
}

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

GIFLZWCompressor::~GIFLZWCompressor()
{
    if (pIDOS!=NULL) EndCompression();
}

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

void GIFLZWCompressor::StartCompression( SvStream& rGIF, USHORT nPixelSize )
{
    if( !pIDOS )
    {
        USHORT i;

        nDataSize = nPixelSize;

        if( nDataSize < 2 )
            nDataSize=2;

        nClearCode=1<<nDataSize;
        nEOICode=nClearCode+1;
        nTableSize=nEOICode+1;
        nCodeSize=nDataSize+1;

        pIDOS=new GIFImageDataOutputStream(rGIF,(BYTE)nDataSize);
        pTable=new GIFLZWCTreeNode[4096];

        for (i=0; i<4096; i++)
        {
            pTable[i].pBrother = pTable[i].pFirstChild = NULL;
            pTable[i].nValue = (BYTE) ( pTable[i].nCode = i );
        }

        pPrefix = NULL;
        pIDOS->WriteBits( nClearCode,nCodeSize );
    }
}

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

void GIFLZWCompressor::Compress( HPBYTE pSrc, ULONG nSize )
{
    if( pIDOS )
    {
        GIFLZWCTreeNode*    p;
        USHORT              i;
        BYTE                nV;

        if( !pPrefix && nSize )
        {
            pPrefix=pTable+(*pSrc++);
            nSize--;
        }

        while( nSize )
        {
            nSize--;
            nV=*pSrc++;
            for( p=pPrefix->pFirstChild; p!=NULL; p=p->pBrother )
            {
                if (p->nValue==nV)
                    break;
            }

            if( p)
                pPrefix=p;
            else
            {
                pIDOS->WriteBits(pPrefix->nCode,nCodeSize);

                if (nTableSize==4096)
                {
                    pIDOS->WriteBits(nClearCode,nCodeSize);

                    for (i=0; i<nClearCode; i++)
                        pTable[i].pFirstChild=NULL;

                    nCodeSize=nDataSize+1;
                    nTableSize=nEOICode+1;
                }
                else
                {
                    if(nTableSize==(USHORT)(1<<nCodeSize))
                        nCodeSize++;

                    p=pTable+(nTableSize++);
                    p->pBrother=pPrefix->pFirstChild;
                    pPrefix->pFirstChild=p;
                    p->nValue=nV;
                    p->pFirstChild=NULL;
                }

                pPrefix=pTable+nV;
            }
        }
    }
}

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

void GIFLZWCompressor::EndCompression()
{
    if( pIDOS )
    {
        if( pPrefix )
            pIDOS->WriteBits(pPrefix->nCode,nCodeSize);

        pIDOS->WriteBits( nEOICode,nCodeSize );
        delete[] pTable;
        delete pIDOS;
        pIDOS=NULL;
    }
}
<|endoftext|>


<commit_before>// Time:  O((logn)^2)
// Space: O(1)

class Solution {
public:
    int preimageSizeFZF(int K) {
        const int p = 5;
        int left = 0, right = p * K;
        while (left <= right) {
            const int mid = left + (right - left) / 2;
            if (countOfFactorialPrimes(mid, p) >= K) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        if (countOfFactorialPrimes(left, p) != K) {
            return 0;
        }
        return (left / p + 1) * p - left;
    }

private:
    int countOfFactorialPrimes(int n, int p) {
        int cnt = 0;
        for (; n > 0; n /= p) {
            cnt += n / p;
        }
        return cnt;
    }
};
<commit_msg>Update preimage-size-of-factorial-zeroes-function.cpp<commit_after>// Time:  O((logn)^2)
// Space: O(1)

class Solution {
public:
    int preimageSizeFZF(int K) {
        const int p = 5;
        int left = 0, right = p * K;
        while (left <= right) {
            const int mid = left + (right - left) / 2;
            if (countOfFactorialPrimes(mid, p) >= K) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return countOfFactorialPrimes(left, p) == K ?
            (left / p + 1) * p - left : 0;
    }

private:
    int countOfFactorialPrimes(int n, int p) {
        int cnt = 0;
        for (; n > 0; n /= p) {
            cnt += n / p;
        }
        return cnt;
    }
};
<|endoftext|>


<commit_before>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>
#include <string>
#include <algorithm>

#include <concol.h>

#include "EthernetControl.h"

using namespace std;

// command options functions taken from:
// http://stackoverflow.com/questions/865668/parse-command-line-arguments
string getCmdOption(char ** begin, char ** end, const std::string & option)
{
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end)
  {
    return string(*itr);
  }
  return "";
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
  return std::find(begin, end, option) != end;
}

int main (int argc, char* argv[])
{

  setcolor(red,black);
  cout<<"BBN AP2 Test Executable" << endl;
  setcolor(white,black);

  set_logging_level(5);

  // lookup based on device name
  //string dev("\\Device\\NPF_{F47ACE9E-1961-4A8E-BA14-2564E3764BFA}");

  // lookup based on description
  string dev("Intel(R) 82579LM Gigabit Network Connection");

  set_ethernet_active(const_cast<char*>(dev.c_str()),true);

  int numDevices = get_numDevices();

  setcolor(red,black);
  cout << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << endl;
  setcolor(white,black);

  if (numDevices < 1)
  	return 0;

  setcolor(red,black);
  cout << "Attempting to initialize libaps" << endl;
  setcolor(white,black);

  init();

  setcolor(red,black);
  cout << "Attempting to get serials" << endl;
  setcolor(white,black);

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
    setcolor(red,black);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
    setcolor(white,black);
  }

  int rc;
  rc = connect_by_ID(0);

  setcolor(red,black);
  cout << "connect_by_ID(0) returned " << rc << endl;
  setcolor(white,black);

  rc = initAPS(0, "../dummyBitfile.bit", 0);

  setcolor(red,black);
  cout << "initAPS(0) returned " << rc << endl;
  setcolor(white,black);

#if 0
  cout << "Set sample rate " << endl;

  set_sampleRate(0,100);

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  const int wfs = 1000;
  short wf[wfs];
  for (int cnt = 0; cnt < wfs; cnt++)
    wf[cnt] = (cnt < wfs/2) ? 32767 : -32767;

  cout << "loading waveform" << endl;

  set_waveform_int(0, 0, wf, wfs);

  cout << "Running" << endl;

  set_sampleRate(0,50);

  run(0);

  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << "Stopping" << endl;

  stop(0);

  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;
#endif
  return 0;
}<commit_msg>Enabled remainder of test<commit_after>#include <iostream>

#include "libaps.h"
#include "constants.h"
#include <thread>
#include <string>
#include <algorithm>

#include <concol.h>

#include "EthernetControl.h"

using namespace std;

// command options functions taken from:
// http://stackoverflow.com/questions/865668/parse-command-line-arguments
string getCmdOption(char ** begin, char ** end, const std::string & option)
{
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end)
  {
    return string(*itr);
  }
  return "";
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
  return std::find(begin, end, option) != end;
}

int main (int argc, char* argv[])
{

  setcolor(red,black);
  cout<<"BBN AP2 Test Executable" << endl;
  setcolor(white,black);

  int dbgLevel = 4;
  if (argc >= 2) {
    dbgLevel = atoi(argv[1]);
  }

  set_logging_level(dbgLevel);

  // lookup based on device name
  //string dev("\\Device\\NPF_{F47ACE9E-1961-4A8E-BA14-2564E3764BFA}");

  // lookup based on description
  string dev("Intel(R) 82579LM Gigabit Network Connection");

  set_ethernet_active(const_cast<char*>(dev.c_str()),true);

  int numDevices = get_numDevices();

  setcolor(red,black);
  cout << numDevices << " APS device" << (numDevices > 1 ? "s": "")  << " found" << endl;
  setcolor(white,black);

  if (numDevices < 1)
  	return 0;

  setcolor(red,black);
  cout << "Attempting to initialize libaps" << endl;
  setcolor(white,black);

  init();

  setcolor(red,black);
  cout << "Attempting to get serials" << endl;
  setcolor(white,black);

  char serialBuffer[100];

  for (int cnt; cnt < numDevices; cnt++) {
  	get_deviceSerial(cnt, serialBuffer);
    setcolor(red,black);
  	cout << "Device " << cnt << " serial #: " << serialBuffer << endl;
    setcolor(white,black);
  }

  int rc;
  rc = connect_by_ID(0);

  setcolor(red,black);
  cout << "connect_by_ID(0) returned " << rc << endl;
  setcolor(white,black);

  rc = initAPS(0, "../dummyBitfile.bit", 0);

  setcolor(red,black);
  cout << "initAPS(0) returned " << rc << endl;
  setcolor(white,black);

  cout << "Set sample rate " << endl;

  set_sampleRate(0,100);

  cout << "current PLL frequency = " << get_sampleRate(0) << " MHz" << endl;

  cout << "setting trigger source = EXTERNAL" << endl;

  set_trigger_source(0, EXTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "setting trigger source = INTERNAL" << endl;

  set_trigger_source(0, INTERNAL);

  cout << "get trigger source returns " << ((get_trigger_source(0) == INTERNAL) ? "INTERNAL" : "EXTERNAL") << endl;

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  cout << "set channel(0) enabled = 1" << endl;

  set_channel_enabled(0,0,true);

  const int wfs = 1000;
  short wf[wfs];
  for (int cnt = 0; cnt < wfs; cnt++)
    wf[cnt] = (cnt < wfs/2) ? 32767 : -32767;

  cout << "loading waveform" << endl;

  set_waveform_int(0, 0, wf, wfs);

  cout << "Running" << endl;

  set_sampleRate(0,50);

  run(0);

  std::this_thread::sleep_for(std::chrono::seconds(10));

  cout << "Stopping" << endl;

  stop(0);

  set_channel_enabled(0,0,false);

  cout << "get channel(0) enable: " << get_channel_enabled(0,0) << endl;

  rc = disconnect_by_ID(0);

  cout << "disconnect_by_ID(0) returned " << rc << endl;

  return 0;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ctime>

#ifndef TIMER_HPP
#define TIMER_HPP

namespace isa {
namespace utils {

class Timer {
public:
	Timer();

	void start();
	void stop();
	void reset();

	inline double getTotalTime() const;
	inline double getLastRunTime() const;
	inline double getAverageTime() const;
	inline double getStdDev() const;

private:
	clock_t starting;
	unsigned int nrRuns;
	double totalTime;
	double time;
	double average;
	double stdDev;
};

} // utils
} // isa

#endif // TIMER_HPP

<commit_msg>Still fixing typos.<commit_after>/*
 * Copyright (C) 2013
 * Alessio Sclocco <a.sclocco@vu.nl>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ctime>

#ifndef TIMER_HPP
#define TIMER_HPP

namespace isa {
namespace utils {

class Timer {
public:
	Timer();

	void start();
	void stop();
	void reset();

	inline double getTotalTime() const;
	inline double getLastRunTime() const;
	inline double getAverageTime() const;
	inline double getStdDev() const;

private:
	clock_t starting;
	unsigned int nrRuns;
	double totalTime;
	double time;
	double average;
	double variance;
};

} // utils
} // isa

#endif // TIMER_HPP

<|endoftext|>