← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3196: add a text replacement function to the XML tagger

 

------------------------------------------------------------
revno: 3196
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Tue 2013-01-29 19:08:36 +0100
message:
  add a text replacement function to the XML tagger
modified:
  dcpp/ChatMessage.cpp
  dcpp/ChatMessage.h
  dcpp/PluginApiImpl.cpp
  dcpp/PluginApiImpl.h
  dcpp/PluginDefs.h
  dcpp/PluginManager.cpp
  dcpp/PluginManager.h
  dcpp/Tagger.cpp
  dcpp/Tagger.h
  win32/AspectChat.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ChatMessage.cpp'
--- dcpp/ChatMessage.cpp	2013-01-18 21:28:38 +0000
+++ dcpp/ChatMessage.cpp	2013-01-29 18:08:36 +0000
@@ -96,13 +96,13 @@
 	message += tmp;
 
 	/* format the message; this will involve adding custom tags. use the Tagger class to that end. */
-	Tagger tags;
-	format(tmp, tags, xmlTmp);
+	Tagger tags(move(tmp));
+	format(tags, xmlTmp);
 
 	// let plugins play with the tag list
-	PluginManager::getInstance()->onChatTags(tmp, tags, from);
+	PluginManager::getInstance()->onChatTags(tags, from);
 
-	htmlMessage += "<span id=\"text\">" + tags.merge(tmp, xmlTmp) + "</span></span>";
+	htmlMessage += "<span id=\"text\">" + tags.merge(xmlTmp) + "</span></span>";
 
 	// forward to plugins
 	PluginManager::getInstance()->onChatDisplay(htmlMessage, from);
@@ -114,12 +114,14 @@
 		(!first && (c == '+' || c == '.' || c == '-'));
 } }
 
-void ChatMessage::format(string& text, Tagger& tags, string& tmp) {
+void ChatMessage::format(Tagger& tags, string& tmp) {
+	const auto& text = tags.getText();
+
 	/* link formatting - optimize the lookup a bit by using the fact that every link identifier
 	(except www ones) contains a colon. */
 
 	auto addLinkStr = [&tmp, &tags](size_t begin, size_t end, const string& link) {
-		tags.add(begin, end, "a", "href=\"" + SimpleXML::escape(link, tmp, true) + "\"");
+		tags.addTag(begin, end, "a", "href=\"" + SimpleXML::escape(link, tmp, true) + "\"");
 	};
 
 	auto addLink = [&text, &addLinkStr](size_t begin, size_t end) {
@@ -154,10 +156,10 @@
 				if(!name.empty()) {
 					// magnet link: replace with the friendly name
 					name += " (magnet)";
-					text.replace(begin, end - begin, name);
+					tags.replaceText(begin, end, name);
 
 					// the size of the string has changed; update counts.
-					auto delta = name.size() - link.size();
+					const auto delta = static_cast<int>(name.size()) - static_cast<int>(link.size());
 					end += delta;
 					n += delta;
 				}

=== modified file 'dcpp/ChatMessage.h'
--- dcpp/ChatMessage.h	2013-01-18 21:28:38 +0000
+++ dcpp/ChatMessage.h	2013-01-29 18:08:36 +0000
@@ -61,7 +61,7 @@
 
 	/** Store context-agnostic formattings that can be applied to the given message in the tagger.
 	Note that the string may be modified. */
-	static void format(string& text, Tagger& tags, string& tmp);
+	static void format(Tagger& tags, string& tmp);
 };
 
 } // namespace dcpp

=== modified file 'dcpp/PluginApiImpl.cpp'
--- dcpp/PluginApiImpl.cpp	2013-01-18 21:28:38 +0000
+++ dcpp/PluginApiImpl.cpp	2013-01-29 18:08:36 +0000
@@ -168,7 +168,10 @@
 DCTagger PluginApiImpl::dcTagger = {
 	DCINTF_DCPP_TAGGER_VER,
 
-	&PluginApiImpl::addTag
+	&PluginApiImpl::addTag,
+
+	&PluginApiImpl::getText,
+	&PluginApiImpl::replaceText
 };
 
 Socket* PluginApiImpl::udpSocket = nullptr;
@@ -497,7 +500,15 @@
 
 // Functions for DCTagger
 void PluginApiImpl::addTag(TagDataPtr hTags, size_t start, size_t end, const char* id, const char* attributes) {
-	reinterpret_cast<Tagger*>(hTags->object)->add(start, end, id, attributes);
+	reinterpret_cast<Tagger*>(hTags->object)->addTag(start, end, id, attributes);
+}
+
+const char* PluginApiImpl::getText(TagDataPtr hTags) {
+	return reinterpret_cast<Tagger*>(hTags->object)->getText().c_str();
+}
+
+void PluginApiImpl::replaceText(TagDataPtr hTags, size_t start, size_t end, const char* replacement) {
+	reinterpret_cast<Tagger*>(hTags->object)->replaceText(start, end, replacement);
 }
 
 // Functions for DCQueue

=== modified file 'dcpp/PluginApiImpl.h'
--- dcpp/PluginApiImpl.h	2013-01-18 21:28:38 +0000
+++ dcpp/PluginApiImpl.h	2013-01-29 18:08:36 +0000
@@ -94,6 +94,9 @@
 	// Functions for DCTagger
 	static void DCAPI addTag(TagDataPtr hTags, size_t start, size_t end, const char* id, const char* attributes);
 
+	static const char* DCAPI getText(TagDataPtr hTags);
+	static void DCAPI replaceText(TagDataPtr hTags, size_t start, size_t end, const char* replacement);
+
 	// Functions for DCQueue
 	static QueueDataPtr DCAPI addList(UserDataPtr user, Bool silent);
 	static QueueDataPtr DCAPI addDownload(const char* hash, uint64_t size, const char* target);

=== modified file 'dcpp/PluginDefs.h'
--- dcpp/PluginDefs.h	2013-01-18 21:28:38 +0000
+++ dcpp/PluginDefs.h	2013-01-29 18:08:36 +0000
@@ -77,7 +77,7 @@
 #define DCINTF_DCPP_UTILS_VER		1
 
 #define DCINTF_DCPP_TAGGER			"dcpp.xml.DCTagger"			/* Manipulation of an XML tagger */
-#define DCINTF_DCPP_TAGGER_VER		1
+#define DCINTF_DCPP_TAGGER_VER		2
 
 #define DCINTF_DCPP_UI				"dcpp.ui.DCUI"				/* User interface */
 #define DCINTF_DCPP_UI_VER			1
@@ -259,7 +259,6 @@
 
 /* Tagging intentions */
 typedef struct tagTagData {
-	const char* text;											/* Plain text string to apply tags on */
 	dcptr_t object;												/* Internal */
 	Bool isManaged;												/* Always True for now */
 } TagData, *TagDataPtr;
@@ -426,6 +425,10 @@
 	uint32_t apiVersion;
 
 	void		(DCAPI *add_tag)					(TagDataPtr hTags, size_t start, size_t end, const char* id, const char* attributes);
+
+	/* Version 2 functions */
+	const char*	(DCAPI *get_text)					(TagDataPtr hTags);
+	void		(DCAPI *replace_text)				(TagDataPtr hTags, size_t start, size_t end, const char* replacement);
 } DCTagger, *DCTaggerPtr;
 
 /* User interface */

=== modified file 'dcpp/PluginManager.cpp'
--- dcpp/PluginManager.cpp	2013-01-18 21:28:38 +0000
+++ dcpp/PluginManager.cpp	2013-01-29 18:08:36 +0000
@@ -207,8 +207,8 @@
 }
 
 // Functions that call the plugin
-bool PluginManager::onChatTags(const string& text, Tagger& tagger, OnlineUser* from) {
-	TagData data = { text.c_str(), reinterpret_cast<dcptr_t>(&tagger), True };
+bool PluginManager::onChatTags(Tagger& tagger, OnlineUser* from) {
+	TagData data = { reinterpret_cast<dcptr_t>(&tagger), True };
 	return runHook(HOOK_UI_CHAT_TAGS, from, &data);
 }
 

=== modified file 'dcpp/PluginManager.h'
--- dcpp/PluginManager.h	2013-01-18 21:28:38 +0000
+++ dcpp/PluginManager.h	2013-01-29 18:08:36 +0000
@@ -111,7 +111,7 @@
 	DCCorePtr getCore() { return &dcCore; }
 
 	// Functions that call the plugin
-	bool onChatTags(const string& text, Tagger& tagger, OnlineUser* from = nullptr);
+	bool onChatTags(Tagger& tagger, OnlineUser* from = nullptr);
 	bool onChatDisplay(string& htmlMessage, OnlineUser* from = nullptr);
 	bool onChatCommand(Client* client, const string& line);
 	bool onChatCommandPM(const HintedUser& user, const string& line);

=== modified file 'dcpp/Tagger.cpp'
--- dcpp/Tagger.cpp	2013-01-18 21:28:38 +0000
+++ dcpp/Tagger.cpp	2013-01-29 18:08:36 +0000
@@ -29,21 +29,47 @@
 
 using std::vector;
 
-void Tagger::add(size_t start, size_t end, string id, string attributes) {
-	Tag openingTag = { start, "<" + id + " " + move(attributes) + ">", true },
-		closingTag = { end, "</" + move(id) + ">", false };
-
-	tags.push_back(std::move(openingTag));
+Tagger::Tagger(const string& text) : text(text)
+{
+}
+
+Tagger::Tagger(string&& text) : text(move(text))
+{
+}
+
+const string& Tagger::getText() const {
+	return text;
+}
+
+void Tagger::addTag(size_t start, size_t end, string id, string attributes) {
+	Tag openingTag { start, "<" + id + " " + move(attributes) + ">", true };
+	Tag closingTag { end, "</" + move(id) + ">", false };
+
+	tags.push_back(move(openingTag));
 	auto& opening = tags.back();
 
-	tags.push_back(std::move(closingTag));
+	tags.push_back(move(closingTag));
 	auto& closing = tags.back();
 
 	opening.otherTag = &closing;
 	closing.otherTag = &opening;
 }
 
-string Tagger::merge(const string& text, string& tmp) {
+void Tagger::replaceText(size_t start, size_t end, const string& replacement) {
+	text.replace(start, end - start, replacement);
+
+	const auto delta = static_cast<int>(replacement.size()) - static_cast<int>(end - start);
+
+	for(auto& tag: tags) {
+		if(tag.pos >= end) {
+			tag.pos -= delta;
+		} else if(tag.pos > start) {
+			tag.pos = start;
+		}
+	}
+}
+
+string Tagger::merge(string& tmp) {
 	tags.sort([](const Tag& a, const Tag& b) { return a.pos < b.pos; });
 
 	string ret;

=== modified file 'dcpp/Tagger.h'
--- dcpp/Tagger.h	2013-01-18 21:28:38 +0000
+++ dcpp/Tagger.h	2013-01-29 18:08:36 +0000
@@ -33,10 +33,18 @@
 entangled tags, such as: <a> <b> </a> </b> -> <a> <b> </b></a><b> </b> */
 class Tagger {
 public:
-	void add(size_t start, size_t end, string id, string attributes);
-	string merge(const string& text, string& tmp);
+	Tagger(const string& text);
+	Tagger(string&& text);
+
+	const string& getText() const;
+
+	void addTag(size_t start, size_t end, string id, string attributes);
+	void replaceText(size_t start, size_t end, const string& replacement);
+	string merge(string& tmp);
 
 private:
+	string text;
+
 	struct Tag { size_t pos; string s; bool opening; Tag* otherTag; };
 	list<Tag> tags; // this table holds the tags to be added along with their position.
 };

=== modified file 'win32/AspectChat.h'
--- win32/AspectChat.h	2013-01-18 21:28:38 +0000
+++ win32/AspectChat.h	2013-01-29 18:08:36 +0000
@@ -75,16 +75,16 @@
 
 	/// add a chat message with some formatting and call addedChat.
 	void addChat(const tstring& message) {
-		string xmlTmp, tmp = Text::fromT(message);
-
-		Tagger tags;
-		ChatMessage::format(tmp, tags, xmlTmp);
-
-		PluginManager::getInstance()->onChatTags(tmp, tags);
+		string tmp;
+
+		Tagger tags(Text::fromT(message));
+		ChatMessage::format(tags, tmp);
+
+		PluginManager::getInstance()->onChatTags(tags);
 
 		string htmlMessage = "<span id=\"message\" style=\"white-space: pre-wrap;\">"
-			"<span id=\"timestamp\">" + SimpleXML::escape("[" + Util::getShortTimeString() + "]", xmlTmp, false) + "</span> "
-			"<span id=\"text\">" + tags.merge(tmp, xmlTmp) + "</span></span>";
+			"<span id=\"timestamp\">" + SimpleXML::escape("[" + Util::getShortTimeString() + "]", tmp, false) + "</span> "
+			"<span id=\"text\">" + tags.merge(tmp) + "</span></span>";
 
 		PluginManager::getInstance()->onChatDisplay(htmlMessage);