00001
00002
00003
00004
00005
00006
00007 #include "vsl_block_binary.h"
00008 #include <vcl_cstddef.h>
00009 #include <vcl_new.h>
00010 #include <vcl_algorithm.h>
00011 #include <vcl_cstdlib.h>
00012 #include <vcl_cassert.h>
00013
00014 struct vsl_block_t
00015 {
00016 char * ptr;
00017 vcl_size_t size;
00018 };
00019
00020 vsl_block_t allocate_up_to(vcl_size_t nbytes)
00021 {
00022 vsl_block_t block = {0, nbytes};
00023 while (true)
00024 {
00025 #if VCL_HAS_EXCEPTIONS
00026 try
00027 {
00028 block.ptr = new char[block.size];
00029 }
00030 catch (const vcl_bad_alloc& )
00031 {
00032 }
00033 #else
00034
00035 block.ptr = (char *)vcl_malloc(block.size);
00036 #endif
00037 if (block.ptr)
00038 return block;
00039 block.size /= 2;
00040 }
00041 }
00042
00043
00044
00045 void vsl_block_binary_read_confirm_specialisation(vsl_b_istream &is, bool specialised)
00046 {
00047 if (!is) return;
00048 bool b;
00049 vsl_b_read(is, b);
00050 if (b != specialised)
00051 {
00052 vcl_cerr << "I/O ERROR: vsl_block_binary_read()\n";
00053 if (specialised)
00054 vcl_cerr << " Data was saved using unspecialised slow form and is being loaded\n"
00055 << " using specialised fast form.\n\n";
00056 else
00057 vcl_cerr << " Data was saved using specialised fast form and is being loaded\n"
00058 << " using unspecialised slow form.\n\n";
00059
00060 is.is().clear(vcl_ios::badbit);
00061 }
00062 }
00063
00064
00065
00066
00067
00068 template <class T>
00069 void vsl_block_binary_write_float_impl(vsl_b_ostream &os, const T* begin, vcl_size_t nelems)
00070 {
00071 vsl_b_write(os, true);
00072
00073 const vcl_size_t wanted = sizeof(T) * nelems;
00074 vsl_block_t block = allocate_up_to(wanted);
00075
00076
00077 const vcl_size_t items_per_block = block.size / sizeof(T);
00078
00079
00080 while (nelems > 0)
00081 {
00082 vcl_size_t items = vcl_min(items_per_block, nelems);
00083 vcl_size_t bytes = sizeof(T) * items;
00084 vsl_swap_bytes_to_buffer((const char *)begin, (char *)block.ptr, sizeof(T), items);
00085 os.os().write( block.ptr, bytes);
00086 begin += items;
00087 nelems -= items;
00088 }
00089 #if VCL_HAS_EXCEPTIONS
00090 delete [] block.ptr;
00091 #else
00092 vcl_free(block.ptr);
00093 #endif
00094 }
00095
00096
00097 template <class T>
00098 void vsl_block_binary_read_float_impl(vsl_b_istream &is, T* begin, vcl_size_t nelems)
00099 {
00100
00101
00102 vsl_block_binary_read_confirm_specialisation(is, true);
00103 if (!is) return;
00104 is.is().read((char*) begin, nelems*sizeof(T));
00105 vsl_swap_bytes((char *)begin, sizeof(T), nelems);
00106 }
00107
00108
00109
00110 template <class T>
00111 void vsl_block_binary_write_int_impl(vsl_b_ostream &os, const T* begin, vcl_size_t nelems)
00112 {
00113
00114 vsl_b_write(os, true);
00115
00116 const vcl_size_t wanted = VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(T)) * nelems;
00117 vsl_block_t block = allocate_up_to(wanted );
00118
00119 if (block.size == wanted)
00120 {
00121
00122 vcl_size_t nbytes = vsl_convert_to_arbitrary_length(begin,
00123 (unsigned char *)block.ptr, nelems);
00124 vsl_b_write(os, nbytes);
00125 os.os().write( block.ptr, nbytes);
00126 }
00127 else
00128 {
00129
00130 const vcl_size_t items_per_block = block.size / VSL_MAX_ARBITRARY_INT_BUFFER_LENGTH(sizeof(T));
00131 vcl_size_t n=nelems;
00132 const T* p=begin;
00133 assert (n > items_per_block);
00134
00135 vcl_size_t n_bytes=0;
00136 while (n > 0)
00137 {
00138 vcl_size_t items = vcl_min(items_per_block, n);
00139 n_bytes += vsl_convert_to_arbitrary_length(p,
00140 (unsigned char *)block.ptr, items);
00141 p += items;
00142 n -= items;
00143 }
00144
00145 vsl_b_write(os, n_bytes);
00146 n=nelems;
00147 p=begin;
00148
00149
00150 while (n > 0)
00151 {
00152 vcl_size_t items = vcl_min(items_per_block, n);
00153 vcl_size_t bytes = vsl_convert_to_arbitrary_length(p,
00154 (unsigned char *)block.ptr, items );
00155 os.os().write( block.ptr, bytes);
00156 p += items;
00157 n -= items;
00158 }
00159 }
00160 #if VCL_HAS_EXCEPTIONS
00161 delete [] block.ptr;
00162 #else
00163 vcl_free(block.ptr);
00164 #endif
00165 }
00166
00167
00168
00169
00170 template <class T>
00171 void vsl_block_binary_read_int_impl(vsl_b_istream &is, T* begin, vcl_size_t nelems)
00172 {
00173 vsl_block_binary_read_confirm_specialisation(is, true);
00174 if (!is) return;
00175 vcl_size_t nbytes;
00176 vsl_b_read(is, nbytes);
00177 if (nbytes==0) return;
00178
00179
00180 vsl_block_t block = allocate_up_to(nbytes);
00181
00182 vcl_size_t n_bytes_converted = 0;
00183 if (block.size == nbytes)
00184 {
00185
00186 is.is().read(block.ptr, block.size);
00187 n_bytes_converted =
00188 vsl_convert_from_arbitrary_length((unsigned char *)block.ptr, begin, nelems);
00189 }
00190 else
00191 {
00192 vcl_size_t offset=0;
00193 vcl_size_t bytes_left = nbytes;
00194 vcl_size_t bytes_read = 0;
00195 while (nelems > 0)
00196 {
00197 assert (offset < block.size);
00198
00199
00200 vcl_size_t bytes = vcl_min((vcl_size_t)nbytes-bytes_read, block.size-offset);
00201 is.is().read(block.ptr+offset, bytes);
00202 bytes_read += bytes;
00203
00204 if (!is) break;
00205
00206
00207 vcl_size_t elems=0;
00208 for (unsigned char *p = (unsigned char *)block.ptr, *p_end=p+bytes+offset; p!=p_end; ++p)
00209 elems += *p >> 7;
00210
00211 if (elems > nelems)
00212 {
00213 vcl_cerr << "\nI/O ERROR: vsl_block_binary_read(.., int*,..)"
00214 << " Corrupted data stream\n";
00215 is.is().clear(vcl_ios::badbit);
00216 break;
00217 }
00218
00219
00220 vcl_size_t bytes_converted =
00221 vsl_convert_from_arbitrary_length((unsigned char *)block.ptr, begin, elems);
00222 nelems -= elems;
00223 begin += elems;
00224
00225 offset = (bytes + offset) - bytes_converted;
00226 n_bytes_converted += bytes_converted;
00227 bytes_left -= bytes_converted;
00228
00229
00230 vcl_memcpy(block.ptr, block.ptr + bytes_converted, offset);
00231 }
00232 if (bytes_left != 0 || nelems != 0 || bytes_read != nbytes)
00233 {
00234 vcl_cerr << "\nI/O ERROR: vsl_block_binary_read(.., int*,..)"
00235 << " Corrupted data stream\n";
00236 is.is().clear(vcl_ios::badbit);
00237 }
00238 }
00239 if (n_bytes_converted != nbytes)
00240 {
00241 vcl_cerr << "\nI/O ERROR: vsl_block_binary_read(.., int*,..)"
00242 << " Corrupted data stream\n";
00243 is.is().clear(vcl_ios::badbit);
00244 }
00245 #if VCL_HAS_EXCEPTIONS
00246 delete [] block.ptr;
00247 #else
00248 vcl_free(block.ptr);
00249 #endif
00250 }
00251
00252
00253
00254
00255 template <class T>
00256 void vsl_block_binary_write_byte_impl(vsl_b_ostream &os, const T* begin, vcl_size_t nelems)
00257 {
00258 vsl_b_write(os, true);
00259 os.os().write((char*) begin, nelems);
00260 }
00261
00262
00263 template <class T>
00264 void vsl_block_binary_read_byte_impl(vsl_b_istream &is, T* begin, vcl_size_t nelems)
00265 {
00266
00267
00268 vsl_block_binary_read_confirm_specialisation(is, true);
00269 if (!is) return;
00270 is.is().read((char*) begin, nelems);
00271 }
00272
00273
00274
00275
00276 template void vsl_block_binary_write_float_impl(vsl_b_ostream &, const double*, vcl_size_t);
00277 template void vsl_block_binary_write_float_impl(vsl_b_ostream &, const float*, vcl_size_t);
00278
00279 template void vsl_block_binary_read_float_impl(vsl_b_istream &, double*, vcl_size_t);
00280 template void vsl_block_binary_read_float_impl(vsl_b_istream &, float*, vcl_size_t);
00281
00282 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const long*, vcl_size_t);
00283 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const unsigned long*, vcl_size_t);
00284 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const int*, vcl_size_t);
00285 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const unsigned int*, vcl_size_t);
00286 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const short*, vcl_size_t);
00287 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const unsigned short*, vcl_size_t);
00288
00289 template void vsl_block_binary_read_int_impl(vsl_b_istream &, long*, vcl_size_t);
00290 template void vsl_block_binary_read_int_impl(vsl_b_istream &, unsigned long*, vcl_size_t);
00291 template void vsl_block_binary_read_int_impl(vsl_b_istream &, int*, vcl_size_t);
00292 template void vsl_block_binary_read_int_impl(vsl_b_istream &, unsigned int*, vcl_size_t);
00293 template void vsl_block_binary_read_int_impl(vsl_b_istream &, short*, vcl_size_t);
00294 template void vsl_block_binary_read_int_impl(vsl_b_istream &, unsigned short*, vcl_size_t);
00295
00296 template void vsl_block_binary_write_byte_impl(vsl_b_ostream &, const signed char*, vcl_size_t);
00297 template void vsl_block_binary_write_byte_impl(vsl_b_ostream &, const unsigned char*, vcl_size_t);
00298
00299 template void vsl_block_binary_read_byte_impl(vsl_b_istream &, signed char*, vcl_size_t);
00300 template void vsl_block_binary_read_byte_impl(vsl_b_istream &, unsigned char*, vcl_size_t);
00301
00302 #if VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG
00303 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const vxl_int_64*, vcl_size_t);
00304 template void vsl_block_binary_write_int_impl(vsl_b_ostream &, const vxl_uint_64*, vcl_size_t);
00305 template void vsl_block_binary_read_int_impl(vsl_b_istream &, vxl_int_64*, vcl_size_t);
00306 template void vsl_block_binary_read_int_impl(vsl_b_istream &, vxl_uint_64*, vcl_size_t);
00307 #endif //VXL_HAS_INT_64 && !VXL_INT_64_IS_LONG