00001 #include "containers.hh"
00002 #include <typelib/registry.hh>
00003 #include <typelib/typemodel.hh>
00004 #include <typelib/value_ops.hh>
00005 #include <typelib/value_ops_details.hh>
00006 #include <boost/tuple/tuple.hpp>
00007 #include <string.h>
00008 #include <limits>
00009
00010 #include <iostream>
00011
00012 using namespace Typelib;
00013 using namespace std;
00014
00015 BOOST_STATIC_ASSERT(( sizeof(vector<void*>) == sizeof(vector<Container>) ));
00016
00017 string Vector::fullName(std::string const& element_name)
00018 { return "/std/vector<" + element_name + ">"; }
00019
00020 Vector::Vector(Type const& on)
00021 : Container("/std/vector", fullName(on.getName()), getNaturalSize(), on)
00022 , is_memcpy(false)
00023 {
00024 try {
00025 MemoryLayout ops = Typelib::layout_of(on);
00026 is_memcpy = (ops.size() == 2 && ops[0] == MemLayout::FLAG_MEMCPY);
00027 }
00028 catch(std::runtime_error)
00029 {
00030
00031 is_memcpy = false;
00032 }
00033 }
00034
00035 size_t Vector::getElementCount(void const* ptr) const
00036 {
00037 size_t byte_count = reinterpret_cast< std::vector<int8_t> const* >(ptr)->size();
00038 return byte_count / getIndirection().getSize();
00039 }
00040 void Vector::init(void* ptr) const
00041 {
00042 new(ptr) vector<int8_t>();
00043 }
00044 void Vector::destroy(void* ptr) const
00045 {
00046 std::vector<uint8_t>* vector_ptr =
00047 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00048 resize(vector_ptr, 0);
00049 vector_ptr->~vector<uint8_t>();
00050 }
00051 void Vector::clear(void* ptr) const
00052 {
00053 std::vector<uint8_t>* vector_ptr =
00054 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00055 resize(vector_ptr, 0);
00056 }
00057
00058 bool Vector::isRandomAccess() const
00059 { return true; }
00060 void Vector::setElement(void* ptr, int idx, Typelib::Value value) const
00061 {
00062 std::vector<uint8_t>* vector_ptr =
00063 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00064 Typelib::copy(
00065 Value(&(*vector_ptr)[idx * getIndirection().getSize()], getIndirection()),
00066 value);
00067 }
00068
00069 Typelib::Value Vector::getElement(void* ptr, int idx) const
00070 {
00071 std::vector<uint8_t>* vector_ptr =
00072 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00073 return Value(&(*vector_ptr)[idx * getIndirection().getSize()], getIndirection());
00074 }
00075
00076 long Vector::getNaturalSize() const
00077 {
00078 return sizeof(std::vector<void*>);
00079 }
00080
00081 void Vector::resize(std::vector<uint8_t>* ptr, size_t new_size) const
00082 {
00083 Type const& element_t = getIndirection();
00084 size_t element_size = getIndirection().getSize();
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 size_t old_raw_size = ptr->size();
00099 size_t old_size = getElementCount(ptr);
00100 size_t new_raw_size = new_size * element_size;
00101
00102 if (!is_memcpy && old_size > new_size)
00103 {
00104
00105 for (size_t i = new_raw_size; i < old_raw_size; i += element_size)
00106 Typelib::destroy(Value(&(*ptr)[i], element_t));
00107 }
00108
00109 ptr->resize(new_raw_size);
00110
00111 if (!is_memcpy && old_size < new_size)
00112 {
00113
00114 for (size_t i = old_raw_size; i < new_raw_size; i += element_size)
00115 Typelib::init(Value(&(*ptr)[i], element_t));
00116 }
00117 }
00118
00119 void Vector::push(void* ptr, Value v) const
00120 {
00121 if (v.getType() != getIndirection())
00122 throw std::runtime_error("type mismatch in vector insertion");
00123
00124 std::vector<uint8_t>* vector_ptr =
00125 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00126
00127 size_t size = getElementCount(ptr);
00128 resize(vector_ptr, size + 1);
00129 Typelib::copy(
00130 Value(&(*vector_ptr)[size * getIndirection().getSize()], getIndirection()),
00131 v);
00132 }
00133
00134 bool Vector::erase(void* ptr, Value v) const
00135 {
00136 if (v.getType() != getIndirection())
00137 throw std::runtime_error("type mismatch in vector insertion");
00138
00139 std::vector<uint8_t>* vector_ptr =
00140 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00141 Type const& element_t = getIndirection();
00142 size_t element_size = element_t.getSize();
00143 size_t element_count = getElementCount(vector_ptr);
00144
00145 uint8_t* base_ptr = &(*vector_ptr)[0];
00146
00147 for (size_t i = 0; i < element_count; ++i)
00148 {
00149 uint8_t* element_ptr = base_ptr + i * element_size;
00150 Value element_v(element_ptr, element_t);
00151 if (Typelib::compare(element_v, v))
00152 {
00153 erase(vector_ptr, i);
00154 return true;
00155 }
00156 }
00157 return false;
00158 }
00159
00160 void Vector::erase(std::vector<uint8_t>* ptr, size_t idx) const
00161 {
00162
00163 size_t element_count = getElementCount(ptr);
00164 if (element_count > idx + 1)
00165 copy(ptr, idx, ptr, idx + 1, element_count - idx - 1);
00166
00167
00168 resize(ptr, element_count - 1);
00169 }
00170
00171 bool Vector::compare(void* ptr, void* other) const
00172 {
00173 std::vector<uint8_t>* a_ptr =
00174 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00175 std::vector<uint8_t>* b_ptr =
00176 reinterpret_cast< std::vector<uint8_t>* >(other);
00177
00178 size_t element_count = getElementCount(a_ptr);
00179 Type const& element_t = getIndirection();
00180 size_t element_size = element_t.getSize();
00181 if (element_count != getElementCount(b_ptr))
00182 return false;
00183
00184 uint8_t* base_a = &(*a_ptr)[0];
00185 uint8_t* base_b = &(*b_ptr)[0];
00186 for (size_t i = 0; i < element_count; ++i)
00187 {
00188 if (!Typelib::compare(
00189 Value(base_a + i * element_size, element_t),
00190 Value(base_b + i * element_size, element_t)))
00191 return false;
00192 }
00193 return true;
00194 }
00195
00196 void Vector::copy(void* dst, void* src) const
00197 {
00198 std::vector<uint8_t>* dst_ptr =
00199 reinterpret_cast< std::vector<uint8_t>* >(dst);
00200 std::vector<uint8_t>* src_ptr =
00201 reinterpret_cast< std::vector<uint8_t>* >(src);
00202
00203 size_t element_count = getElementCount(src_ptr);
00204 resize(dst_ptr, element_count);
00205 copy(dst_ptr, 0, src_ptr, 0, element_count);
00206 }
00207
00208 void Vector::copy(std::vector<uint8_t>* dst_ptr, size_t dst_idx, std::vector<uint8_t>* src_ptr, size_t src_idx, size_t count) const
00209 {
00210 Type const& element_t = getIndirection();
00211 size_t element_size = element_t.getSize();
00212 uint8_t* base_src = &(*src_ptr)[src_idx * element_size];
00213 uint8_t* base_dst = &(*dst_ptr)[dst_idx * element_size];
00214 if (is_memcpy)
00215 {
00216 if (dst_ptr == src_ptr)
00217 memmove(base_dst, base_src, element_size * count);
00218 else
00219 memcpy(base_dst, base_src, element_size * count);
00220 }
00221 else
00222 {
00223 for (size_t i = 0; i < count; ++i)
00224 {
00225 Typelib::copy(
00226 Value(base_dst + i * element_size, element_t),
00227 Value(base_src + i * element_size, element_t));
00228 }
00229 }
00230 }
00231
00232
00233 bool Vector::visit(void* ptr, ValueVisitor& visitor) const
00234 {
00235 std::vector<uint8_t>* vector_ptr =
00236 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00237 uint8_t* base = &(*vector_ptr)[0];
00238 size_t element_size = getIndirection().getSize();
00239 size_t element_count = getElementCount(vector_ptr);
00240
00241 for (size_t i = 0; i < element_count; ++i)
00242 visitor.dispatch(Value(base + i * element_size, getIndirection()));
00243
00244 return true;
00245 }
00246
00247 void Vector::delete_if_impl(void* ptr, DeleteIfPredicate& pred) const
00248 {
00249 std::vector<uint8_t>* vector_ptr =
00250 reinterpret_cast< std::vector<uint8_t>* >(ptr);
00251
00252 size_t element_count = getElementCount(vector_ptr);
00253 Type const& element_t = getIndirection();
00254 size_t element_size = element_t.getSize();
00255
00256 uint8_t* base = &(*vector_ptr)[0];
00257 for (size_t i = 0; i < element_count; )
00258 {
00259 uint8_t* element_ptr = base + i * element_size;
00260 Value element_v(element_ptr, element_t);
00261 if (pred.should_delete(element_v))
00262 {
00263 erase(vector_ptr, i);
00264 element_count--;
00265 }
00266 else
00267 ++i;
00268 }
00269 }
00270
00271 Container::MarshalOps::const_iterator Vector::dump(
00272 void const* container_ptr, size_t element_count, ValueOps::OutputStream& stream,
00273 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const
00274 {
00275 std::vector<uint8_t> const* vector_ptr =
00276 reinterpret_cast< std::vector<uint8_t> const* >(container_ptr);
00277
00278 MarshalOps::const_iterator it = begin;
00279 if (is_memcpy)
00280 {
00281
00282 size_t size = *(++it) * element_count;
00283 stream.write(&(*vector_ptr)[0], size);
00284 return begin + 2;
00285 }
00286 else
00287 {
00288 MarshalOps::const_iterator it_end = begin;
00289 size_t in_offset = 0;
00290 for (size_t i = 0; i < element_count; ++i)
00291 {
00292 boost::tie(in_offset, it_end) = ValueOps::dump(
00293 &(*vector_ptr)[i * getIndirection().getSize()], 0,
00294 stream, begin, end);
00295 }
00296 return it_end;
00297 }
00298 }
00299
00300 Container::MarshalOps::const_iterator Vector::load(
00301 void* container_ptr, size_t element_count,
00302 ValueOps::InputStream& stream,
00303 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const
00304 {
00305 std::vector<uint8_t>* vector_ptr =
00306 reinterpret_cast< std::vector<uint8_t>* >(container_ptr);
00307
00308 Type const& element_t = getIndirection();
00309 size_t element_size = element_t.getSize();
00310 resize(vector_ptr, element_count);
00311
00312 MarshalOps::const_iterator it = begin;
00313 if (is_memcpy)
00314 {
00315 size_t size = *(++it) * element_count;
00316 stream.read(&(*vector_ptr)[0], size);
00317 return begin + 2;
00318 }
00319 else
00320 {
00321 MarshalOps::const_iterator it_end;
00322 size_t out_offset = 0;
00323 for (size_t i = 0; i < element_count; ++i)
00324 {
00325 boost::tie(out_offset, it_end) =
00326 ValueOps::load(&(*vector_ptr)[i * element_size], 0,
00327 stream, begin, end);
00328 }
00329 return it_end;
00330 }
00331 }
00332
00333 std::string Vector::getIndirectTypeName(std::string const& element_name) const
00334 {
00335 return Vector::fullName(element_name);
00336 }
00337
00338 Container const& Vector::factory(Registry& registry, std::list<Type const*> const& on)
00339 {
00340 if (on.size() != 1)
00341 throw std::runtime_error("expected only one template argument for std::vector");
00342
00343 Type const& contained_type = *on.front();
00344 std::string full_name = Vector::fullName(contained_type.getName());
00345 if (! registry.has(full_name))
00346 {
00347 Vector* new_type = new Vector(contained_type);
00348 registry.add(new_type);
00349 return *new_type;
00350 }
00351 else
00352 return dynamic_cast<Container const&>(*registry.get(full_name));
00353 }
00354 Container::ContainerFactory Vector::getFactory() const { return factory; }
00355
00356
00357 Type const& String::getElementType(Typelib::Registry const& registry)
00358 {
00359 if (std::numeric_limits<char>::is_signed)
00360 return *registry.get("/int8_t");
00361 else
00362 return *registry.get("/uint8_t");
00363 }
00364 String::String(Typelib::Registry const& registry)
00365 : Container("/std/string", "/std/string", getNaturalSize(), String::getElementType(registry)) {}
00366
00367 size_t String::getElementCount(void const* ptr) const
00368 {
00369 size_t byte_count = reinterpret_cast< std::string const* >(ptr)->length();
00370 return byte_count / getIndirection().getSize();
00371 }
00372 void String::init(void* ptr) const
00373 {
00374 new(ptr) std::string();
00375 }
00376 void String::destroy(void* ptr) const
00377 {
00378 reinterpret_cast< std::string* >(ptr)->~string();
00379 }
00380 void String::clear(void* ptr) const
00381 {
00382 reinterpret_cast< std::string* >(ptr)->clear();
00383 }
00384
00385
00386 long String::getNaturalSize() const
00387 {
00388 return sizeof(std::string);
00389 }
00390
00391 void String::push(void* ptr, Value v) const
00392 {
00393 if (v.getType() != getIndirection())
00394 throw std::runtime_error("type mismatch in string insertion");
00395
00396 std::string* string_ptr =
00397 reinterpret_cast< std::string* >(ptr);
00398
00399 string_ptr->append(reinterpret_cast<std::string::value_type*>(v.getData()), 1);
00400 }
00401
00402 bool String::erase(void* ptr, Value v) const
00403 {
00404 return false;
00405 }
00406
00407 bool String::compare(void* ptr, void* other) const
00408 {
00409 std::string* a_ptr = reinterpret_cast< std::string* >(ptr);
00410 std::string* b_ptr = reinterpret_cast< std::string* >(other);
00411 return *a_ptr == *b_ptr;
00412 }
00413
00414 void String::copy(void* dst, void* src) const
00415 {
00416 std::string* dst_ptr = reinterpret_cast< std::string* >(dst);
00417 std::string* src_ptr = reinterpret_cast< std::string* >(src);
00418 *dst_ptr = *src_ptr;
00419 }
00420
00421 bool String::visit(void* ptr, ValueVisitor& visitor) const
00422 {
00423 std::string* string_ptr =
00424 reinterpret_cast< std::string* >(ptr);
00425 char* base = const_cast<char*>(string_ptr->c_str());
00426 size_t element_count = string_ptr->length();
00427
00428 for (size_t i = 0; i < element_count; ++i)
00429 visitor.dispatch(Value(base + i, getIndirection()));
00430
00431 return true;
00432 }
00433
00434 Container::MarshalOps::const_iterator String::dump(
00435 void const* container_ptr, size_t element_count, ValueOps::OutputStream& stream,
00436 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const
00437 {
00438 const std::string* string_ptr =
00439 reinterpret_cast< const std::string* >(container_ptr);
00440
00441 stream.write(reinterpret_cast<uint8_t const*>(string_ptr->c_str()), element_count);
00442 return begin + 2;
00443 }
00444
00445 Container::MarshalOps::const_iterator String::load(
00446 void* container_ptr, size_t element_count,
00447 ValueOps::InputStream& stream,
00448 MarshalOps::const_iterator const begin, MarshalOps::const_iterator const end) const
00449 {
00450 std::string* string_ptr =
00451 reinterpret_cast< std::string* >(container_ptr);
00452
00453 std::vector<uint8_t> buffer;
00454 buffer.resize(element_count);
00455 stream.read(&buffer[0], element_count);
00456 (*string_ptr).append(reinterpret_cast<const char*>(&buffer[0]), element_count);
00457 return begin + 2;
00458 }
00459 void String::delete_if_impl(void* ptr, DeleteIfPredicate& pred) const
00460 {}
00461
00462 Container const& String::factory(Registry& registry, std::list<Type const*> const& on)
00463 {
00464 if (registry.has("/std/string"))
00465 return dynamic_cast<Container const&>(*registry.get("/std/string"));
00466
00467 if (on.size() != 1)
00468 throw std::runtime_error("expected only one template argument for std::string");
00469
00470 Type const& contained_type = *on.front();
00471 Type const& expected_type = String::getElementType(registry);
00472 if (contained_type != expected_type)
00473 throw std::runtime_error("std::string can only be built on top of '" + expected_type.getName() + "' -- found " + contained_type.getName());
00474
00475 String* new_type = new String(registry);
00476 registry.add(new_type);
00477 return *new_type;
00478 }
00479 Container::ContainerFactory String::getFactory() const { return factory; }
00480