1// This file is part of the ustl library, an STL implementation.
2//
3// Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4// This file is free software, distributed under the MIT License.
5//
6// cmemlink.cc
7//
8// See cmemlink.h for documentation.
9//
10
11#include "cmemlink.h"
12#include "ofstream.h"
13#include "strmsize.h"
14#include "ualgo.h"
15#include "uassert.h"
16
17#if PLATFORM_ANDROID
18#include <stdio.h>
19#undef CPU_HAS_MMX
20#endif
21
22namespace ustl {
23
24/// \brief Attaches the object to pointer \p p of size \p n.
25///
26/// If \p p is NULL and \p n is non-zero, bad_alloc is thrown and current
27/// state remains unchanged.
28///
29void cmemlink::link (const void* p, size_type n)
30{
31    if (!p && n)
32#if PLATFORM_ANDROID
33       printf("bad alloc\n");
34#else /* !PLATFORM_ANDROID */
35	throw bad_alloc (n);
36#endif
37    unlink();
38    relink (p, n);
39}
40
41/// Writes the object to stream \p os
42void cmemlink::write (ostream& os) const
43{
44    const written_size_type sz (size());
45    assert (sz == size() && "No support for writing memblocks larger than 4G");
46    os << sz;
47    os.write (cdata(), sz);
48    os.align (alignof (sz));
49}
50
51/// Writes the object to stream \p os
52void cmemlink::text_write (ostringstream& os) const
53{
54    os.write (begin(), readable_size());
55}
56
57/// Returns the number of bytes required to write this object to a stream.
58cmemlink::size_type cmemlink::stream_size (void) const
59{
60    const written_size_type sz (size());
61    return (Align (stream_size_of (sz) + sz, alignof(sz)));
62}
63
64/// Writes the data to file \p "filename".
65void cmemlink::write_file (const char* filename, int mode) const
66{
67    fstream f;
68    f.exceptions (fstream::allbadbits);
69    f.open (filename, fstream::out | fstream::trunc, mode);
70    f.write (cdata(), readable_size());
71    f.close();
72}
73
74/// swaps the contents with \p l
75void cmemlink::swap (cmemlink& l)
76{
77#if CPU_HAS_MMX && SIZE_OF_POINTER == 4
78    asm (
79	"movq %0, %%mm0\n\t"
80	"movq %2, %%mm1\n\t"
81	"movq %%mm0, %2\n\t"
82	"movq %%mm1, %0"
83	: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
84	:
85	: "mm0", "mm1", "st", "st(1)");
86    simd::reset_mmx();
87#elif CPU_HAS_SSE && SIZE_OF_POINTER == 8
88    asm (
89	"movups %0, %%xmm0\n\t"
90	"movups %2, %%xmm1\n\t"
91	"movups %%xmm0, %2\n\t"
92	"movups %%xmm1, %0"
93	: "=m"(m_Data), "=m"(m_Size), "=m"(l.m_Data), "=m"(l.m_Size)
94	:
95	: "xmm0", "xmm1");
96#else
97    ::ustl::swap (m_Data, l.m_Data);
98    ::ustl::swap (m_Size, l.m_Size);
99#endif
100}
101
102/// Compares to memory block pointed by l. Size is compared first.
103bool cmemlink::operator== (const cmemlink& l) const
104{
105    return (l.m_Size == m_Size &&
106	    (l.m_Data == m_Data || 0 == memcmp (l.m_Data, m_Data, m_Size)));
107}
108
109} // namespace ustl
110
111