]> Dogcows Code - chaz/yoink/blobdiff - src/moof/string.cc
fixed documentation about where to find licenses
[chaz/yoink] / src / moof / string.cc
index a2c27bb25cf3b670d9b04c66c498c55e53530f9e..995553c59f58d24980ef37bd1adbd1d41b5d1dea 100644 (file)
 
-/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+/*]  Copyright (c) 2009-2011, Charles McGarvey  [*****************************
 **]  All rights reserved.
 *
-* vi:ts=4 sw=4 tw=75
-*
 * Distributable under the terms and conditions of the 2-clause BSD license;
 * see the file COPYING for a complete text of the license.
 *
-**************************************************************************/
+*****************************************************************************/
 
 #include <stdexcept>
 
-#include "ConvertUTF.h"
+#include <boost/shared_array.hpp>
+
+#include "script.hh"
 #include "string.hh"
+#include "ConvertUTF.h"
 
 
 namespace moof {
 
 
-// TODO this code is ugly
-
 wstring multi_to_wide(const string& multi)
 {
-       size_t length = multi.length();
+       typedef boost::shared_array<wchar_t> buffer;
 
        if (sizeof(wchar_t) == 2)
        {
-               wchar_t* wide = new wchar_t[length + 1];
-
-               const UTF8* srcStart = reinterpret_cast<const UTF8*>(multi.c_str());
-               const UTF8* srcEnd = srcStart + length;
-               UTF16* targetStart = reinterpret_cast<UTF16*>(wide);
-               UTF16* targetEnd = targetStart + length+1;
-
-               ConversionResult res = ConvertUTF8toUTF16(&srcStart, srcEnd,
-                               &targetStart, targetEnd, lenientConversion);
-               if (res != conversionOK)
-               {
-                       delete[] wide;
-                       throw std::runtime_error("bad conversion from multi to wide characters");
-               }
-
-               *targetStart = 0;
-               wstring convertedStr(wide);
-               delete[] wide;
-
-               return convertedStr;
+               size_t          length = multi.length();
+               buffer          wide(new wchar_t[length + 1]);
+               const UTF8*     src1 = (const UTF8*)multi.c_str();
+               const UTF8*     src2 = src1 + length;
+               UTF16*          dst1 = (UTF16*)wide.get();
+               UTF16*          dst2 = dst1 + length + 1;
+
+               if (ConvertUTF8toUTF16(&src1, src2,
+                                       &dst1, dst2,
+                                       lenientConversion) != conversionOK)
+                       throw std::runtime_error("bad string conversion");
+
+               *dst1 = 0;
+               wstring str(wide.get());
+               return str;
        }
        else if (sizeof(wchar_t) == 4)
        {
-               wchar_t* wide = new wchar_t[length];
-
-               const UTF8* srcStart = reinterpret_cast<const UTF8*>(multi.c_str());
-               const UTF8* srcEnd = srcStart + length;
-               UTF32* targetStart = reinterpret_cast<UTF32*>(wide);
-               UTF32* targetEnd = targetStart + length;
-
-               ConversionResult res = ConvertUTF8toUTF32(&srcStart, srcEnd,
-                               &targetStart, targetEnd, lenientConversion);
-               if (res != conversionOK)
-               {
-                       delete[] wide;
-                       throw std::runtime_error("bad conversion from multi to wide characters");
-               }
-
-               *targetStart = 0;
-               wstring convertedStr(wide);
-               delete[] wide;
-
-               return convertedStr;
+               size_t          length = multi.length();
+               buffer          wide(new wchar_t[length + 1]);
+               const UTF8*     src1 = (const UTF8*)multi.c_str();
+               const UTF8*     src2 = src1 + length;
+               UTF32*          dst1 = (UTF32*)wide.get();
+               UTF32*          dst2 = dst1 + length + 1;
+
+               if (ConvertUTF8toUTF32(&src1, src2,
+                                       &dst1, dst2,
+                                       lenientConversion) != conversionOK)
+                       throw std::runtime_error("bad string conversion");
+
+               *dst1 = 0;
+               wstring str(wide.get());
+               return str;
        }
        else
        {
                throw std::runtime_error("unknown size of wide characters");
        }
-       return L"";
 }
 
 string wide_to_multi(const wstring& wide)
 {
-       size_t length = wide.length();
+       typedef boost::shared_array<char> buffer;
 
        if (sizeof(wchar_t) == 2)
        {
-               size_t multiLength = 3 * length + 1;
-               char* multi = new char[multiLength];
-
-               const UTF16* srcStart = reinterpret_cast<const UTF16*>(wide.c_str());
-               const UTF16* srcEnd = srcStart + length;
-               UTF8* targetStart = reinterpret_cast<UTF8*>(multi);
-               UTF8* targetEnd = targetStart + multiLength;
-
-               ConversionResult res = ConvertUTF16toUTF8(&srcStart, srcEnd,
-                               &targetStart, targetEnd, lenientConversion);
-               if (res != conversionOK)
-               {
-                       delete[] multi;
-                       throw std::runtime_error("bad conversion from wide to multi-characters");
-               }
-
-               *targetStart = 0;
-               string convertedStr(multi);
-               delete[] multi;
-
-               return convertedStr;
+               size_t          length = wide.length();
+               size_t          multi_length = 3 * length + 1;
+               buffer          multi(new char[multi_length]);
+               const UTF16*    src1 = (const UTF16*)wide.c_str();
+               const UTF16*    src2 = src1 + length;
+               UTF8*           dst1 = (UTF8*)multi.get();
+               UTF8*           dst2 = dst1 + multi_length;
+
+               if (ConvertUTF16toUTF8(&src1, src2,
+                                       &dst1, dst2,
+                                       lenientConversion) != conversionOK)
+                       throw std::runtime_error("bad string conversion");
+
+               *dst1 = 0;
+               string str(multi.get());
+               return str;
        }
        else if (sizeof(wchar_t) == 4)
        {
-               size_t multiLength = 4 * length + 1;
-               char* multi = new char[multiLength];
-
-               const UTF32* srcStart = reinterpret_cast<const UTF32*>(wide.c_str());
-               const UTF32* srcEnd = srcStart + length;
-               UTF8* targetStart = reinterpret_cast<UTF8*>(multi);
-               UTF8* targetEnd = targetStart + multiLength;
-
-               ConversionResult res = ConvertUTF32toUTF8(&srcStart, srcEnd,
-                               &targetStart, targetEnd, lenientConversion);
-               if (res != conversionOK)
-               {
-                       delete[] multi;
-                       throw std::runtime_error("bad conversion from wide to multi-characters");
-               }
-
-               *targetStart = 0;
-               string convertedStr(multi);
-               delete[] multi;
-
-               return convertedStr;
+               size_t          length = wide.length();
+               size_t          multi_length = 4 * length + 1;
+               buffer          multi(new char[multi_length]);
+               const UTF32*    src1 = (const UTF32*)wide.c_str();
+               const UTF32*    src2 = src1 + length;
+               UTF8*           dst1 = (UTF8*)multi.get();
+               UTF8*           dst2 = dst1 + multi_length;
+
+               if (ConvertUTF32toUTF8(&src1, src2,
+                                       &dst1, dst2,
+                                       lenientConversion) != conversionOK)
+                       throw std::runtime_error("bad string conversion");
+
+               *dst1 = 0;
+               string str(multi.get());
+               return str;
        }
        else
        {
                throw std::runtime_error("unknown size of wide characters");
        }
-       return "";
+}
+
+
+static script& pattern_script()
+{
+       static script   script;
+       static bool     init = true;
+       if (init)
+       {
+               script.import_string_library();
+               script.globals().push_field("string").push_field("match");
+               script.globals().set_field("match");
+               script.top().push_field("gmatch");
+               script.globals().set_field("gmatch");
+               script.top().push_field("gsub");
+               script.globals().set_field("gsub");
+               script.push_nil();
+               script.globals().set_field("string");
+               script.pop();
+               init = false;
+       }
+       return script;
+}
+
+pattern::pattern(const std::string& pattern)
+{
+       pattern::string(pattern);
+}
+
+pattern::pattern(const std::string& pattern, const std::string& source)
+{
+       pattern::string(pattern);
+       match(source);
+}
+
+pattern::~pattern()
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+       script.push_nil();
+       script.globals().set_field();
+       script.push_pointer(this);
+       script.push_nil();
+       script.registry().set_field();
+}
+
+std::string pattern::string() const
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+       script::slot saved = script.registry().push_field();
+
+       std::string pattern;
+       saved.get(pattern);
+
+       saved.pop();
+       return pattern;
+}
+
+void pattern::string(const std::string& pattern)
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+       script.push(pattern);
+       script.registry().set_field();
+}
+
+void pattern::match(const std::string& source)
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+
+       script.globals().push_field("gmatch");
+       script.push(source);
+       script.push_pointer(this);
+       script.registry().push_field();
+       script.call(2, 1);
+
+       script.globals().set_field();
+}
+
+bool pattern::get(std::string& match)
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+       script::slot value = script.globals().push_field();
+       if (!value.is_function())
+       {
+               script.clear_stack();
+               return false;
+       }
+
+       script.call(0, 1);
+       bool result = value.get(match);
+       script.pop();
+       return result;
+}
+
+bool pattern::get(std::vector<std::string>& captures)
+{
+       script& script = pattern_script();
+       script.push_pointer(this);
+       script::slot value = script.globals().push_field();
+       if (!value.is_function())
+       {
+               script.clear_stack();
+               return false;
+       }
+
+       script.call();
+       captures.clear();
+
+       while (value.is_string())
+       {
+               captures.resize(captures.size() + 1);
+               value.get(captures.back());
+               ++value.index;
+       }
+
+       script.clear_stack();
+       return 0 < captures.size();
+}
+
+bool pattern::match(std::string& match,
+               const std::string& pattern, const std::string& source, int position)
+{
+       script& script = pattern_script();
+       script::slot value = script.globals().push_field("match");
+       script.push(source);
+       script.push(pattern);
+       ++position;     // lua indices count from one
+       script.push(position);
+       script.call(3, 1);
+
+       bool result = value.get(match);
+       script.clear_stack();
+       return result;
+}
+
+bool pattern::match(std::vector<std::string>& captures,
+               const std::string& pattern, const std::string& source, int position)
+{
+       script& script = pattern_script();
+       script::slot value = script.globals().push_field("match");
+       script.push(source);
+       script.push(pattern);
+       ++position;     // lua indices count from one
+       script.push(position);
+       script.call(3);
+
+       captures.clear();
+
+       while (value.is_string())
+       {
+               captures.resize(captures.size() + 1);
+               value.get(captures.back());
+               ++value.index;
+       }
+
+       script.clear_stack();
+       return 0 < captures.size();
+}
+
+int pattern::sub(std::string& substitution,
+               const std::string& pattern,
+               const std::string& source, const std::string& replacement)
+{
+       script& script = pattern_script();
+       script::slot value = script.globals().push_field("gsub");
+       script.push(source);
+       script.push(pattern);
+       script.push(replacement);
+       script.call(3, 2);
+
+       value.get(substitution);
+
+       ++value.index;
+       int count = 0;
+       value.get(count);
+
+       script.clear_stack();
+       return count;
 }
 
 
This page took 0.026656 seconds and 4 git commands to generate.