1 // This file is part of the ustl library, an STL implementation. 2 // 3 // Copyright (C) 2005 by Mike Sharov <msharov (at) 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 22 namespace 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 /// 29 void 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 42 void 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 52 void 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. 58 cmemlink::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". 65 void 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 75 void 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. 103 bool 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