blob: 7250e9f3edd93918773cdec8716f6a01ee09a764 [file] [log] [blame]
// This file is part of the ustl library, an STL implementation.
//
// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the MIT License.
//
// cmemlink.cc
//
// See cmemlink.h for documentation.
//
#include "cmemlink.h"
#include "ofstream.h"
#include "strmsize.h"
#include "ualgo.h"
#include "uassert.h"
#if PLATFORM_ANDROID
#include <stdio.h>
#undef CPU_HAS_MMX
#endif
namespace ustl {
/// \brief Attaches the object to pointer \p p of size \p n.
///
/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current
/// state remains unchanged.
///
void cmemlink::link (const void* p, size_type n)
{
if (!p && n)
#if PLATFORM_ANDROID
printf("bad alloc\n");
#else /* !PLATFORM_ANDROID */
throw bad_alloc (n);
#endif
unlink();
relink (p, n);
}
/// Writes the object to stream \p os
void cmemlink::write (ostream& os) const
{
const written_size_type sz (size());
assert (sz == size() && "No support for writing memblocks larger than 4G");
os << sz;
os.write (cdata(), sz);
os.align (alignof (sz));
}
/// Writes the object to stream \p os
void cmemlink::text_write (ostringstream& os) const
{
os.write (begin(), readable_size());
}
/// Returns the number of bytes required to write this object to a stream.
cmemlink::size_type cmemlink::stream_size (void) const
{
const written_size_type sz (size());
return (Align (stream_size_of (sz) + sz, alignof(sz)));
}
/// Writes the data to file \p "filename".
void cmemlink::write_file (const char* filename, int mode) const
{
fstream f;
f.exceptions (fstream::allbadbits);
f.open (filename, fstream::out | fstream::trunc, mode);
f.write (cdata(), readable_size());
f.close();
}
/// swaps the contents with \p l
void cmemlink::swap (cmemlink& l)
{
#if CPU_HAS_MMX && SIZE_OF_POINTER == 4
asm (
"movq %0, %%mm0\n\t"
"movq %2, %%mm1\n\t"
"movq %%mm0, %2\n\t"
"movq %%mm1, %0"
: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
:
: "mm0", "mm1", "st", "st(1)");
simd::reset_mmx();
#elif CPU_HAS_SSE && SIZE_OF_POINTER == 8
asm (
"movups %0, %%xmm0\n\t"
"movups %2, %%xmm1\n\t"
"movups %%xmm0, %2\n\t"
"movups %%xmm1, %0"
: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
:
: "xmm0", "xmm1");
#else
::ustl::swap (m_Data, l.m_Data);
::ustl::swap (m_Size, l.m_Size);
#endif
}
/// Compares to memory block pointed by l. Size is compared first.
bool cmemlink::operator== (const cmemlink& l) const
{
return (l.m_Size == m_Size &&
(l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size)));
}
} // namespace ustl