<commit_before>/**
 * ofxAppUpdater.cpp is developed by Paul Vollmer
 * http://www.wng.cc
 *
 *
 * Copyright (c) 2012 Paul Vollmer
 *
 * ofxAppUpdater.cpp is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * ofxAppUpdater.cpp 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 ofxAppUpdater.cpp; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @author      Paul Vollmer
 * @modified    2012.04.13
 * @version     1.0.1
 */

#include "ofxAppUpdater.h"

#include "ofxXmlSettings.h"

namespace wng {

	/**
	 * A Constructor, usually called to initialize and start the class.
	 */
	ofxAppUpdater::ofxAppUpdater(){

		// Set the internetConnection variable to false.
		// If you want to manually, set the internetConnection variable,
		// change it at openFrameworks setup.
		internetConnection = false;

		// We use the draw mode to design different ofxAppUpdater mode states.
		// See at example draw.
		drawMode = 0;

		/*
		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "Constructor Ready! ");
		#endif
		*/
	}

	/**
	 * initialize
	 *
	 * @param currentVersion
	 *        The current Application Version.
	 *        Like this: "1.0.0"
	 * @param serverUrl
	 *        The url of the server to load the files.
	 *        Like this: "http://www.wrong-entertainment.com/appupdate"
	 * @param versionInfoXml
	 *        The name of our version information xml file.
	 *        Like this: "versioninfo.xml"
	 * @param latestZip
	 *        The name of the zip file.
	 *        Like this: "latest.zip"
	 */
	void ofxAppUpdater::init(string currentVersion, string serverUrl, string versionInfoXml, string latestZip){

		this->currentVersion = currentVersion;
		this->serverUrl = serverUrl;
		this->versionInfoXml = versionInfoXml;
		this->latestZip = latestZip;

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxAppUpdater] init() Current-Version: " + this->currentVersion + ", Server-Url: " + this->serverUrl + ", Version-Info-XML: " + this->versionInfoXml + ", Latest-ZIP: " + this->latestZip);
		#endif

	}

	/**
	 * checking
	 */
	void ofxAppUpdater::checking(){

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxAppUpdater] check() Start");
		#endif

		// At the moment we create a file at he same directory like the app.
		// after parsing the xml, we remove file.
		string tempFile = ofFilePath::getCurrentWorkingDirectory()+"tempVersionInfo.xml";
		loadFile(serverUrl+versionInfoXml, tempFile);

		ofSleepMillis(200);

		parseXML(tempFile);

		ofSleepMillis(200);

		ofFile tempXmlFile;
		tempXmlFile.removeFile(tempFile, true);

		// Check the Version numbers if it's false, you can download a new version.
		if(checkVersion(currentVersion, latestVersion) == true){
			// go to draw mode 1
			drawMode = 1;

		} else {
			// go to draw mode 2
			drawMode = 2;
		}

	}

	/**
	 *
	 */
	void ofxAppUpdater::downloading(){

		//ofSetLogLevel(OF_LOG_VERBOSE);
		//ofLog(OF_LOG_VERBOSE, "downloading");

		if(drawMode == 2){

			// At the moment we create a file at he same directory like the app.
			//string tempFile = ofFilePath::getPathForDirectory("~/Desktop")+"tempDownloadfile.zip";
			string tempFile = ofFilePath::getPathForDirectory("~/Desktop")+latestZip;

			loadFile(serverUrl+latestZip, tempFile);

			ofSleepMillis(2000);

			drawMode = 3;
		}

	}

	/**
	 *
	 */
	void ofxAppUpdater::restart(){

		if(drawMode == 3){
			//string t = ofFilePath::getPathForDirectory("~/Desktop/")+"tempDownloadfile.zip";
			string tempFile = ofFilePath::getPathForDirectory("~/Desktop/")+latestZip;
			#ifdef OFXAPPUPDATER_LOG
				cout << "unzip <" << tempFile << ">\n";
			#endif

			unzip(tempFile);

			drawMode = 4;

			ofExit(1);
		}
	}

	/**
	 * checkVersion
	 *
	 * @param currentVer
	 *        Float of the Current-Version.
	 * @param latestVer
	 *        Float of the Latest-Version.
	 * @return bool
	 *         True if the Version is the latest.
	 */
	bool ofxAppUpdater::checkVersion(string currentVer, string latestVer){

		if(currentVer == latestVer){

			/*#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] checkVersion() Current-Version: " + ofToString(currentVer) + " Latest-Version: " + ofToString(latestVer));
			ofLog(OF_LOG_VERBOSE, "                            State: You're running the latest Application Release.");
			#endif*/
			return true;

		} else {

			/*#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] checkVersion() Current-Version: " + ofToString(currentVer) + " Latest-Version: " + ofToString(latestVer));
			ofLog(OF_LOG_VERBOSE, "                            State: A new Version is Available.");
			#endif*/
			return false;

		}

	}

	/**
	 * parseXML
	 */
	void ofxAppUpdater::parseXML(string filename){

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] parseXML() Start");
		#endif

		//  Create a new ofxXmlSettings object for reading the saved file.
		ofxXmlSettings xml;

		// We load our xml file.
		// This is based on the openFrameworks xmlSettingsExample.
		if(xml.loadFile(filename)){
			latestVersion = xml.getValue("VERSIONING:VERSION",  "1.0.0", 0);
			modifiedDate  = xml.getValue("VERSIONING:MODIFIED", "1970.01.01", 0);
			author        = xml.getValue("VERSIONING:AUTHOR",   "wng.cc", 0);
			changes       = xml.getValue("VERSIONING:CHANGES",  "nothing", 0);
			#ifdef OFXAPPUPDATER_LOG
			ofLog(OF_LOG_VERBOSE, "parseXML() File <" + filename + "> loaded!");
			ofLog(OF_LOG_VERBOSE, "Latest Version: " + latestVersion);
			ofLog(OF_LOG_VERBOSE, "Modified: " + modifiedDate);
			ofLog(OF_LOG_VERBOSE, "Author: " + author);
			ofLog(OF_LOG_VERBOSE, "Changes: " + changes);
			#endif
		} else {
			#ifdef OFXAPPUPDATER_LOG
				ofLog(OF_LOG_VERBOSE, "parseXML() File <" + filename + "> not found");
			#endif
		}

	}

	/**
	 * loadFile
	 */
	void ofxAppUpdater::loadFile(string serverSrc, string tempFilepath){

		// A path and name for the file we load from server.
		// I think we can handle this as an intern variable.
		//string tempFilename = "tempVersioninfo.xml";

		// Xml file download
		//
		// Soluion 1:
		// use openFrameworks to download our xml file.

		//cout << ofGetTimestampString() << " DOWNLOAD XML FILE START." << endl;
		// Copy our version xml file to data folder.
		//ofSaveURLAsync(serverUrl+versionInfoXml, tempFilename);
		//cout << ofGetTimestampString() << " DOWNLOAD XML FILE READY." << endl;

		// Solution 2:
		// we use applescript to download our xml file.
		//
		// Here is the original applescript
		//
		// tell application "URL Access Scripting"
		// download "http://www.wrong-entertainment.com/code/wngUpdater/versioninfo.xml" to file "/testfile.txt" replacing yes
		// end tell
		string tempApplescript = "osascript -e 'tell app \"URL Access Scripting\" \n download \""+serverSrc+"\" to file \""+tempFilepath+"\" replacing yes \n end tell'";
		system(tempApplescript.c_str());

	}

	/**
	 * unzip
	 */
	void ofxAppUpdater::unzip(string src){

		// unzip file
		#ifdef TARGET_OSX
			// ok gotta be a better way then this,
			// this is what I found...
			string commandStr = "open /Users/wrongMacBookpro/Desktop/"+latestZip;
			system(commandStr.c_str());
		#endif

		ofSleepMillis(4000);

		// Delete downloaded zip file.
		ofFile tempXmlFile;
		tempXmlFile.removeFile("/Users/wrongMacBookpro/Desktop/"+latestZip	, true);

		// Move downloaded file to current working directory.

	}

}
<commit_msg>fixed removeFile path<commit_after>/**
 * ofxAppUpdater.cpp is developed by Paul Vollmer
 * http://www.wng.cc
 *
 *
 * Copyright (c) 2012 Paul Vollmer
 *
 * ofxAppUpdater.cpp is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * ofxAppUpdater.cpp 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 ofxAppUpdater.cpp; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @author      Paul Vollmer
 * @modified    2012.04.13
 * @version     1.0.1
 */

#include "ofxAppUpdater.h"

#include "ofxXmlSettings.h"

namespace wng {

	/**
	 * A Constructor, usually called to initialize and start the class.
	 */
	ofxAppUpdater::ofxAppUpdater(){

		// Set the internetConnection variable to false.
		// If you want to manually, set the internetConnection variable,
		// change it at openFrameworks setup.
		internetConnection = false;

		// We use the draw mode to design different ofxAppUpdater mode states.
		// See at example draw.
		drawMode = 0;

		/*
		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "Constructor Ready! ");
		#endif
		*/
	}

	/**
	 * initialize
	 *
	 * @param currentVersion
	 *        The current Application Version.
	 *        Like this: "1.0.0"
	 * @param serverUrl
	 *        The url of the server to load the files.
	 *        Like this: "http://www.wrong-entertainment.com/appupdate"
	 * @param versionInfoXml
	 *        The name of our version information xml file.
	 *        Like this: "versioninfo.xml"
	 * @param latestZip
	 *        The name of the zip file.
	 *        Like this: "latest.zip"
	 */
	void ofxAppUpdater::init(string currentVersion, string serverUrl, string versionInfoXml, string latestZip){

		this->currentVersion = currentVersion;
		this->serverUrl = serverUrl;
		this->versionInfoXml = versionInfoXml;
		this->latestZip = latestZip;

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxAppUpdater] init() Current-Version: " + this->currentVersion + ", Server-Url: " + this->serverUrl + ", Version-Info-XML: " + this->versionInfoXml + ", Latest-ZIP: " + this->latestZip);
		#endif

	}

	/**
	 * checking
	 */
	void ofxAppUpdater::checking(){

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxAppUpdater] check() Start");
		#endif

		// At the moment we create a file at he same directory like the app.
		// after parsing the xml, we remove file.
		string tempFile = ofFilePath::getCurrentWorkingDirectory()+"tempVersionInfo.xml";
		loadFile(serverUrl+versionInfoXml, tempFile);

		ofSleepMillis(200);

		parseXML(tempFile);

		ofSleepMillis(200);

		ofFile tempXmlFile;
		tempXmlFile.removeFile(tempFile, true);

		// Check the Version numbers if it's false, you can download a new version.
		if(checkVersion(currentVersion, latestVersion) == true){
			// go to draw mode 1
			drawMode = 1;

		} else {
			// go to draw mode 2
			drawMode = 2;
		}

	}

	/**
	 *
	 */
	void ofxAppUpdater::downloading(){

		//ofSetLogLevel(OF_LOG_VERBOSE);
		//ofLog(OF_LOG_VERBOSE, "downloading");

		if(drawMode == 2){

			// At the moment we create a file at he same directory like the app.
			//string tempFile = ofFilePath::getPathForDirectory("~/Desktop")+"tempDownloadfile.zip";
			string tempFile = ofFilePath::getPathForDirectory("~/Desktop")+latestZip;

			loadFile(serverUrl+latestZip, tempFile);

			ofSleepMillis(2000);

			drawMode = 3;
		}

	}

	/**
	 *
	 */
	void ofxAppUpdater::restart(){

		if(drawMode == 3){
			//string t = ofFilePath::getPathForDirectory("~/Desktop/")+"tempDownloadfile.zip";
			string tempFile = ofFilePath::getPathForDirectory("~/Desktop/")+latestZip;
			#ifdef OFXAPPUPDATER_LOG
				cout << "unzip <" << tempFile << ">\n";
			#endif

			unzip(tempFile);

			drawMode = 4;

			ofExit(1);
		}
	}

	/**
	 * checkVersion
	 *
	 * @param currentVer
	 *        Float of the Current-Version.
	 * @param latestVer
	 *        Float of the Latest-Version.
	 * @return bool
	 *         True if the Version is the latest.
	 */
	bool ofxAppUpdater::checkVersion(string currentVer, string latestVer){

		if(currentVer == latestVer){

			/*#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] checkVersion() Current-Version: " + ofToString(currentVer) + " Latest-Version: " + ofToString(latestVer));
			ofLog(OF_LOG_VERBOSE, "                            State: You're running the latest Application Release.");
			#endif*/
			return true;

		} else {

			/*#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] checkVersion() Current-Version: " + ofToString(currentVer) + " Latest-Version: " + ofToString(latestVer));
			ofLog(OF_LOG_VERBOSE, "                            State: A new Version is Available.");
			#endif*/
			return false;

		}

	}

	/**
	 * parseXML
	 */
	void ofxAppUpdater::parseXML(string filename){

		#ifdef OFXAPPUPDATER_LOG
			ofSetLogLevel(OF_LOG_VERBOSE);
			ofLog(OF_LOG_VERBOSE, "[ofxUpdater] parseXML() Start");
		#endif

		//  Create a new ofxXmlSettings object for reading the saved file.
		ofxXmlSettings xml;

		// We load our xml file.
		// This is based on the openFrameworks xmlSettingsExample.
		if(xml.loadFile(filename)){
			latestVersion = xml.getValue("VERSIONING:VERSION",  "1.0.0", 0);
			modifiedDate  = xml.getValue("VERSIONING:MODIFIED", "1970.01.01", 0);
			author        = xml.getValue("VERSIONING:AUTHOR",   "wng.cc", 0);
			changes       = xml.getValue("VERSIONING:CHANGES",  "nothing", 0);
			#ifdef OFXAPPUPDATER_LOG
			ofLog(OF_LOG_VERBOSE, "parseXML() File <" + filename + "> loaded!");
			ofLog(OF_LOG_VERBOSE, "Latest Version: " + latestVersion);
			ofLog(OF_LOG_VERBOSE, "Modified: " + modifiedDate);
			ofLog(OF_LOG_VERBOSE, "Author: " + author);
			ofLog(OF_LOG_VERBOSE, "Changes: " + changes);
			#endif
		} else {
			#ifdef OFXAPPUPDATER_LOG
				ofLog(OF_LOG_VERBOSE, "parseXML() File <" + filename + "> not found");
			#endif
		}

	}

	/**
	 * loadFile
	 */
	void ofxAppUpdater::loadFile(string serverSrc, string tempFilepath){

		// A path and name for the file we load from server.
		// I think we can handle this as an intern variable.
		//string tempFilename = "tempVersioninfo.xml";

		// Xml file download
		//
		// Soluion 1:
		// use openFrameworks to download our xml file.

		//cout << ofGetTimestampString() << " DOWNLOAD XML FILE START." << endl;
		// Copy our version xml file to data folder.
		//ofSaveURLAsync(serverUrl+versionInfoXml, tempFilename);
		//cout << ofGetTimestampString() << " DOWNLOAD XML FILE READY." << endl;

		// Solution 2:
		// we use applescript to download our xml file.
		//
		// Here is the original applescript
		//
		// tell application "URL Access Scripting"
		// download "http://www.wrong-entertainment.com/code/wngUpdater/versioninfo.xml" to file "/testfile.txt" replacing yes
		// end tell
		string tempApplescript = "osascript -e 'tell app \"URL Access Scripting\" \n download \""+serverSrc+"\" to file \""+tempFilepath+"\" replacing yes \n end tell'";
		system(tempApplescript.c_str());

	}

	/**
	 * unzip
	 */
	void ofxAppUpdater::unzip(string src){

		// unzip file
		#ifdef TARGET_OSX
			// ok gotta be a better way then this,
			// this is what I found...
			string commandStr = "open "+src;
			system(commandStr.c_str());
		#endif

		ofSleepMillis(4000);

		// Delete downloaded zip file.
		ofFile tempXmlFile;
		tempXmlFile.removeFile(src, true);

		// Move downloaded file to current working directory.

	}

}
<|endoftext|>


<commit_before>/*
 * Silly subclass of CTreeCtrl just to implement Drag&Drop.
 *
 * Based on MFC sample code from CMNCTRL1
 */

#include "stdafx.h"
#include "MyTreeCtrl.h"
#include "DboxMain.h"
#include "corelib/ItemData.h"
#include "corelib/MyString.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static const TCHAR GROUP_SEP = TCHAR('.');

CMyTreeCtrl::CMyTreeCtrl() : m_bDragging(false), m_pimagelist(NULL)
{
}

CMyTreeCtrl::~CMyTreeCtrl()
{
  delete m_pimagelist;
}

BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
	//{{AFX_MSG_MAP(CMyTreeCtrl)
	ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
	ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
	ON_WM_MOUSEMOVE()
	ON_WM_DESTROY()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMyTreeCtrl::OnDestroy()
{
  CImageList  *pimagelist;

  pimagelist = GetImageList(TVSIL_NORMAL);
  if (pimagelist != NULL) {
    pimagelist->DeleteImageList();
    delete pimagelist;
  }
}

void CMyTreeCtrl::SetNewStyle(long lStyleMask, BOOL bSetBits)
{
  long        lStyleOld;

  lStyleOld = GetWindowLong(m_hWnd, GWL_STYLE);
  lStyleOld &= ~lStyleMask;
  if (bSetBits)
    lStyleOld |= lStyleMask;

  SetWindowLong(m_hWnd, GWL_STYLE, lStyleOld);
  SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
}

void CMyTreeCtrl::UpdateLeafsGroup(HTREEITEM hItem, CString prefix)
{
  // Starting with hItem, update the Group field of all of hItem's
  // children. Called after a label has been edited.
  if (IsLeafNode(hItem)) {
    DWORD itemData = GetItemData(hItem);
    ASSERT(itemData != NULL);
    CItemData *ci = (CItemData *)itemData;
    ci->SetGroup(CMyString(prefix));
  } else { // update prefix with current group name and recurse
    if (!prefix.IsEmpty())
      prefix += GROUP_SEP;
    prefix += GetItemText(hItem);
    HTREEITEM child;
    for(child = GetChildItem(hItem); child != NULL; child = GetNextSiblingItem(child)) {
      UpdateLeafsGroup(child, prefix);
    }
  }
}

void CMyTreeCtrl::OnBeginLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
{
  TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pnmhdr;
  // I thought m_BeginEditText was needed to restore text if desired,
  // but setting *pLResult to FALSE in OnEndLabelEdit suffices
  if (ptvinfo->item.pszText != NULL &&
      ptvinfo->item.pszText[0] != '\0') {
    m_BeginEditText = ptvinfo->item.pszText;
  } else {
    m_BeginEditText = _T("");
  }
  DboxMain *parent = (DboxMain *)GetParent();
  parent->DisableOnEdit(true); // so that Enter doesn't invoke Edit dialog
  *pLResult = FALSE; // TRUE cancels label editing
}

static void splitLeafText(const char *lt, CString &newTitle, CString &newUser)
{
  CString leafText(lt);
  int leftBraceIndex = leafText.Find('[');

  if (leftBraceIndex == -1) {
    newTitle = leafText;
    newUser = _T("");
  } else {
    newTitle = leafText.Left(leftBraceIndex - 1);
    int rightBraceIndex = leafText.Find(']');
    if (rightBraceIndex == -1) {
      newUser = leafText.Mid(leftBraceIndex + 1);
    } else {
      newUser = leafText.Mid(leftBraceIndex + 1, rightBraceIndex - leftBraceIndex - 1);
    }
  }
}

static void makeLeafText(CString &treeDispString, const CString &title, const CString &user)
{
  treeDispString = title;
  if (!user.IsEmpty()) {
    treeDispString += _T(" [");
    treeDispString += user;
    treeDispString += _T("]");
    }
}

void CMyTreeCtrl::OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
{
  static bool inEdit = false;

  if (inEdit) { // happens when edit control manipulated - see below
    inEdit = false;
    *pLResult = TRUE;
    return;
  }
  TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pnmhdr;
  HTREEITEM ti = ptvinfo->item.hItem;
  DboxMain *parent = (DboxMain *)GetParent();
  if (ptvinfo->item.pszText != NULL && // NULL if edit cancelled,
      ptvinfo->item.pszText[0] != '\0') { // empty if text deleted - not allowed
    ptvinfo->item.mask = TVIF_TEXT;
    SetItem(&ptvinfo->item);
    if (IsLeafNode(ptvinfo->item.hItem)) {
      /*
       * Leaf text is of the form: title [user]
       * If edited text contains '[', then the user is updated
       * If not, then the user is retrieved and the leaf is updated
       */
      // Update leaf's title
      DWORD itemData = GetItemData(ti);
      ASSERT(itemData != NULL);
      CItemData *ci = (CItemData *)itemData;
      CString newTitle, newUser;
      splitLeafText(ptvinfo->item.pszText, newTitle, newUser);
      if (newUser.IsEmpty())
	newUser = CString(ci->GetUser());
      CString treeDispString;
      makeLeafText(treeDispString, newTitle, newUser);
      // Following needed to force display to update at this stage.
      inEdit = true; // hack to exit ugly recursion.
      CEdit *ed = EditLabel(ti);
      ASSERT(ed != NULL);
      ed->SetWindowText(treeDispString);
      SetItemText(ti, treeDispString);
      ci->SetTitle(newTitle); ci->SetUser(newUser);
      // update corresponding List text
      DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
      ASSERT(di != NULL);
      int lindex = di->list_index;
      parent->UpdateListItemTitle(lindex, newTitle);
      parent->UpdateListItemUser(lindex, newUser);
    } else {
      // Update all leaf children with new path element
      // prefix is path up to and NOT including renamed node
      CString prefix;
      HTREEITEM parent, current = ti;
      do {
	parent = GetParentItem(current);
	if (parent == NULL) {
	  break;
	}
	current = parent;
	if (!prefix.IsEmpty())
	  prefix = GROUP_SEP + prefix;
	prefix = GetItemText(current) + prefix;
      } while (1);
      UpdateLeafsGroup(ti, prefix);
    }
    // Mark database as modified
    parent->SetChanged(true);
    SortChildren(GetParentItem(ti));
  *pLResult = TRUE;
  } else {
    // restore text
    // (not that this is documented anywhere in MS's docs...)
    *pLResult = FALSE;
  }
  // following has to be done at end of function, since OnBeginLabelEdit
  // may be called (indirectly) from this fuction
  parent->DisableOnEdit(false); // Allow Enter to invoke Edit dialog
}

void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
  if (m_bDragging) {
    UINT                flags;

    ASSERT(m_pimagelist != NULL);
    m_pimagelist->DragMove(point);
    HTREEITEM hitem = HitTest(point, &flags);
    if (hitem != NULL) {
      m_pimagelist->DragLeave(this);
      SelectDropTarget(hitem);
      m_hitemDrop = hitem;
      m_pimagelist->DragEnter(this, point);
    }
  }
  CTreeCtrl::OnMouseMove(nFlags, point);
}

bool CMyTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
{
  do {
    if (hitemChild == hitemSuspectedParent)
      break;
  } while ((hitemChild = GetParentItem(hitemChild)) != NULL);

  return (hitemChild != NULL);
}

bool CMyTreeCtrl::IsLeafNode(HTREEITEM hItem)
{
  // ItemHasChildren() won't work in the general case
  BOOL status;
  int i, dummy;
  status = GetItemImage(hItem, i, dummy);
  ASSERT(status);
  return (i == LEAF);
}

void CMyTreeCtrl::DeleteWithParents(HTREEITEM hItem)
{
  // We don't want nodes that have no children to remain
  HTREEITEM p;
  do {
    p = GetParentItem(hItem);
    DeleteItem(hItem);
    if (ItemHasChildren(p))
      break;
    hItem = p;
  } while (p != TVI_ROOT && p != NULL);
}

CString CMyTreeCtrl::GetGroup(HTREEITEM hItem)
{
  CString retval;
  CString nodeText;
  while (hItem != NULL) {
    nodeText = GetItemText(hItem);
    if (!retval.IsEmpty())
      nodeText += GROUP_SEP;
    retval = nodeText + retval;
    hItem = GetParentItem(hItem);
  }
  return retval;
}

static CMyString GetPathElem(CMyString &path)
{
  // Get first path element and chop it off, i.e., if
  // path = "a.b.c.d"
  // will return "a" and path will be "b.c.d"
  // (assuming GROUP_SEP is '.')

  CMyString retval;
  int N = path.Find(GROUP_SEP);
  if (N == -1) {
    retval = path;
    path = _T("");
  } else {
    const int Len = path.GetLength();
    retval = CMyString(path.Left(N));
    path = CMyString(path.Right(Len - N - 1));
  }
  return retval;
}

static bool ExistsInTree(CTreeCtrl &Tree, HTREEITEM node,
			 const CMyString &s, HTREEITEM &si)
{
  // returns true iff s is a direct descendant of node
  HTREEITEM ti = Tree.GetChildItem(node);

  while (ti != NULL) {
    const CMyString itemText = Tree.GetItemText(ti);
    if (itemText == s) {
      si = ti;
      return true;
    }
    ti = Tree.GetNextItem(ti, TVGN_NEXT);
  }
  return false;
}

HTREEITEM CMyTreeCtrl::AddGroup(const CString &group)
{
  // Add a group at the end of path
  HTREEITEM ti = TVI_ROOT;
  HTREEITEM si;
  if (!group.IsEmpty()) {
    CMyString path = group;
    CMyString s;
    do {
      s = GetPathElem(path);
      if (!ExistsInTree(*this, ti, s, si)) {
	ti = InsertItem(s, ti, TVI_SORT);
	SetItemImage(ti, CMyTreeCtrl::NODE, CMyTreeCtrl::NODE);
      } else
	ti = si;
    } while (!path.IsEmpty());
  }
  return ti;
}

bool CMyTreeCtrl::TransferItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop)
{
  TV_INSERTSTRUCT     tvstruct;
  TCHAR               sztBuffer[128];
  HTREEITEM           hNewItem, hFirstChild;
  DWORD itemData = GetItemData(hitemDrag);

  // avoid an infinite recursion
  tvstruct.item.hItem = hitemDrag;
  tvstruct.item.cchTextMax = sizeof(sztBuffer)/sizeof(TCHAR) - 1;
  tvstruct.item.pszText = sztBuffer;
  tvstruct.item.mask = (TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE
			| TVIF_SELECTEDIMAGE | TVIF_TEXT);
  GetItem(&tvstruct.item);  // get information of the dragged element
  tvstruct.hParent = hitemDrop;
  tvstruct.hInsertAfter = TVI_SORT;
  tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
  hNewItem = InsertItem(&tvstruct);
  if (itemData != 0) { // Non-NULL itemData implies Leaf
    CItemData *ci = (CItemData *)itemData;
    // Update Group
    CMyString path, elem;
    HTREEITEM p, q = hNewItem;
    do {
      p = GetParentItem(q);
      if (p != NULL) {
	elem = CMyString(GetItemText(p));
	if (!path.IsEmpty())
	  elem += GROUP_SEP;
	path = elem + path;
	q = p;
      } else
	break;
    } while (1);
    ci->SetGroup(path);
    // Mark database as modified!
    ((DboxMain *)GetParent())->SetChanged(true);
    // Update DisplayInfo record associated with ItemData
    DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
    ASSERT(di != NULL);
    di->tree_item = hNewItem;
  }
  SetItemData(hNewItem, itemData);

  while ((hFirstChild = GetChildItem(hitemDrag)) != NULL) {
    TransferItem(hFirstChild, hNewItem);  // recursively transfer all the items
    DeleteItem(hFirstChild);
  }
  return true;
}

void CMyTreeCtrl::OnButtonUp()
{
  if (m_bDragging) {
    ASSERT(m_pimagelist != NULL);
    m_pimagelist->DragLeave(this);
    m_pimagelist->EndDrag();
    delete m_pimagelist;
    m_pimagelist = NULL;
    HTREEITEM parent = GetParentItem(m_hitemDrag);

    if (m_hitemDrag != m_hitemDrop &&
	!IsLeafNode(m_hitemDrop) &&
	!IsChildNodeOf(m_hitemDrop, m_hitemDrag) &&
	parent != m_hitemDrop) {
      TransferItem(m_hitemDrag, m_hitemDrop);
      DeleteItem(m_hitemDrag);
      while (parent != NULL && !ItemHasChildren(parent)) {
	HTREEITEM grandParent = GetParentItem(parent);
	DeleteItem(parent);
	parent = grandParent;
      }
      SelectItem(m_hitemDrop);
    } else { // drag failed, revert to last selected
      SelectItem(m_hitemDrag);
    }
    ReleaseCapture();
    m_bDragging = FALSE;
    SelectDropTarget(NULL);
  }
}

void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
  OnButtonUp();
  CTreeCtrl::OnLButtonUp(nFlags, point);
}

void CMyTreeCtrl::OnBeginDrag(LPNMHDR , LRESULT *)
{
  CPoint      ptAction;
  UINT        nFlags;

  GetCursorPos(&ptAction);
  ScreenToClient(&ptAction);
  ASSERT(!m_bDragging);
  m_bDragging = TRUE;
  m_hitemDrag = HitTest(ptAction, &nFlags);
  m_hitemDrop = NULL;

  ASSERT(m_pimagelist == NULL);
  m_pimagelist = CreateDragImage(m_hitemDrag);
  m_pimagelist->DragShowNolock(TRUE);
  m_pimagelist->SetDragCursorImage(0, CPoint(0, 0));
  m_pimagelist->BeginDrag(0, CPoint(0,0));
  m_pimagelist->DragMove(ptAction);
  m_pimagelist->DragEnter(this, ptAction);
  SetCapture();
}
<commit_msg>bug 899400: fix precision of drag-and-drop start detection.<commit_after>/*
 * Silly subclass of CTreeCtrl just to implement Drag&Drop.
 *
 * Based on MFC sample code from CMNCTRL1
 */

#include "stdafx.h"
#include "MyTreeCtrl.h"
#include "DboxMain.h"
#include "corelib/ItemData.h"
#include "corelib/MyString.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static const TCHAR GROUP_SEP = TCHAR('.');

CMyTreeCtrl::CMyTreeCtrl() : m_bDragging(false), m_pimagelist(NULL)
{
}

CMyTreeCtrl::~CMyTreeCtrl()
{
  delete m_pimagelist;
}

BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)
	//{{AFX_MSG_MAP(CMyTreeCtrl)
	ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnBeginLabelEdit)
	ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnEndLabelEdit)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
	ON_WM_MOUSEMOVE()
	ON_WM_DESTROY()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMyTreeCtrl::OnDestroy()
{
  CImageList  *pimagelist;

  pimagelist = GetImageList(TVSIL_NORMAL);
  if (pimagelist != NULL) {
    pimagelist->DeleteImageList();
    delete pimagelist;
  }
}

void CMyTreeCtrl::SetNewStyle(long lStyleMask, BOOL bSetBits)
{
  long        lStyleOld;

  lStyleOld = GetWindowLong(m_hWnd, GWL_STYLE);
  lStyleOld &= ~lStyleMask;
  if (bSetBits)
    lStyleOld |= lStyleMask;

  SetWindowLong(m_hWnd, GWL_STYLE, lStyleOld);
  SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
}

void CMyTreeCtrl::UpdateLeafsGroup(HTREEITEM hItem, CString prefix)
{
  // Starting with hItem, update the Group field of all of hItem's
  // children. Called after a label has been edited.
  if (IsLeafNode(hItem)) {
    DWORD itemData = GetItemData(hItem);
    ASSERT(itemData != NULL);
    CItemData *ci = (CItemData *)itemData;
    ci->SetGroup(CMyString(prefix));
  } else { // update prefix with current group name and recurse
    if (!prefix.IsEmpty())
      prefix += GROUP_SEP;
    prefix += GetItemText(hItem);
    HTREEITEM child;
    for(child = GetChildItem(hItem); child != NULL; child = GetNextSiblingItem(child)) {
      UpdateLeafsGroup(child, prefix);
    }
  }
}

void CMyTreeCtrl::OnBeginLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
{
  TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pnmhdr;
  // I thought m_BeginEditText was needed to restore text if desired,
  // but setting *pLResult to FALSE in OnEndLabelEdit suffices
  if (ptvinfo->item.pszText != NULL &&
      ptvinfo->item.pszText[0] != '\0') {
    m_BeginEditText = ptvinfo->item.pszText;
  } else {
    m_BeginEditText = _T("");
  }
  DboxMain *parent = (DboxMain *)GetParent();
  parent->DisableOnEdit(true); // so that Enter doesn't invoke Edit dialog
  *pLResult = FALSE; // TRUE cancels label editing
}

static void splitLeafText(const char *lt, CString &newTitle, CString &newUser)
{
  CString leafText(lt);
  int leftBraceIndex = leafText.Find('[');

  if (leftBraceIndex == -1) {
    newTitle = leafText;
    newUser = _T("");
  } else {
    newTitle = leafText.Left(leftBraceIndex - 1);
    int rightBraceIndex = leafText.Find(']');
    if (rightBraceIndex == -1) {
      newUser = leafText.Mid(leftBraceIndex + 1);
    } else {
      newUser = leafText.Mid(leftBraceIndex + 1, rightBraceIndex - leftBraceIndex - 1);
    }
  }
}

static void makeLeafText(CString &treeDispString, const CString &title, const CString &user)
{
  treeDispString = title;
  if (!user.IsEmpty()) {
    treeDispString += _T(" [");
    treeDispString += user;
    treeDispString += _T("]");
    }
}

void CMyTreeCtrl::OnEndLabelEdit(LPNMHDR pnmhdr, LRESULT *pLResult)
{
  static bool inEdit = false;

  if (inEdit) { // happens when edit control manipulated - see below
    inEdit = false;
    *pLResult = TRUE;
    return;
  }
  TV_DISPINFO *ptvinfo = (TV_DISPINFO *)pnmhdr;
  HTREEITEM ti = ptvinfo->item.hItem;
  DboxMain *parent = (DboxMain *)GetParent();
  if (ptvinfo->item.pszText != NULL && // NULL if edit cancelled,
      ptvinfo->item.pszText[0] != '\0') { // empty if text deleted - not allowed
    ptvinfo->item.mask = TVIF_TEXT;
    SetItem(&ptvinfo->item);
    if (IsLeafNode(ptvinfo->item.hItem)) {
      /*
       * Leaf text is of the form: title [user]
       * If edited text contains '[', then the user is updated
       * If not, then the user is retrieved and the leaf is updated
       */
      // Update leaf's title
      DWORD itemData = GetItemData(ti);
      ASSERT(itemData != NULL);
      CItemData *ci = (CItemData *)itemData;
      CString newTitle, newUser;
      splitLeafText(ptvinfo->item.pszText, newTitle, newUser);
      if (newUser.IsEmpty())
	newUser = CString(ci->GetUser());
      CString treeDispString;
      makeLeafText(treeDispString, newTitle, newUser);
      // Following needed to force display to update at this stage.
      inEdit = true; // hack to exit ugly recursion.
      CEdit *ed = EditLabel(ti);
      ASSERT(ed != NULL);
      ed->SetWindowText(treeDispString);
      SetItemText(ti, treeDispString);
      ci->SetTitle(newTitle); ci->SetUser(newUser);
      // update corresponding List text
      DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
      ASSERT(di != NULL);
      int lindex = di->list_index;
      parent->UpdateListItemTitle(lindex, newTitle);
      parent->UpdateListItemUser(lindex, newUser);
    } else {
      // Update all leaf children with new path element
      // prefix is path up to and NOT including renamed node
      CString prefix;
      HTREEITEM parent, current = ti;
      do {
	parent = GetParentItem(current);
	if (parent == NULL) {
	  break;
	}
	current = parent;
	if (!prefix.IsEmpty())
	  prefix = GROUP_SEP + prefix;
	prefix = GetItemText(current) + prefix;
      } while (1);
      UpdateLeafsGroup(ti, prefix);
    }
    // Mark database as modified
    parent->SetChanged(true);
    SortChildren(GetParentItem(ti));
  *pLResult = TRUE;
  } else {
    // restore text
    // (not that this is documented anywhere in MS's docs...)
    *pLResult = FALSE;
  }
  // following has to be done at end of function, since OnBeginLabelEdit
  // may be called (indirectly) from this fuction
  parent->DisableOnEdit(false); // Allow Enter to invoke Edit dialog
}

void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
  if (m_bDragging) {
    UINT                flags;

    ASSERT(m_pimagelist != NULL);
    m_pimagelist->DragMove(point);
    HTREEITEM hitem = HitTest(point, &flags);
    if (hitem != NULL) {
      m_pimagelist->DragLeave(this);
      SelectDropTarget(hitem);
      m_hitemDrop = hitem;
      m_pimagelist->DragEnter(this, point);
    }
  }
  CTreeCtrl::OnMouseMove(nFlags, point);
}

bool CMyTreeCtrl::IsChildNodeOf(HTREEITEM hitemChild, HTREEITEM hitemSuspectedParent)
{
  do {
    if (hitemChild == hitemSuspectedParent)
      break;
  } while ((hitemChild = GetParentItem(hitemChild)) != NULL);

  return (hitemChild != NULL);
}

bool CMyTreeCtrl::IsLeafNode(HTREEITEM hItem)
{
  // ItemHasChildren() won't work in the general case
  BOOL status;
  int i, dummy;
  status = GetItemImage(hItem, i, dummy);
  ASSERT(status);
  return (i == LEAF);
}

void CMyTreeCtrl::DeleteWithParents(HTREEITEM hItem)
{
  // We don't want nodes that have no children to remain
  HTREEITEM p;
  do {
    p = GetParentItem(hItem);
    DeleteItem(hItem);
    if (ItemHasChildren(p))
      break;
    hItem = p;
  } while (p != TVI_ROOT && p != NULL);
}

CString CMyTreeCtrl::GetGroup(HTREEITEM hItem)
{
  CString retval;
  CString nodeText;
  while (hItem != NULL) {
    nodeText = GetItemText(hItem);
    if (!retval.IsEmpty())
      nodeText += GROUP_SEP;
    retval = nodeText + retval;
    hItem = GetParentItem(hItem);
  }
  return retval;
}

static CMyString GetPathElem(CMyString &path)
{
  // Get first path element and chop it off, i.e., if
  // path = "a.b.c.d"
  // will return "a" and path will be "b.c.d"
  // (assuming GROUP_SEP is '.')

  CMyString retval;
  int N = path.Find(GROUP_SEP);
  if (N == -1) {
    retval = path;
    path = _T("");
  } else {
    const int Len = path.GetLength();
    retval = CMyString(path.Left(N));
    path = CMyString(path.Right(Len - N - 1));
  }
  return retval;
}

static bool ExistsInTree(CTreeCtrl &Tree, HTREEITEM node,
			 const CMyString &s, HTREEITEM &si)
{
  // returns true iff s is a direct descendant of node
  HTREEITEM ti = Tree.GetChildItem(node);

  while (ti != NULL) {
    const CMyString itemText = Tree.GetItemText(ti);
    if (itemText == s) {
      si = ti;
      return true;
    }
    ti = Tree.GetNextItem(ti, TVGN_NEXT);
  }
  return false;
}

HTREEITEM CMyTreeCtrl::AddGroup(const CString &group)
{
  // Add a group at the end of path
  HTREEITEM ti = TVI_ROOT;
  HTREEITEM si;
  if (!group.IsEmpty()) {
    CMyString path = group;
    CMyString s;
    do {
      s = GetPathElem(path);
      if (!ExistsInTree(*this, ti, s, si)) {
	ti = InsertItem(s, ti, TVI_SORT);
	SetItemImage(ti, CMyTreeCtrl::NODE, CMyTreeCtrl::NODE);
      } else
	ti = si;
    } while (!path.IsEmpty());
  }
  return ti;
}

bool CMyTreeCtrl::TransferItem(HTREEITEM hitemDrag, HTREEITEM hitemDrop)
{
  TV_INSERTSTRUCT     tvstruct;
  TCHAR               sztBuffer[128];
  HTREEITEM           hNewItem, hFirstChild;
  DWORD itemData = GetItemData(hitemDrag);

  // avoid an infinite recursion
  tvstruct.item.hItem = hitemDrag;
  tvstruct.item.cchTextMax = sizeof(sztBuffer)/sizeof(TCHAR) - 1;
  tvstruct.item.pszText = sztBuffer;
  tvstruct.item.mask = (TVIF_CHILDREN | TVIF_HANDLE | TVIF_IMAGE
			| TVIF_SELECTEDIMAGE | TVIF_TEXT);
  GetItem(&tvstruct.item);  // get information of the dragged element
  tvstruct.hParent = hitemDrop;
  tvstruct.hInsertAfter = TVI_SORT;
  tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
  hNewItem = InsertItem(&tvstruct);
  if (itemData != 0) { // Non-NULL itemData implies Leaf
    CItemData *ci = (CItemData *)itemData;
    // Update Group
    CMyString path, elem;
    HTREEITEM p, q = hNewItem;
    do {
      p = GetParentItem(q);
      if (p != NULL) {
	elem = CMyString(GetItemText(p));
	if (!path.IsEmpty())
	  elem += GROUP_SEP;
	path = elem + path;
	q = p;
      } else
	break;
    } while (1);
    ci->SetGroup(path);
    // Mark database as modified!
    ((DboxMain *)GetParent())->SetChanged(true);
    // Update DisplayInfo record associated with ItemData
    DisplayInfo *di = (DisplayInfo *)ci->GetDisplayInfo();
    ASSERT(di != NULL);
    di->tree_item = hNewItem;
  }
  SetItemData(hNewItem, itemData);

  while ((hFirstChild = GetChildItem(hitemDrag)) != NULL) {
    TransferItem(hFirstChild, hNewItem);  // recursively transfer all the items
    DeleteItem(hFirstChild);
  }
  return true;
}

void CMyTreeCtrl::OnButtonUp()
{
  if (m_bDragging) {
    ASSERT(m_pimagelist != NULL);
    m_pimagelist->DragLeave(this);
    m_pimagelist->EndDrag();
    delete m_pimagelist;
    m_pimagelist = NULL;
    HTREEITEM parent = GetParentItem(m_hitemDrag);

    if (m_hitemDrag != m_hitemDrop &&
	!IsLeafNode(m_hitemDrop) &&
	!IsChildNodeOf(m_hitemDrop, m_hitemDrag) &&
	parent != m_hitemDrop) {
      TransferItem(m_hitemDrag, m_hitemDrop);
      DeleteItem(m_hitemDrag);
      while (parent != NULL && !ItemHasChildren(parent)) {
	HTREEITEM grandParent = GetParentItem(parent);
	DeleteItem(parent);
	parent = grandParent;
      }
      SelectItem(m_hitemDrop);
    } else { // drag failed, revert to last selected
      SelectItem(m_hitemDrag);
    }
    ReleaseCapture();
    m_bDragging = FALSE;
    SelectDropTarget(NULL);
  }
}

void CMyTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
  OnButtonUp();
  CTreeCtrl::OnLButtonUp(nFlags, point);
}

void CMyTreeCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
  CPoint      ptAction;

  NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  *pResult = 0;

  GetCursorPos(&ptAction);
  ScreenToClient(&ptAction);
  ASSERT(!m_bDragging);
  m_bDragging = TRUE;
  m_hitemDrag = pNMTreeView->itemNew.hItem;
  m_hitemDrop = NULL;
  SelectItem(m_hitemDrag);

  ASSERT(m_pimagelist == NULL);
  m_pimagelist = CreateDragImage(m_hitemDrag);
  m_pimagelist->DragShowNolock(TRUE);
  m_pimagelist->SetDragCursorImage(0, CPoint(0, 0));
  m_pimagelist->BeginDrag(0, CPoint(0,0));
  m_pimagelist->DragMove(ptAction);
  m_pimagelist->DragEnter(this, ptAction);
  SetCapture();
}
<|endoftext|>


<commit_before>// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <zmq/zmqrpc.h>

#include <rpc/server.h>
#include <rpc/util.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>

#include <univalue.h>

namespace {

static RPCHelpMan getzmqnotifications()
{
    return RPCHelpMan{"getzmqnotifications",
                "\nReturns information about the active ZeroMQ notifications.\n",
                {},
                RPCResult{
                    RPCResult::Type::ARR, "", "",
                    {
                        {RPCResult::Type::OBJ, "", "",
                        {
                            {RPCResult::Type::STR, "type", "Type of notification"},
                            {RPCResult::Type::STR, "address", "Address of the publisher"},
                            {RPCResult::Type::STR, "addresssub", "Address of the subsciber"},
                            {RPCResult::Type::NUM, "hwm", "Outbound message high water mark"},
                        }},
                    }
                },
                RPCExamples{
                    HelpExampleCli("getzmqnotifications", "")
            + HelpExampleRpc("getzmqnotifications", "")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
    UniValue result(UniValue::VARR);
    if (g_zmq_notification_interface != nullptr) {
        for (const auto* n : g_zmq_notification_interface->GetActiveNotifiers()) {
            UniValue obj(UniValue::VOBJ);
            obj.pushKV("type", n->GetType());
            obj.pushKV("address", n->GetAddress());
            // SYSCOIN
            obj.pushKV("addresssub", n->GetAddressSub());
            obj.pushKV("hwm", n->GetOutboundMessageHighWaterMark());
            result.push_back(obj);
        }
    }

    return result;
},
    };
}

const CRPCCommand commands[] =
{ //  category           actor (function)
  //  -----------------  -----------------------
    { "zmq",             &getzmqnotifications,    },
};

} // anonymous namespace

void RegisterZMQRPCCommands(CRPCTable& t)
{
    for (const auto& c : commands) {
        t.appendCommand(c.name, &c);
    }
}
<commit_msg>fix zmq interface test<commit_after>// Copyright (c) 2018-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <zmq/zmqrpc.h>

#include <rpc/server.h>
#include <rpc/util.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>

#include <univalue.h>

namespace {

static RPCHelpMan getzmqnotifications()
{
    return RPCHelpMan{"getzmqnotifications",
                "\nReturns information about the active ZeroMQ notifications.\n",
                {},
                RPCResult{
                    RPCResult::Type::ARR, "", "",
                    {
                        {RPCResult::Type::OBJ, "", "",
                        {
                            {RPCResult::Type::STR, "type", "Type of notification"},
                            {RPCResult::Type::STR, "address", "Address of the publisher"},
                            {RPCResult::Type::STR, "addresssub", "Address of the subsciber, omitted if there is no subscriber assigned to this notification"},
                            {RPCResult::Type::NUM, "hwm", "Outbound message high water mark"},
                        }},
                    }
                },
                RPCExamples{
                    HelpExampleCli("getzmqnotifications", "")
            + HelpExampleRpc("getzmqnotifications", "")
                },
        [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
    UniValue result(UniValue::VARR);
    if (g_zmq_notification_interface != nullptr) {
        for (const auto* n : g_zmq_notification_interface->GetActiveNotifiers()) {
            UniValue obj(UniValue::VOBJ);
            obj.pushKV("type", n->GetType());
            obj.pushKV("address", n->GetAddress());
            // SYSCOIN
            const std::string &addresssub = n->GetAddressSub();
            if(!addresssub.empty())
                obj.pushKV("addresssub", addresssub);
            obj.pushKV("hwm", n->GetOutboundMessageHighWaterMark());
            result.push_back(obj);
        }
    }

    return result;
},
    };
}

const CRPCCommand commands[] =
{ //  category           actor (function)
  //  -----------------  -----------------------
    { "zmq",             &getzmqnotifications,    },
};

} // anonymous namespace

void RegisterZMQRPCCommands(CRPCTable& t)
{
    for (const auto& c : commands) {
        t.appendCommand(c.name, &c);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <zmq/zmqrpc.h>

#include <rpc/server.h>
#include <rpc/util.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>

#include <univalue.h>

namespace {

UniValue getzmqnotifications(const Config &config,
                             const JSONRPCRequest &request) {
    if (request.fHelp || request.params.size() != 0) {
        throw std::runtime_error(
            RPCHelpMan{"getzmqnotifications",
                       "\nReturns information about the active ZeroMQ "
                       "notifications.\n",
                       {}}
                .ToString() +
            "\nResult:\n"
            "[\n"
            "  {                        (json object)\n"
            "    \"type\": \"pubhashtx\",   (string) Type of notification\n"
            "    \"address\": \"...\"       (string) Address of the publisher\n"
            "  },\n"
            "  ...\n"
            "]\n"
            "\nExamples:\n" +
            HelpExampleCli("getzmqnotifications", "") +
            HelpExampleRpc("getzmqnotifications", ""));
    }

    UniValue result(UniValue::VARR);
    if (g_zmq_notification_interface != nullptr) {
        for (const auto *n :
             g_zmq_notification_interface->GetActiveNotifiers()) {
            UniValue obj(UniValue::VOBJ);
            obj.pushKV("type", n->GetType());
            obj.pushKV("address", n->GetAddress());
            result.push_back(obj);
        }
    }

    return result;
}

// clang-format off
static const ContextFreeRPCCommand commands[] = {
    //  category          name                     actor (function)        argNames
    //  ----------------- ------------------------ ----------------------- ----------
    { "zmq",            "getzmqnotifications",   getzmqnotifications,    {} },
};
// clang-format on

} // anonymous namespace

void RegisterZMQRPCCommands(CRPCTable &t) {
    for (const auto &c : commands) {
        t.appendCommand(c.name, &c);
    }
}
<commit_msg>Pass zmq RPC results and examples to RPCHelpMan<commit_after>// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <zmq/zmqrpc.h>

#include <rpc/server.h>
#include <rpc/util.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>

#include <univalue.h>

namespace {

UniValue getzmqnotifications(const Config &config,
                             const JSONRPCRequest &request) {
    if (request.fHelp || request.params.size() != 0) {
        throw std::runtime_error(RPCHelpMan{
            "getzmqnotifications",
            "\nReturns information about the active ZeroMQ "
            "notifications.\n",
            {},
            RPCResult{
                "[\n"
                "  {                        (json object)\n"
                "    \"type\": \"pubhashtx\",   (string) Type of notification\n"
                "    \"address\": \"...\"       (string) Address of the "
                "publisher\n"
                "  },\n"
                "  ...\n"
                "]\n"},
            RPCExamples{HelpExampleCli("getzmqnotifications", "") +
                        HelpExampleRpc("getzmqnotifications", "")},
        }
                                     .ToStringWithResultsAndExamples());
    }

    UniValue result(UniValue::VARR);
    if (g_zmq_notification_interface != nullptr) {
        for (const auto *n :
             g_zmq_notification_interface->GetActiveNotifiers()) {
            UniValue obj(UniValue::VOBJ);
            obj.pushKV("type", n->GetType());
            obj.pushKV("address", n->GetAddress());
            result.push_back(obj);
        }
    }

    return result;
}

// clang-format off
static const ContextFreeRPCCommand commands[] = {
    //  category          name                     actor (function)        argNames
    //  ----------------- ------------------------ ----------------------- ----------
    { "zmq",            "getzmqnotifications",   getzmqnotifications,    {} },
};
// clang-format on

} // anonymous namespace

void RegisterZMQRPCCommands(CRPCTable &t) {
    for (const auto &c : commands) {
        t.appendCommand(c.name, &c);
    }
}
<|endoftext|>


<commit_before>#include "thruster_sim.h"
#include "thruster_tortuga.h"

/**
   This is the main method for our depth_sensor node
**/

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

    //SG: argc may need to be different idk
    if(argc != 4){
        ROS_ERROR("The thruster node received %i arguments which is not right\n", argc);
        for(int i = 0; i < argc; i++){
            ROS_ERROR("arg: %s\n", argv[i]);
        }
        exit(1);
    }

    ros::init(argc, argv, "thruster_node"); /** basically always needs to be called first */

    /**
       The basic idea here is to pass in a boolean from a launch script that determines if our class is
       a real one or a simulated one. after that they behave exactly the same as far as main is concerned
       right now though we don't have a real depth sensor, hence the comments
    **/

    std::unique_ptr<QuboNode> node;

    if(strcmp(argv[1], "simulated") == 0){
        node.reset(new ThrusterSimNode(argc, argv, 10)); /** 10 (the rate) is completely arbitrary */
    }else if(strcmp(argv[1], "tortuga") == 0) {
        node.reset(new ThrusterTortugaNode(argc, argv, 10));
    }else{
        ROS_ERROR("the passed in arguments to thruster node (%s) doesn't match anything that makes sense..\n", argv[1]);
    }

    ROS_ERROR("got here!!!!!!!\n");
    while (ros::ok()){
        ROS_ERROR("inside the loop, all is well.\n");
        node->update();
        ROS_ERROR("updated!.\n");
        node->publish();
        ROS_ERROR("published!.\n");

    }

}

<commit_msg>removing some debug values<commit_after>#include "thruster_sim.h"
#include "thruster_tortuga.h"

/**
   This is the main method for our depth_sensor node
**/

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

    //SG: argc may need to be different idk
    if(argc != 4){
        ROS_ERROR("The thruster node received %i arguments which is not right\n", argc);
        for(int i = 0; i < argc; i++){
            ROS_ERROR("arg: %s\n", argv[i]);
        }
        exit(1);
    }

    ros::init(argc, argv, "thruster_node"); /** basically always needs to be called first */

    /**
       The basic idea here is to pass in a boolean from a launch script that determines if our class is
       a real one or a simulated one. after that they behave exactly the same as far as main is concerned
       right now though we don't have a real depth sensor, hence the comments
    **/

    std::unique_ptr<QuboNode> node;

    if(strcmp(argv[1], "simulated") == 0){
        node.reset(new ThrusterSimNode(argc, argv, 10)); /** 10 (the rate) is completely arbitrary */
    }else if(strcmp(argv[1], "tortuga") == 0) {
        node.reset(new ThrusterTortugaNode(argc, argv, 10));
    }else{
        ROS_ERROR("the passed in arguments to thruster node (%s) doesn't match anything that makes sense..\n", argv[1]);
    }

    while (ros::ok()){
        node->update();
        node->publish();

    }

}

<|endoftext|>


<commit_before>
#include <iostream>
#include <fstream>
#include <utility>
#include <ctime>

// TCLAP
#include "tclap/CmdLine.h"

#include <sdsl/bit_vectors.hpp>
#include <cstdio>

#include <cstdlib>

#include <libgen.h>
#include <sparsepp/spp.h>
#include <boost/dynamic_bitset.hpp>
using spp::sparse_hash_map;
// Custom Headers
//#include "uint128_t.hpp"
//#include "debug.h"
#include "kmer.hpp"

//using namespace std;
//using namespace sdsl;

#include <cstdlib>
#include <sys/timeb.h>
#include "pack-color.hpp"
#include <bitset>
int getMilliCount()
{
    timeb tb;
    ftime(&tb);
    int nCount = tb.millitm + (tb.time & 0xfffff) * 1000;
    return nCount;
}

int getMilliSpan(int nTimeStart)
{
    int nSpan = getMilliCount() - nTimeStart;
    if(nSpan < 0)
        nSpan += 0x100000 * 1000;
    return nSpan;
}

std::string file_extension = ".<extension>";

void parse_arguments(int argc, char **argv, parameters_t & params)
{
    TCLAP::CmdLine cmd("Cosmo Copyright (c) Alex Bowe (alexbowe.com) 2014", ' ', VERSION);
    TCLAP::UnlabeledValueArg<std::string> input_filename_arg("input",
                                                             "Input file. Currently only supports DSK's binary format (for k<=64).", true, "", "input_file", cmd);
    TCLAP::UnlabeledValueArg<std::string> num_colors_arg("num_colors",
                                                         "Number of colors", true, "", "num colors", cmd);
    cmd.parse( argc, argv );
    params.input_filename  = input_filename_arg.getValue();
    params.num_colors  = atoi(num_colors_arg.getValue().c_str());

}

void deserialize_color_bv(std::ifstream &colorfile, color_bv &value)
{
    colorfile.read((char *)&value, sizeof(color_bv));
}
int insertColorLabel(boost::dynamic_bitset<>& bs, unsigned num, int pos) {
	// most significant bit of number goes down to the end of the bitset
    do {
    	if (num&1) {
	      bs.set(pos);
    	}
	num>>=1;
    	pos++;
    } while(num);
    return pos;
}

bool writeBitset(boost::dynamic_bitset<>& bs, std::ofstream& out) {
  int bitctr{7};
  unsigned char byte{0};
  size_t bs_size = bs.size();
  std::cout<<bs_size<<"\n";
  out.write(reinterpret_cast<char*>(&bs_size), sizeof(bs_size));
  for (size_t i = 0; i < bs.size(); ++i) {
    byte |= (bs[i] << bitctr);
    if (bitctr == 0) {
       out.write(reinterpret_cast<char*>(&byte), sizeof(byte));
       byte = 0;
       bitctr = 8;
    }
    bitctr--;
  }
  if (bitctr > 0) {
    out.write(reinterpret_cast<char*>(&byte), sizeof(byte));
  }
  return true;
}

int main(int argc, char * argv[])
{
    std::cerr << "pack-color compiled with supported colors=" << NUM_COLS << std::endl;
    std::cerr <<"Starting" << std::endl;
    parameters_t params;
    parse_arguments(argc, argv, params);

    const char * file_name = params.input_filename.c_str();
    std::cerr << "file name: " << file_name << std::endl;

// Open File
    std::ifstream colorfile(file_name, std::ios::in|std::ios::binary);

    colorfile.seekg(0, colorfile.end);
    size_t end = colorfile.tellg();
    colorfile.seekg(0, colorfile.beg);
    std::cerr << "file size: " << end << std::endl;
    std::cerr << "sizeof(color_bv): " << sizeof(color_bv) << std::endl;
    size_t num_color = params.num_colors;
    size_t num_edges = end / sizeof(color_bv);

    size_t cnt0 = 0;
    size_t cnt1 = 0;
    std::cerr << "edges: " << num_edges << " colors: " << num_color << " Total: " << num_edges * num_color << std::endl;
    sparse_hash_map<color_bv, int> eqCls;
    for (size_t i=0; i < num_edges; i++) {
        if (i % 100000000 == 0) {
            std::cerr << "deserializing edge " << i
                      << " cnt0: " << cnt0
                      << " cnt1: " << cnt1 << std::endl;
        }
        color_bv value;
        deserialize_color_bv(colorfile, value);
		if (eqCls.find(value)==eqCls.end())
	    	eqCls[value] = 1;
		else
			eqCls[value] = eqCls[value]+1;
    }
    std::cerr << "Succinct builder object allocated." << std::endl;
    std::vector<std::pair<color_bv, int>> eqClsVec;
    eqClsVec.reserve(eqCls.size());
    for (const auto& c : eqCls) { eqClsVec.push_back(c); }
	// sort the hashmap
	auto cmp = [](std::pair<color_bv, int> const & a, std::pair<color_bv, int> const & b)
	{
    	 return a.second > b.second;
	};
	std::sort(eqClsVec.begin(), eqClsVec.end(), cmp);
	boost::dynamic_bitset<> eqTable(eqCls.size()*num_color);
	size_t i = 0;
    for (const auto& c : eqClsVec) {
		for (size_t j = 0; j < num_color; ++j) {
			eqTable[i] = c.first[j];
			i++;
		}
	}
	std::cout<<"Eq. cls BV:\n"<<eqTable<<"\n";
	// replacing labels instead of k-mer counts as the hash map values
    int lbl = 0;
	int totalBits = 0;
    for (const auto& c : eqClsVec) {
	 	//std::cerr <<"eq cls "<<lbl++<< ": "<<c.first<<" : "<<c.second << "\n";
		totalBits += (lbl==0?c.second:ceil(log2(lbl+1))*c.second);
		eqCls[c.first] = lbl;
	}
    size_t vecBits = totalBits;
    totalBits *= 2;
    totalBits += num_color * eqCls.size();
	std::cerr << "total bits: " << totalBits << " or " << totalBits/(8*pow(1024,2)) << " MBs\n";

	// creating bitvectors A and b
	// A contains eq. class label for each k-mer in bits
	// b is set in the start position of each k-mer in A
	int sysTime = getMilliCount();
        colorfile.seekg(0, colorfile.beg);
	boost::dynamic_bitset<> A(vecBits);
	boost::dynamic_bitset<> rnk(vecBits);
	int curPos = 0;
	for (size_t i=0; i < num_edges; i++) {
		color_bv value;
		deserialize_color_bv(colorfile, value);
		rnk.set(curPos);
		curPos = insertColorLabel(A, eqCls[value], curPos);
		// if we want to set the end, here we should say b.set(curPos-1);
	}

	std::cerr << "\nA, rnk & eq. cls BVs creation time : " << getMilliSpan(sysTime) << " ms\n";
    std::cout<<"A.bitvec:";
    std::ofstream Aout("A.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(A, Aout)) {
       std::cerr << "Oh noes; couldn't write A!\n";
    }
    Aout.close();
    std::cout<<"B.bitvec:";
    std::ofstream Bout("B.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(rnk, Bout)) {
       std::cerr << "Oh noes; couldn't write B!\n";
    }
    Bout.close();
    std::cout<<"eqTable.bitvec:";
	std::ofstream eqTableout("eqTable.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(eqTable, eqTableout)) {
       std::cerr << "Oh noes; couldn't write eqTable!\n";
    }
    eqTableout.close();

	//std::cerr << "**********************    A    ***********************\n" << A;
	//std::cerr << "**********************   rank  ***********************\n" << rnk;

/*
  sysTime = getMilliCount();
  sd_vector<> sdb(b);
  std::cerr << "SD Creation Time: " << getMilliSpan(sysTime) << endl;
  sysTime = getMilliCount();
  for (size_t i=0; i < num_edges*num_color; i++) {
  sdb[i];
  }
  std::cerr << "SD Access Time: " << getMilliSpan(sysTime) << endl;
  std::cerr << "SD Size (MB): " << size_in_mega_bytes(sdb) << endl;

  sysTime = getMilliCount();
  hyb_vector<> hyb(b);
  std::cerr << "Hyb Creation Time: " << getMilliSpan(sysTime) << endl;
  sysTime = getMilliCount();
  for (size_t i=0; i < num_edges*num_color; i++) {
  hyb[i];
  }
  std::cerr << "Hyb Access Time: " << getMilliSpan(sysTime) << endl;
  std::cerr << "Hyb Size (MB): " << size_in_mega_bytes(hyb) << endl;
*/
}
<commit_msg>Bug Fixed<commit_after>
#include <iostream>
#include <fstream>
#include <utility>
#include <ctime>

// TCLAP
#include "tclap/CmdLine.h"

#include <sdsl/bit_vectors.hpp>
#include <cstdio>

#include <cstdlib>

#include <libgen.h>
#include <sparsepp/spp.h>
#include <boost/dynamic_bitset.hpp>
using spp::sparse_hash_map;
// Custom Headers
//#include "uint128_t.hpp"
//#include "debug.h"
#include "kmer.hpp"

//using namespace std;
//using namespace sdsl;

#include <cstdlib>
#include <sys/timeb.h>
#include "pack-color.hpp"
#include <bitset>
int getMilliCount()
{
    timeb tb;
    ftime(&tb);
    int nCount = tb.millitm + (tb.time & 0xfffff) * 1000;
    return nCount;
}

int getMilliSpan(int nTimeStart)
{
    int nSpan = getMilliCount() - nTimeStart;
    if(nSpan < 0)
        nSpan += 0x100000 * 1000;
    return nSpan;
}

std::string file_extension = ".<extension>";

void parse_arguments(int argc, char **argv, parameters_t & params)
{
    TCLAP::CmdLine cmd("Cosmo Copyright (c) Alex Bowe (alexbowe.com) 2014", ' ', VERSION);
    TCLAP::UnlabeledValueArg<std::string> input_filename_arg("input",
                                                             "Input file. Currently only supports DSK's binary format (for k<=64).", true, "", "input_file", cmd);
    TCLAP::UnlabeledValueArg<std::string> num_colors_arg("num_colors",
                                                         "Number of colors", true, "", "num colors", cmd);
    cmd.parse( argc, argv );
    params.input_filename  = input_filename_arg.getValue();
    params.num_colors  = atoi(num_colors_arg.getValue().c_str());

}

void deserialize_color_bv(std::ifstream &colorfile, color_bv &value)
{
    colorfile.read((char *)&value, sizeof(color_bv));
}
int insertColorLabel(boost::dynamic_bitset<>& bs, unsigned num, int pos) {
	// most significant bit of number goes down to the end of the bitset
    do {
    	if (num&1) {
	      bs.set(pos);
    	}
	num>>=1;
    	pos++;
    } while(num);
    return pos;
}

bool writeBitset(boost::dynamic_bitset<>& bs, std::ofstream& out) {
  int bitctr{7};
  unsigned char byte{0};
  size_t bs_size = bs.size();
  std::cout<<bs_size<<"\n";
  out.write(reinterpret_cast<char*>(&bs_size), sizeof(bs_size));
  for (size_t i = 0; i < bs.size(); ++i) {
    byte |= (bs[i] << bitctr);
    if (bitctr == 0) {
       out.write(reinterpret_cast<char*>(&byte), sizeof(byte));
       byte = 0;
       bitctr = 8;
    }
    bitctr--;
  }
  if (bitctr > 0) {
    out.write(reinterpret_cast<char*>(&byte), sizeof(byte));
  }
  return true;
}

int main(int argc, char * argv[])
{
    std::cerr << "pack-color compiled with supported colors=" << NUM_COLS << std::endl;
    std::cerr <<"Starting" << std::endl;
    parameters_t params;
    parse_arguments(argc, argv, params);

    const char * file_name = params.input_filename.c_str();
    std::cerr << "file name: " << file_name << std::endl;

// Open File
    std::ifstream colorfile(file_name, std::ios::in|std::ios::binary);

    colorfile.seekg(0, colorfile.end);
    size_t end = colorfile.tellg();
    colorfile.seekg(0, colorfile.beg);
    std::cerr << "file size: " << end << std::endl;
    std::cerr << "sizeof(color_bv): " << sizeof(color_bv) << std::endl;
    size_t num_color = params.num_colors;
    size_t num_edges = end / sizeof(color_bv);

    size_t cnt0 = 0;
    size_t cnt1 = 0;
    std::cerr << "edges: " << num_edges << " colors: " << num_color << " Total: " << num_edges * num_color << std::endl;
    sparse_hash_map<color_bv, int> eqCls;
    for (size_t i=0; i < num_edges; i++) {
        if (i % 100000000 == 0) {
            std::cerr << "deserializing edge " << i
                      << " cnt0: " << cnt0
                      << " cnt1: " << cnt1 << std::endl;
        }
        color_bv value;
        deserialize_color_bv(colorfile, value);
		if (eqCls.find(value)==eqCls.end())
	    	eqCls[value] = 1;
		else
			eqCls[value] = eqCls[value]+1;
    }
    std::cerr << "Succinct builder object allocated." << std::endl;
    std::vector<std::pair<color_bv, int>> eqClsVec;
    eqClsVec.reserve(eqCls.size());
    for (const auto& c : eqCls) { eqClsVec.push_back(c); }
	// sort the hashmap
	auto cmp = [](std::pair<color_bv, int> const & a, std::pair<color_bv, int> const & b)
	{
    	 return a.second > b.second;
	};
	std::sort(eqClsVec.begin(), eqClsVec.end(), cmp);
	boost::dynamic_bitset<> eqTable(eqCls.size()*num_color);
	size_t i = 0;
    for (const auto& c : eqClsVec) {
		for (size_t j = 0; j < num_color; ++j) {
			eqTable[i] = c.first[j];
			i++;
		}
	}
	std::cout<<"Eq. cls BV:\n"<<eqTable<<"\n";
	// replacing labels instead of k-mer counts as the hash map values
    int lbl = 0;
	int totalBits = 0;
    for (const auto& c : eqClsVec) {
	 	//std::cerr <<"eq cls "<<lbl++<< ": "<<c.first<<" : "<<c.second << "\n";
		totalBits += (lbl==0?c.second:ceil(log2(lbl+1))*c.second);
		eqCls[c.first] = lbl++;
		std::cout<<c.first<<":"<<eqCls[c.first];
	}
    size_t vecBits = totalBits;
    totalBits *= 2;
    totalBits += num_color * eqCls.size();
	std::cerr << "total bits: " << totalBits << " or " << totalBits/(8*pow(1024,2)) << " MBs\n";

	// creating bitvectors A and b
	// A contains eq. class label for each k-mer in bits
	// b is set in the start position of each k-mer in A
	int sysTime = getMilliCount();
    colorfile.seekg(0, colorfile.beg);
	boost::dynamic_bitset<> A(vecBits);
	boost::dynamic_bitset<> rnk(vecBits);
	int curPos = 0;
	for (size_t i=0; i < num_edges; i++) {
		color_bv value;
		deserialize_color_bv(colorfile, value);
//		std::cout<<value<<":"<<eqCls[value]<<" ";
		rnk.set(curPos);
		curPos = insertColorLabel(A, eqCls[value], curPos);
		// if we want to set the end, here we should say b.set(curPos-1);
	}

	std::cerr << "\nA, rnk & eq. cls BVs creation time : " << getMilliSpan(sysTime) << " ms\n";
    std::cout<<"A.bitvec:";
    std::ofstream Aout("A.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(A, Aout)) {
       std::cerr << "Oh noes; couldn't write A!\n";
    }
    Aout.close();
    std::cout<<"B.bitvec:";
    std::ofstream Bout("B.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(rnk, Bout)) {
       std::cerr << "Oh noes; couldn't write B!\n";
    }
    Bout.close();
    std::cout<<"eqTable.bitvec:";
	std::ofstream eqTableout("eqTable.bitvec", std::ios::out|std::ios::binary);
    if (!writeBitset(eqTable, eqTableout)) {
       std::cerr << "Oh noes; couldn't write eqTable!\n";
    }
    eqTableout.close();

	//std::cerr << "**********************    A    ***********************\n" << A;
	//std::cerr << "**********************   rank  ***********************\n" << rnk;

/*
  sysTime = getMilliCount();
  sd_vector<> sdb(b);
  std::cerr << "SD Creation Time: " << getMilliSpan(sysTime) << endl;
  sysTime = getMilliCount();
  for (size_t i=0; i < num_edges*num_color; i++) {
  sdb[i];
  }
  std::cerr << "SD Access Time: " << getMilliSpan(sysTime) << endl;
  std::cerr << "SD Size (MB): " << size_in_mega_bytes(sdb) << endl;

  sysTime = getMilliCount();
  hyb_vector<> hyb(b);
  std::cerr << "Hyb Creation Time: " << getMilliSpan(sysTime) << endl;
  sysTime = getMilliCount();
  for (size_t i=0; i < num_edges*num_color; i++) {
  hyb[i];
  }
  std::cerr << "Hyb Access Time: " << getMilliSpan(sysTime) << endl;
  std::cerr << "Hyb Size (MB): " << size_in_mega_bytes(hyb) << endl;
*/
}
<|endoftext|>


<commit_before>#include <sirius.h>

using namespace sirius;

void test_hloc(std::vector<int> mpi_grid_dims__, double cutoff__, int num_bands__,
               int use_gpu__, double gpu_workload__)
{
    device_t pu = static_cast<device_t>(use_gpu__);

    MPI_grid mpi_grid(mpi_grid_dims__, mpi_comm_world());

    matrix3d<double> M = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

    FFT3D_grid fft_box(find_translations(2.01 * cutoff__, M));

    FFT3D fft(fft_box, mpi_grid.communicator(1 << 0), pu, gpu_workload__);

    Gvec gvec(M, cutoff__, mpi_comm_world(), mpi_grid.communicator(1 << 0), false);

    std::vector<double> veff(fft.local_size(), 2.0);

    if (mpi_comm_world().rank() == 0) {
        printf("total number of G-vectors: %i\n", gvec.num_gvec());
        printf("local number of G-vectors: %i\n", gvec.gvec_count(0));
        printf("FFT grid size: %i %i %i\n", fft_box.size(0), fft_box.size(1), fft_box.size(2));
        printf("number of FFT threads: %i\n", omp_get_max_threads());
        printf("number of FFT groups: %i\n", mpi_grid.dimension_size(1));
        printf("MPI grid: %i %i\n", mpi_grid.dimension_size(0), mpi_grid.dimension_size(1));
        printf("number of z-columns: %i\n", gvec.num_zcol());
        if (use_gpu__) printf("GPU workload: %f\n", gpu_workload__);
    }

    fft.prepare(gvec.partition());

    Local_operator hloc(fft, gvec);

    wave_functions phi(pu, gvec, 4 * num_bands__);
    for (int i = 0; i < 4 * num_bands__; i++) {
        for (int j = 0; j < phi.pw_coeffs().num_rows_loc(); j++) {
            phi.pw_coeffs().prime(j, i) = type_wrapper<double_complex>::random();
        }
    }
    wave_functions hphi(pu, gvec, 4 * num_bands__);

    #ifdef __GPU
    if (pu == GPU) {
        phi.pw_coeffs().allocate_on_device();
        phi.pw_coeffs().copy_to_device(0, 4 * num_bands__);
        hphi.pw_coeffs().allocate_on_device();
    }
    #endif

    mpi_comm_world().barrier();
    sddk::timer t1("h_loc");
    for (int i = 0; i < 4; i++) {
        hphi.copy_from(phi, i * num_bands__, num_bands__);
        #ifdef __GPU
        if (pu == GPU && !fft.gpu_only()) {
            hphi.pw_coeffs().copy_to_host(i * num_bands__, num_bands__);
        }
        #endif
        hloc.apply_h(0, hphi, i * num_bands__, num_bands__);
    }
    mpi_comm_world().barrier();
    t1.stop();

    #ifdef __GPU
    if (pu == GPU && fft.gpu_only()) {
        hphi.pw_coeffs().copy_to_host(0, 4 * num_bands__);
    }
    #endif

    double diff{0};
    for (int i = 0; i < 4 * num_bands__; i++) {
        for (int j = 0; j < phi.pw_coeffs().num_rows_loc(); j++) {
            diff += std::abs(2.0 * phi.pw_coeffs().prime(j, i) - hphi.pw_coeffs().prime(j, i));
        }
    }
    if (diff != diff) {
        TERMINATE("NaN");
    }
    mpi_comm_world().allreduce(&diff, 1);
    if (mpi_comm_world().rank() == 0) {
        printf("diff: %18.12f\n", diff);
    }

    fft.dismiss();
}

int main(int argn, char** argv)
{
    cmd_args args;
    args.register_key("--mpi_grid_dims=", "{int int} dimensions of MPI grid");
    args.register_key("--cutoff=", "{double} wave-functions cutoff");
    args.register_key("--num_bands=", "{int} number of bands");
    args.register_key("--use_gpu=", "{int} 0: CPU only, 1: hybrid CPU+GPU");
    args.register_key("--gpu_workload=", "{double} worload of GPU");

    args.parse_args(argn, argv);
    if (args.exist("help")) {
        printf("Usage: %s [options]\n", argv[0]);
        args.print_help();
        return 0;
    }
    auto mpi_grid_dims = args.value< std::vector<int> >("mpi_grid_dims", {1, 1});
    auto cutoff = args.value<double>("cutoff", 2.0);
    auto num_bands = args.value<int>("num_bands", 10);
    auto use_gpu = args.value<int>("use_gpu", 0);
    auto gpu_workload = args.value<double>("gpu_workload", 0.8);

    sirius::initialize(1);
    for (int i = 0; i < 10; i++) {
        test_hloc(mpi_grid_dims, cutoff, num_bands, use_gpu, gpu_workload);
    }
    mpi_comm_world().barrier();
    sddk::timer::print();
    //runtime::Timer::print_all();
    sirius::finalize();
}
<commit_msg>update test<commit_after>#include <sirius.h>

using namespace sirius;

void test_hloc(std::vector<int> mpi_grid_dims__, double cutoff__, int num_bands__,
               int use_gpu__)
{
    device_t pu = static_cast<device_t>(use_gpu__);

    MPI_grid mpi_grid(mpi_grid_dims__, mpi_comm_world());

    matrix3d<double> M = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

    FFT3D_grid fft_box(find_translations(2.01 * cutoff__, M));

    FFT3D fft(fft_box, mpi_grid.communicator(1 << 0), pu);

    Gvec gvec(M, cutoff__, mpi_comm_world(), mpi_grid.communicator(1 << 0), false);

    std::vector<double> veff(fft.local_size(), 2.0);

    if (mpi_comm_world().rank() == 0) {
        printf("total number of G-vectors: %i\n", gvec.num_gvec());
        printf("local number of G-vectors: %i\n", gvec.gvec_count(0));
        printf("FFT grid size: %i %i %i\n", fft_box.size(0), fft_box.size(1), fft_box.size(2));
        printf("number of FFT threads: %i\n", omp_get_max_threads());
        printf("number of FFT groups: %i\n", mpi_grid.dimension_size(1));
        printf("MPI grid: %i %i\n", mpi_grid.dimension_size(0), mpi_grid.dimension_size(1));
        printf("number of z-columns: %i\n", gvec.num_zcol());
    }

    fft.prepare(gvec.partition());

    Local_operator hloc(fft, gvec);

    wave_functions phi(pu, gvec, 4 * num_bands__);
    for (int i = 0; i < 4 * num_bands__; i++) {
        for (int j = 0; j < phi.pw_coeffs().num_rows_loc(); j++) {
            phi.pw_coeffs().prime(j, i) = type_wrapper<double_complex>::random();
        }
    }
    wave_functions hphi(pu, gvec, 4 * num_bands__);

    #ifdef __GPU
    if (pu == GPU) {
        phi.pw_coeffs().allocate_on_device();
        phi.pw_coeffs().copy_to_device(0, 4 * num_bands__);
        hphi.pw_coeffs().allocate_on_device();
    }
    #endif

    mpi_comm_world().barrier();
    sddk::timer t1("h_loc");
    for (int i = 0; i < 4; i++) {
        hphi.copy_from(phi, i * num_bands__, num_bands__);
        #ifdef __GPU
        if (pu == GPU) {
            hphi.pw_coeffs().copy_to_host(i * num_bands__, num_bands__);
        }
        #endif
        hloc.apply_h(0, hphi, i * num_bands__, num_bands__);
    }
    mpi_comm_world().barrier();
    t1.stop();

    #ifdef __GPU
    if (pu == GPU) {
        hphi.pw_coeffs().copy_to_host(0, 4 * num_bands__);
    }
    #endif

    double diff{0};
    for (int i = 0; i < 4 * num_bands__; i++) {
        for (int j = 0; j < phi.pw_coeffs().num_rows_loc(); j++) {
            diff += std::abs(2.0 * phi.pw_coeffs().prime(j, i) - hphi.pw_coeffs().prime(j, i));
        }
    }
    if (diff != diff) {
        TERMINATE("NaN");
    }
    mpi_comm_world().allreduce(&diff, 1);
    if (mpi_comm_world().rank() == 0) {
        printf("diff: %18.12f\n", diff);
    }

    fft.dismiss();
}

int main(int argn, char** argv)
{
    cmd_args args;
    args.register_key("--mpi_grid_dims=", "{int int} dimensions of MPI grid");
    args.register_key("--cutoff=", "{double} wave-functions cutoff");
    args.register_key("--num_bands=", "{int} number of bands");
    args.register_key("--use_gpu=", "{int} 0: CPU only, 1: hybrid CPU+GPU");

    args.parse_args(argn, argv);
    if (args.exist("help")) {
        printf("Usage: %s [options]\n", argv[0]);
        args.print_help();
        return 0;
    }
    auto mpi_grid_dims = args.value< std::vector<int> >("mpi_grid_dims", {1, 1});
    auto cutoff = args.value<double>("cutoff", 2.0);
    auto num_bands = args.value<int>("num_bands", 10);
    auto use_gpu = args.value<int>("use_gpu", 0);

    sirius::initialize(1);
    for (int i = 0; i < 10; i++) {
        test_hloc(mpi_grid_dims, cutoff, num_bands, use_gpu);
    }
    mpi_comm_world().barrier();
    sddk::timer::print();
    //runtime::Timer::print_all();
    sirius::finalize();
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <string.h>

#include "threads.h"

static struct rejit_thread_t *rejit_thread_acquire(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = r->free;

    if (t) {
        r->free = t->next;
        t->next = t;
        return t;
    }

    return (struct rejit_thread_t *) malloc(sizeof(struct rejit_thread_t)
                                          + sizeof(int) * r->groups);
}

static struct rejit_thread_t *rejit_thread_fork(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = rejit_thread_acquire(r);
    struct rejit_thread_t *c = r->running;

    RE2JIT_NULL_CHECK(t) return NULL;
    rejit_list_append(r->forked, t);
    memcpy(t->groups, c->groups, sizeof(int) * r->groups);
    t->bitmap_id = c->bitmap_id;
    return r->forked = t;
}

static struct rejit_thread_t *rejit_thread_initial(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = rejit_thread_acquire(r);

    RE2JIT_NULL_CHECK(t) return NULL;
    memset(t->groups, 255, sizeof(int) * r->groups);
    t->wait = 0;
    t->state = r->initial;
    t->groups[0] = r->offset;
    t->bitmap_id = ++r->bitmap_id_last;
    rejit_list_append(r->all_threads.last, t);
    rejit_list_append(r->queues[r->queue].last, &t->category);
    return t;
}

int rejit_thread_init(struct rejit_threadset_t *r)
{
    rejit_list_init(&r->all_threads);

    r->bitmap = (uint8_t *) calloc(1, (r->states + 7) / 8);
    RE2JIT_NULL_CHECK(r->bitmap) return 0;
    rejit_list_init(&r->queues[0]);
    rejit_list_init(&r->queues[1]);
    r->empty   = ~(RE2JIT_EMPTY_BEGIN_LINE | RE2JIT_EMPTY_BEGIN_TEXT);
    r->offset  = 0;
    r->queue   = 0;
    r->free    = NULL;
    r->running = NULL;
    r->bitmap_id      = 0;
    r->bitmap_id_last = 0;

    if (!r->length)
        r->empty &= ~(RE2JIT_EMPTY_END_LINE | RE2JIT_EMPTY_END_TEXT);

    RE2JIT_NULL_CHECK(rejit_thread_initial(r)) {
        free(r->bitmap);
        r->bitmap = NULL;
        return 0;
    }

    return 1;
}

void rejit_thread_free(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *a, *b;

    #define FREE_LIST(init, end) do { \
        for (a = init; a != end; ) {  \
            b = a;                    \
            a = a->next;              \
            free(b);                  \
        }                             \
    } while (0)

    FREE_LIST(r->free, NULL);
    FREE_LIST(r->all_threads.first, rejit_list_end(&r->all_threads));
    free(r->bitmap);
    r->bitmap = NULL;
    #undef FREE_LIST
}

int rejit_thread_dispatch(struct rejit_threadset_t *r)
{
    unsigned char queue = r->queue;

    while (1) {
        struct rejit_thread_t *t = r->queues[queue].first;

        for (; t != rejit_list_end(&r->queues[queue]); t = r->queues[queue].first) {
            struct rejit_thread_t *q = RE2JIT_DEREF_THREAD(t);

            if (q->wait) {
                q->wait--;
                rejit_list_remove(&q->category);
                rejit_list_append(r->queues[!queue].last, &q->category);
                continue;
            }

            r->running = q;
            r->forked  = q->prev;
            rejit_list_remove(q);
            rejit_list_remove(&q->category);

            if (r->bitmap_id != q->bitmap_id) {
                r->bitmap_id  = q->bitmap_id;
                memset(r->bitmap, 0, (r->states + 7) / 8);
            }

            r->entry(r, q->state);
            q->next = r->free;
            r->free = q;
        }

        if (!r->length)
            return 0;

        memset(r->bitmap, 0, (r->states + 7) / 8);

        r->queue = queue = !queue;
        r->offset++;
        r->empty = ~0;

        if (*r->input++ == '\n')
            r->empty &= ~RE2JIT_EMPTY_BEGIN_LINE;

        if (--r->length == 0)
            r->empty &= ~(RE2JIT_EMPTY_END_LINE | RE2JIT_EMPTY_END_TEXT);
        else if (*r->input == '\n')
            r->empty &= ~RE2JIT_EMPTY_END_LINE;

        // Word boundaries not supported because UTF-8.

        if (!(r->flags & RE2JIT_ANCHOR_START))
            RE2JIT_NULL_CHECK(rejit_thread_initial(r)) {
                // XOO < *ac was completely screwed out of memory
                //        and nothing can fix that!!*
            }
    }
}

int rejit_thread_match(struct rejit_threadset_t *r)
{
    if ((r->flags & RE2JIT_ANCHOR_END) && r->length)
        // No, it did not. Not EOF yet.
        return 0;

    struct rejit_thread_t *t = rejit_thread_fork(r);
    RE2JIT_NULL_CHECK(t) return 0;
    rejit_list_init(&t->category);
    t->groups[1] = r->offset;

    while (t->next != rejit_list_end(&r->all_threads)) {
        struct rejit_thread_t *q = t->next;
        // Can safely fail all less important threads. If they fail, this one
        // has matched, so whatever. If they match, this one contains better results.
        rejit_list_remove(q);
        rejit_list_remove(&q->category);
        q->next = r->free;
        r->free = q;
    }

    return 1;
}

int rejit_thread_wait(struct rejit_threadset_t *r, const void *state, size_t shift)
{
    struct rejit_thread_t *t = rejit_thread_fork(r);
    RE2JIT_NULL_CHECK(t) return 0;
    t->state = state;
    t->wait  = shift - 1;
    rejit_list_append(r->queues[!r->queue].last, &t->category);
    return 0;
}

int rejit_thread_result(struct rejit_threadset_t *r, int **groups)
{
    if (r->all_threads.first == rejit_list_end(&r->all_threads))
        return 0;

    *groups = r->all_threads.first->groups;
    return 1;
}

struct _bitmap
{
    unsigned old_id;
    uint8_t *old_map;
    uint8_t  bitmap[0];
};

int rejit_thread_bitmap_save(struct rejit_threadset_t *r)
{
    struct _bitmap *s = (struct _bitmap *) malloc(sizeof(struct _bitmap) + (r->states + 7) / 8);

    RE2JIT_NULL_CHECK(s) return 0;
    memset(s->bitmap, 0, (r->states + 7) / 8);
    s->old_id  = r->running->bitmap_id;
    s->old_map = r->bitmap;
    r->bitmap  = s->bitmap;
    r->running->bitmap_id = ++r->bitmap_id_last;
    return 1;
}

void rejit_thread_bitmap_restore(struct rejit_threadset_t *r)
{
    struct _bitmap *s = (struct _bitmap *) (r->bitmap - offsetof(struct _bitmap, bitmap));
    r->bitmap = s->old_map;
    r->running->bitmap_id = s->old_id;
    free(s);
}
<commit_msg>Reserve bitmap id 0 for those filled with -1s.<commit_after>#include <stdlib.h>
#include <string.h>

#include "threads.h"

static struct rejit_thread_t *rejit_thread_acquire(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = r->free;

    if (t) {
        r->free = t->next;
        t->next = t;
        return t;
    }

    return (struct rejit_thread_t *) malloc(sizeof(struct rejit_thread_t)
                                          + sizeof(int) * r->groups);
}

static struct rejit_thread_t *rejit_thread_fork(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = rejit_thread_acquire(r);
    struct rejit_thread_t *c = r->running;

    RE2JIT_NULL_CHECK(t) return NULL;
    rejit_list_append(r->forked, t);
    memcpy(t->groups, c->groups, sizeof(int) * r->groups);
    t->bitmap_id = c->bitmap_id;
    return r->forked = t;
}

static struct rejit_thread_t *rejit_thread_initial(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *t = rejit_thread_acquire(r);

    RE2JIT_NULL_CHECK(t) return NULL;
    memset(t->groups, 255, sizeof(int) * r->groups);
    t->wait = 0;
    t->state = r->initial;
    t->groups[0] = r->offset;
    t->bitmap_id = 0;
    rejit_list_append(r->all_threads.last, t);
    rejit_list_append(r->queues[r->queue].last, &t->category);
    return t;
}

int rejit_thread_init(struct rejit_threadset_t *r)
{
    rejit_list_init(&r->all_threads);

    r->bitmap = (uint8_t *) calloc(1, (r->states + 7) / 8);
    RE2JIT_NULL_CHECK(r->bitmap) return 0;
    rejit_list_init(&r->queues[0]);
    rejit_list_init(&r->queues[1]);
    r->empty   = ~(RE2JIT_EMPTY_BEGIN_LINE | RE2JIT_EMPTY_BEGIN_TEXT);
    r->offset  = 0;
    r->queue   = 0;
    r->free    = NULL;
    r->running = NULL;
    r->bitmap_id      = 0;
    r->bitmap_id_last = 0;

    if (!r->length)
        r->empty &= ~(RE2JIT_EMPTY_END_LINE | RE2JIT_EMPTY_END_TEXT);

    RE2JIT_NULL_CHECK(rejit_thread_initial(r)) {
        free(r->bitmap);
        r->bitmap = NULL;
        return 0;
    }

    return 1;
}

void rejit_thread_free(struct rejit_threadset_t *r)
{
    struct rejit_thread_t *a, *b;

    #define FREE_LIST(init, end) do { \
        for (a = init; a != end; ) {  \
            b = a;                    \
            a = a->next;              \
            free(b);                  \
        }                             \
    } while (0)

    FREE_LIST(r->free, NULL);
    FREE_LIST(r->all_threads.first, rejit_list_end(&r->all_threads));
    free(r->bitmap);
    r->bitmap = NULL;
    #undef FREE_LIST
}

int rejit_thread_dispatch(struct rejit_threadset_t *r)
{
    unsigned char queue = r->queue;

    while (1) {
        struct rejit_thread_t *t = r->queues[queue].first;

        for (; t != rejit_list_end(&r->queues[queue]); t = r->queues[queue].first) {
            struct rejit_thread_t *q = RE2JIT_DEREF_THREAD(t);

            if (q->wait) {
                q->wait--;
                rejit_list_remove(&q->category);
                rejit_list_append(r->queues[!queue].last, &q->category);
                continue;
            }

            r->running = q;
            r->forked  = q->prev;
            rejit_list_remove(q);
            rejit_list_remove(&q->category);

            if (r->bitmap_id != q->bitmap_id) {
                r->bitmap_id  = q->bitmap_id;
                memset(r->bitmap, 0, (r->states + 7) / 8);
            }

            r->entry(r, q->state);
            q->next = r->free;
            r->free = q;
        }

        if (!r->length)
            return 0;

        memset(r->bitmap, 0, (r->states + 7) / 8);

        r->queue = queue = !queue;
        r->offset++;
        r->empty = ~0;

        if (*r->input++ == '\n')
            r->empty &= ~RE2JIT_EMPTY_BEGIN_LINE;

        if (--r->length == 0)
            r->empty &= ~(RE2JIT_EMPTY_END_LINE | RE2JIT_EMPTY_END_TEXT);
        else if (*r->input == '\n')
            r->empty &= ~RE2JIT_EMPTY_END_LINE;

        // Word boundaries not supported because UTF-8.

        if (!(r->flags & RE2JIT_ANCHOR_START))
            RE2JIT_NULL_CHECK(rejit_thread_initial(r)) {
                // XOO < *ac was completely screwed out of memory
                //        and nothing can fix that!!*
            }
    }
}

int rejit_thread_match(struct rejit_threadset_t *r)
{
    if ((r->flags & RE2JIT_ANCHOR_END) && r->length)
        // No, it did not. Not EOF yet.
        return 0;

    struct rejit_thread_t *t = rejit_thread_fork(r);
    RE2JIT_NULL_CHECK(t) return 0;
    rejit_list_init(&t->category);
    t->groups[1] = r->offset;

    while (t->next != rejit_list_end(&r->all_threads)) {
        struct rejit_thread_t *q = t->next;
        // Can safely fail all less important threads. If they fail, this one
        // has matched, so whatever. If they match, this one contains better results.
        rejit_list_remove(q);
        rejit_list_remove(&q->category);
        q->next = r->free;
        r->free = q;
    }

    return 1;
}

int rejit_thread_wait(struct rejit_threadset_t *r, const void *state, size_t shift)
{
    struct rejit_thread_t *t = rejit_thread_fork(r);
    RE2JIT_NULL_CHECK(t) return 0;
    t->state = state;
    t->wait  = shift - 1;
    rejit_list_append(r->queues[!r->queue].last, &t->category);
    return 0;
}

int rejit_thread_result(struct rejit_threadset_t *r, int **groups)
{
    if (r->all_threads.first == rejit_list_end(&r->all_threads))
        return 0;

    *groups = r->all_threads.first->groups;
    return 1;
}

struct _bitmap
{
    unsigned old_id;
    uint8_t *old_map;
    uint8_t  bitmap[0];
};

int rejit_thread_bitmap_save(struct rejit_threadset_t *r)
{
    struct _bitmap *s = (struct _bitmap *) malloc(sizeof(struct _bitmap) + (r->states + 7) / 8);

    RE2JIT_NULL_CHECK(s) return 0;
    memset(s->bitmap, 0, (r->states + 7) / 8);
    s->old_id  = r->running->bitmap_id;
    s->old_map = r->bitmap;
    r->bitmap  = s->bitmap;
    r->running->bitmap_id = ++r->bitmap_id_last;
    return 1;
}

void rejit_thread_bitmap_restore(struct rejit_threadset_t *r)
{
    struct _bitmap *s = (struct _bitmap *) (r->bitmap - offsetof(struct _bitmap, bitmap));
    r->bitmap = s->old_map;
    r->running->bitmap_id = s->old_id;
    free(s);
}
<|endoftext|>


<commit_before>#include "read_fru_data.hpp"

#include "fruread.hpp"
#include "types.hpp"
#include "utils.hpp"

#include <host-ipmid/ipmid-api.h>

#include <map>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

extern const FruMap frus;
namespace ipmi
{
namespace fru
{

namespace variant_ns = sdbusplus::message::variant_ns;

using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);

static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";

namespace cache
{
// User initiate read FRU info area command followed by
// FRU read command. Also data is read in small chunks of
// the specified offset and count.
// Caching the data which will be invalidated when ever there
// is a change in FRU properties.
FRUAreaMap fruMap;
} // namespace cache
/**
 * @brief Read all the property value's for the specified interface
 *  from Inventory.
 *
 * @param[in] intf Interface
 * @param[in] path Object path
 * @return map of properties
 */
ipmi::PropertyMap readAllProperties(const std::string& intf,
                                    const std::string& path)
{
    ipmi::PropertyMap properties;
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
    auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
    std::string objPath = OBJ_PATH + path;
    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
                                      PROP_INTF, "GetAll");
    method.append(intf);
    auto reply = bus.call(method);
    if (reply.is_method_error())
    {
        // If property is not found simply return empty value
        log<level::ERR>("Error in reading property values from inventory",
                        entry("INTERFACE=%s", intf.c_str()),
                        entry("PATH=%s", objPath.c_str()));
        return properties;
    }
    reply.read(properties);
    return properties;
}

void processFruPropChange(sdbusplus::message::message& msg)
{
    if (cache::fruMap.empty())
    {
        return;
    }
    std::string path = msg.get_path();
    // trim the object base path, if found at the beginning
    if (path.compare(0, strlen(OBJ_PATH), OBJ_PATH) == 0)
    {
        path.erase(0, strlen(OBJ_PATH));
    }
    for (auto& fru : frus)
    {
        bool found = false;
        auto& instanceList = fru.second;
        for (auto& instance : instanceList)
        {
            if (instance.path == path)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            auto& fruId = fru.first;

            cache::fruMap.erase(fruId);
            break;
        }
    }
}

// register for fru property change
int registerCallbackHandler()
{
    if (matchPtr == nullptr)
    {
        using namespace sdbusplus::bus::match::rules;
        sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
        matchPtr = std::make_unique<sdbusplus::bus::match_t>(
            bus,
            path_namespace(OBJ_PATH) + type::signal() +
                member("PropertiesChanged") + interface(PROP_INTF),
            std::bind(processFruPropChange, std::placeholders::_1));
    }
    return 0;
}

/**
 * @brief Read FRU property values from Inventory
 *
 * @param[in] fruNum  FRU id
 * @return populate FRU Inventory data
 */
FruInventoryData readDataFromInventory(const FRUId& fruNum)
{
    auto iter = frus.find(fruNum);
    if (iter == frus.end())
    {
        log<level::ERR>("Unsupported FRU ID ", entry("FRUID=%d", fruNum));
        elog<InternalFailure>();
    }

    FruInventoryData data;
    auto& instanceList = iter->second;
    for (auto& instance : instanceList)
    {
        for (auto& intf : instance.interfaces)
        {
            ipmi::PropertyMap allProp =
                readAllProperties(intf.first, instance.path);
            for (auto& properties : intf.second)
            {
                auto iter = allProp.find(properties.first);
                if (iter != allProp.end())
                {
                    data[properties.second.section].emplace(
                        properties.first,
                        std::move(variant_ns::get<std::string>(
                            allProp[properties.first])));
                }
            }
        }
    }
    return data;
}

const FruAreaData& getFruAreaData(const FRUId& fruNum)
{
    auto iter = cache::fruMap.find(fruNum);
    if (iter != cache::fruMap.end())
    {
        return iter->second;
    }
    auto invData = readDataFromInventory(fruNum);

    // Build area info based on inventory data
    FruAreaData newdata = buildFruAreaData(std::move(invData));
    cache::fruMap.emplace(fruNum, std::move(newdata));
    return cache::fruMap.at(fruNum);
}
} // namespace fru
} // namespace ipmi
<commit_msg>read_fru_data: use std::find_if instead of raw loop<commit_after>#include "read_fru_data.hpp"

#include "fruread.hpp"
#include "types.hpp"
#include "utils.hpp"

#include <host-ipmid/ipmid-api.h>

#include <algorithm>
#include <map>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

extern const FruMap frus;
namespace ipmi
{
namespace fru
{

namespace variant_ns = sdbusplus::message::variant_ns;

using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);

static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";

namespace cache
{
// User initiate read FRU info area command followed by
// FRU read command. Also data is read in small chunks of
// the specified offset and count.
// Caching the data which will be invalidated when ever there
// is a change in FRU properties.
FRUAreaMap fruMap;
} // namespace cache
/**
 * @brief Read all the property value's for the specified interface
 *  from Inventory.
 *
 * @param[in] intf Interface
 * @param[in] path Object path
 * @return map of properties
 */
ipmi::PropertyMap readAllProperties(const std::string& intf,
                                    const std::string& path)
{
    ipmi::PropertyMap properties;
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
    auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
    std::string objPath = OBJ_PATH + path;
    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
                                      PROP_INTF, "GetAll");
    method.append(intf);
    auto reply = bus.call(method);
    if (reply.is_method_error())
    {
        // If property is not found simply return empty value
        log<level::ERR>("Error in reading property values from inventory",
                        entry("INTERFACE=%s", intf.c_str()),
                        entry("PATH=%s", objPath.c_str()));
        return properties;
    }
    reply.read(properties);
    return properties;
}

void processFruPropChange(sdbusplus::message::message& msg)
{
    if (cache::fruMap.empty())
    {
        return;
    }
    std::string path = msg.get_path();
    // trim the object base path, if found at the beginning
    if (path.compare(0, strlen(OBJ_PATH), OBJ_PATH) == 0)
    {
        path.erase(0, strlen(OBJ_PATH));
    }
    for (auto& fru : frus)
    {
        auto& instanceList = fru.second;

        auto found = std::find_if(
            instanceList.begin(), instanceList.end(),
            [&path](const auto& iter) { return (iter.path == path); });

        if (found != instanceList.end())
        {
            auto& fruId = fru.first;

            cache::fruMap.erase(fruId);
            break;
        }
    }
}

// register for fru property change
int registerCallbackHandler()
{
    if (matchPtr == nullptr)
    {
        using namespace sdbusplus::bus::match::rules;
        sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
        matchPtr = std::make_unique<sdbusplus::bus::match_t>(
            bus,
            path_namespace(OBJ_PATH) + type::signal() +
                member("PropertiesChanged") + interface(PROP_INTF),
            std::bind(processFruPropChange, std::placeholders::_1));
    }
    return 0;
}

/**
 * @brief Read FRU property values from Inventory
 *
 * @param[in] fruNum  FRU id
 * @return populate FRU Inventory data
 */
FruInventoryData readDataFromInventory(const FRUId& fruNum)
{
    auto iter = frus.find(fruNum);
    if (iter == frus.end())
    {
        log<level::ERR>("Unsupported FRU ID ", entry("FRUID=%d", fruNum));
        elog<InternalFailure>();
    }

    FruInventoryData data;
    auto& instanceList = iter->second;
    for (auto& instance : instanceList)
    {
        for (auto& intf : instance.interfaces)
        {
            ipmi::PropertyMap allProp =
                readAllProperties(intf.first, instance.path);
            for (auto& properties : intf.second)
            {
                auto iter = allProp.find(properties.first);
                if (iter != allProp.end())
                {
                    data[properties.second.section].emplace(
                        properties.first,
                        std::move(variant_ns::get<std::string>(
                            allProp[properties.first])));
                }
            }
        }
    }
    return data;
}

const FruAreaData& getFruAreaData(const FRUId& fruNum)
{
    auto iter = cache::fruMap.find(fruNum);
    if (iter != cache::fruMap.end())
    {
        return iter->second;
    }
    auto invData = readDataFromInventory(fruNum);

    // Build area info based on inventory data
    FruAreaData newdata = buildFruAreaData(std::move(invData));
    cache::fruMap.emplace(fruNum, std::move(newdata));
    return cache::fruMap.at(fruNum);
}
} // namespace fru
} // namespace ipmi
<|endoftext|>


<commit_before><commit_msg>_sent in AgencyCommResult assigned too late?<commit_after><|endoftext|>