Browse Source

Optimized StringToBuffer & BufferToString.
Fixed warnings in XMLElement.

Lasse Öörni 12 years ago
parent
commit
b6366ff982

+ 78 - 8
Engine/Core/StringUtils.cpp

@@ -358,12 +358,49 @@ String ToStringHex(unsigned value)
 
 void BufferToString(String& dest, const void* data, unsigned size)
 {
-    /// \todo Optimize, resize the string only once
+    // Precalculate needed string size
     const unsigned char* bytes = (const unsigned char*)data;
-    dest.Clear();
+    unsigned length = 0;
+    for (unsigned i = 0; i < size; ++i)
+    {
+        // Room for separator
+        if (i)
+            ++length;
+        
+        // Room for the value
+        if (bytes[i] < 10)
+            ++length;
+        else if (bytes[i] < 100)
+            length += 2;
+        else
+            length += 3;
+    }
     
+    dest.Resize(length);
+    unsigned index = 0;
+    
+    // Convert values
     for (unsigned i = 0; i < size; ++i)
-        dest += String((unsigned)bytes[i]) + " ";
+    {
+        if (i)
+            dest[index++] = ' ';
+        
+        if (bytes[i] < 10)
+        {
+            dest[index++] = '0' + bytes[i];
+        }
+        else if (bytes[i] < 100)
+        {
+            dest[index++] = '0' + bytes[i] / 10;
+            dest[index++] = '0' + bytes[i] % 10;
+        }
+        else
+        {
+            dest[index++] = '0' + bytes[i] / 100;
+            dest[index++] = '0' + bytes[i] % 100 / 10;
+            dest[index++] = '0' + bytes[i] % 10;
+        }
+    }
 }
 
 void StringToBuffer(PODVector<unsigned char>& dest, const String& source)
@@ -373,12 +410,45 @@ void StringToBuffer(PODVector<unsigned char>& dest, const String& source)
 
 void StringToBuffer(PODVector<unsigned char>& dest, const char* source)
 {
-    /// \todo Optimize, parse the string in-place without splitting
-    Vector<String> bytes = String::Split(source, ' ');
+    if (!source)
+    {
+        dest.Clear();
+        return;
+    }
+    
+    unsigned size = CountElements(source, ' ');
+    dest.Resize(size);
+    
+    bool inSpace = true;
+    unsigned index = 0;
+    unsigned value = 0;
+    
+    // Parse values
+    const char* ptr = source;
+    while (*ptr)
+    {
+        if (inSpace && *ptr != ' ')
+        {
+            inSpace = false;
+            value = *ptr - '0';
+        }
+        else if (!inSpace && *ptr != ' ')
+        {
+            value *= 10;
+            value += *ptr - '0';
+        }
+        else if (!inSpace && *ptr == ' ')
+        {
+            dest[index++] = value;
+            inSpace = true;
+        }
+        
+        ++ptr;
+    }
     
-    dest.Resize(bytes.Size());
-    for (unsigned i = 0; i < bytes.Size(); ++i)
-        dest[i] = ToInt(bytes[i]);
+    // Write the final value
+    if (!inSpace && index < size)
+        dest[index] = value;
 }
 
 unsigned GetStringListIndex(const String& value, const String* strings, unsigned defaultIndex, bool caseSensitive)

+ 3 - 3
Engine/IO/FileWatcher.cpp

@@ -24,7 +24,7 @@
 #include "File.h"
 #include "FileSystem.h"
 #include "FileWatcher.h"
-#include "Log.h"
+#include "Log.h"
 #include "Timer.h"
 
 #ifdef WIN32
@@ -290,8 +290,8 @@ void FileWatcher::ThreadFunction()
     }
 #elif defined(__APPLE__) && !defined(IOS)
     while (shouldRun_)
-    {
-        Time::Sleep(100);
+    {
+        Time::Sleep(100);
 
         String changes = ReadFileWatcher(watcher_);
         if (!changes.Empty())

+ 15 - 5
Engine/Resource/XMLElement.cpp

@@ -559,13 +559,18 @@ bool XMLElement::HasAttribute(const char* name) const
 
 String XMLElement::GetAttribute(const String& name) const
 {
-    return String(GetAttribute(name.CString()));
+    return String(GetAttributeCString(name.CString()));
 }
 
 String XMLElement::GetAttribute(const char* name) const
+{
+    return String(GetAttributeCString(name));
+}
+
+const char* XMLElement::GetAttributeCString(const char* name) const
 {
     if (!file_ || (!node_ && !xpathNode_))
-        return String::EMPTY;
+        return 0;
 
     // If xpath_node contains just attribute, return it regardless of the specified name
     if (xpathNode_ && xpathNode_->attribute())
@@ -707,7 +712,7 @@ Variant XMLElement::GetVariantValue(VariantType type) const
     else if (type == VAR_VARIANTMAP)
         ret = GetVariantMap();
     else
-        ret.FromString(type, GetAttribute("value"));
+        ret.FromString(type, GetAttributeCString("value"));
 
     return ret;
 }
@@ -931,7 +936,12 @@ bool XPathQuery::SetVariable(const String& name, const XPathResultSet& value)
 {
     if (!variables_)
         variables_ = new pugi::xpath_variable_set();
-    return variables_->set(name.CString(), value.GetXPathNodeSet());
+    
+    pugi::xpath_node_set* nodeSet = value.GetXPathNodeSet();
+    if (!nodeSet)
+        return false;
+    
+    return variables_->set(name.CString(), *nodeSet);
 }
 
 bool XPathQuery::SetQuery(const String& queryString, const String& variableString, bool bind)
@@ -999,7 +1009,7 @@ float XPathQuery::EvaluateToFloat(XMLElement element) const
         return 0.0f;
 
     const pugi::xml_node& node = element.GetXPathNode() ? element.GetXPathNode()->node(): pugi::xml_node(element.GetNode());
-    return query_->evaluate_number(node);
+    return (float)query_->evaluate_number(node);
 }
 
 String XPathQuery::EvaluateToString(XMLElement element) const

+ 3 - 0
Engine/Resource/XMLElement.h

@@ -173,6 +173,8 @@ public:
     String GetAttribute(const String& name = String::EMPTY) const;
     /// Return attribute, or empty if missing.
     String GetAttribute(const char* name) const;
+    /// Return attribute as C string, or null if missing.
+    const char* GetAttributeCString(const char* name) const;
     /// Return attribute in lowercase, or empty if missing.
     String GetAttributeLower(const String& name) const;
     /// Return attribute in lowercase, or empty if missing.
@@ -239,6 +241,7 @@ public:
     unsigned GetXPathResultIndex() const { return xpathResultIndex_; }
     /// Return next XPath query result. Only valid when this instance of XMLElement is itself one of the query result in the result set.
     XMLElement NextResult() const;
+    
     /// Empty XMLElement.
     static const XMLElement EMPTY;