aboutsummaryrefslogtreecommitdiffhomepage
path: root/common.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-02-22 16:22:56 -0800
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-02-22 16:22:56 -0800
commita8e92639af37ff1e289eb0c3db9589740a630f4a (patch)
tree5ae5938c9a63c675a0b566ebc9c290af3efb6e25 /common.cpp
parentd99c2cb9a7ec4b2292616ccbd851eed10fd4328b (diff)
Cleanup and simplify null_terminated_array_t and its clients
Diffstat (limited to 'common.cpp')
-rw-r--r--common.cpp75
1 files changed, 72 insertions, 3 deletions
diff --git a/common.cpp b/common.cpp
index 91646b8d..c2068b5c 100644
--- a/common.cpp
+++ b/common.cpp
@@ -1978,18 +1978,21 @@ void exit_without_destructors(int code)
}
/* Helper function to convert from a null_terminated_array_t<wchar_t> to a null_terminated_array_t<char_t> */
-null_terminated_array_t<char> convert_wide_array_to_narrow(const null_terminated_array_t<wchar_t> &wide_arr)
+void convert_wide_array_to_narrow(const null_terminated_array_t<wchar_t> &wide_arr, null_terminated_array_t<char> *output)
{
const wchar_t *const *arr = wide_arr.get();
if (! arr)
- return null_terminated_array_t<char>();
+ {
+ output->clear();
+ return;
+ }
std::vector<std::string> list;
for (size_t i=0; arr[i]; i++)
{
list.push_back(wcs2string(arr[i]));
}
- return null_terminated_array_t<char>(list);
+ output->set(list);
}
void append_path_component(wcstring &path, const wcstring &component)
@@ -2167,3 +2170,69 @@ wcstokenizer::~wcstokenizer()
{
free(buffer);
}
+
+
+template <typename CharType_t>
+static CharType_t **make_null_terminated_array_helper(const std::vector<std::basic_string<CharType_t> > &argv)
+{
+ size_t count = argv.size();
+
+ /* We allocate everything in one giant block. First compute how much space we need. */
+
+ /* N + 1 pointers */
+ size_t pointers_allocation_len = (count + 1) * sizeof(CharType_t *);
+
+ /* In the very unlikely event that CharType_t has stricter alignment requirements than does a pointer, round us up to the size of a CharType_t */
+ pointers_allocation_len += sizeof(CharType_t) - 1;
+ pointers_allocation_len -= pointers_allocation_len % sizeof(CharType_t);
+
+ /* N null terminated strings */
+ size_t strings_allocation_len = 0;
+ for (size_t i=0; i < count; i++)
+ {
+ /* The size of the string, plus a null terminator */
+ strings_allocation_len += (argv.at(i).size() + 1) * sizeof(CharType_t);
+ }
+
+ /* Now allocate their sum */
+ unsigned char *base = static_cast<unsigned char *>(malloc(pointers_allocation_len + strings_allocation_len));
+ if (! base) return NULL;
+
+ /* Divvy it up into the pointers and strings */
+ CharType_t **pointers = reinterpret_cast<CharType_t **>(base);
+ CharType_t *strings = reinterpret_cast<CharType_t *>(base + pointers_allocation_len);
+
+ /* Start copying */
+ for (size_t i=0; i < count; i++)
+ {
+ const std::basic_string<CharType_t> &str = argv.at(i);
+ // store the current string pointer into self
+ *pointers++ = strings;
+
+ // copy the string into strings
+ strings = std::copy(str.begin(), str.end(), strings);
+ // each string needs a null terminator
+ *strings++ = (CharType_t)(0);
+ }
+ // array of pointers needs a null terminator
+ *pointers++ = NULL;
+
+ // Make sure we know what we're doing
+ assert((unsigned char *)pointers - base == (ptrdiff_t)pointers_allocation_len);
+ assert((unsigned char *)strings - (unsigned char *)pointers == (ptrdiff_t)strings_allocation_len);
+ assert((unsigned char *)strings - base == (ptrdiff_t)(pointers_allocation_len + strings_allocation_len));
+
+ // Return what we did
+ return reinterpret_cast<CharType_t**>(base);
+}
+
+wchar_t **make_null_terminated_array(const wcstring_list_t &lst)
+{
+ return make_null_terminated_array_helper(lst);
+}
+
+char **make_null_terminated_array(const std::vector<std::string> &lst)
+{
+ return make_null_terminated_array_helper(lst);
+}
+