├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── compile-bench ├── GenCompileBench │ ├── GenCompileBench.cpp │ ├── GenCompileBench.vcproj │ └── ReadMe.txt ├── Makefile └── src │ ├── CompileSpeedBoost │ ├── CompileSpeedBoost.cpp │ ├── CompileSpeedBoost.vcproj │ ├── Makefile │ ├── ReadMe.txt │ └── data_boost.h │ └── CompileSpeedNark │ ├── CompileSpeedNark.cpp │ ├── CompileSpeedNark.vcproj │ ├── Makefile │ ├── ReadMe.txt │ └── data_nark.h ├── doc ├── DataIO-representation.pptx └── DataIO.doc ├── gen_env_conf.sh ├── src └── nark │ └── io │ ├── BzipStream.cpp │ ├── BzipStream.hpp │ ├── DataIO.hpp │ ├── DataIO_Basic.hpp │ ├── DataIO_Dump.hpp │ ├── DataIO_Exception.cpp │ ├── DataIO_Exception.hpp │ ├── DataIO_SmartPtr.hpp │ ├── DataIO_Tuple.hpp │ ├── DataIO_Version.hpp │ ├── DataInput.hpp │ ├── DataInputIterator.hpp │ ├── DataInput_Basic.hpp │ ├── DataInput_BigEndian.hpp │ ├── DataInput_LittleEndian.hpp │ ├── DataInput_String.hpp │ ├── DataInput_VarIntAsFixLen.hpp │ ├── DataInput_VarIntAsVarLen.hpp │ ├── DataOutput.hpp │ ├── DataOutput_Basic.hpp │ ├── DataOutput_BigEndian.hpp │ ├── DataOutput_LittleEndian.hpp │ ├── DataOutput_String.hpp │ ├── DataOutput_VarIntAsFixLen.hpp │ ├── DataOutput_VarIntAsVarLen.hpp │ ├── FileDataIO.hpp │ ├── FileStream.cpp │ ├── FileStream.hpp │ ├── GzipStream.cpp │ ├── GzipStream.hpp │ ├── HexCodingStream.cpp │ ├── HexCodingStream.hpp │ ├── IOException.cpp │ ├── IOException.hpp │ ├── IStream.cpp │ ├── IStream.hpp │ ├── IStreamWrapper.hpp │ ├── MemMapStream.cpp │ ├── MemMapStream.hpp │ ├── MemStream.cpp │ ├── MemStream.hpp │ ├── RangeStream.hpp │ ├── StreamBuffer.cpp │ ├── StreamBuffer.hpp │ ├── ZcMemMap.cpp │ ├── ZcMemMap.hpp │ ├── ZeroCopy.cpp │ ├── ZeroCopy.hpp │ ├── avro.hpp │ ├── byte_io_impl.hpp │ ├── byte_swap.hpp │ ├── discard │ ├── ConcurrentStream.hpp │ ├── DataInput.cpp │ ├── DataOutputMeasure.hpp │ ├── custom_int.hpp │ ├── dump_allocator.hpp │ ├── hole_stream.hpp │ └── is_primitive.hpp │ ├── file_load_save.hpp │ ├── int_diff_coding.hpp │ ├── todo │ ├── DataIO_Parser.hpp │ ├── DataIO_Polymorphic.hpp │ ├── inter_thread_pipe.cpp │ └── inter_thread_pipe.hpp │ ├── var_int.cpp │ ├── var_int.hpp │ ├── var_int_boost_serialization.hpp │ ├── var_int_declare_read.hpp │ ├── var_int_declare_write.hpp │ ├── var_int_inline.hpp │ ├── var_int_io.hpp │ └── win │ ├── MfcFileStream.cpp │ ├── MfcFileStream.hpp │ ├── WinFileStream.cpp │ └── WinFileStream.hpp └── test ├── DataIO.sln ├── Makefile └── src ├── Bench ├── Bench.vcproj ├── ReadMe.txt ├── bench.cpp └── test_body.h ├── FastVarIntBench ├── FastVarIntBench.cpp └── FastVarIntBench.vcproj ├── IsDump ├── IsDump.cpp ├── IsDump.vcproj └── ReadMe.txt └── TestCorrection ├── ReadMe.txt ├── TestCorrection.cpp ├── TestCorrection.vcproj └── body.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nark-serialization 2 | ================== 3 | 4 | ## Now the newest version is in [topling-ark](https://github.com/topling/topling-ark) 5 | 6 | An easy, fast, small, portable C++ object serialization framework 7 | 8 | ## Features 9 | 1. Declarative syntax, Easy to use, Easy to integrate 10 | 1. *Fast* at runtime, *Fast* at compile time 11 | 1. Serialized data is *small*, Compiled code is *small* 12 | 1. Support STL containers & types 13 | 1. Can serialize to BigEndian/LittleEndian in any platform 14 | 1. Support variant int/uint encoding 15 | 1. Optional serialization version control 16 | 1. More and more... 17 | 18 | ## Bench Mark 19 | I have written a [benchmark vs boost-serialization](http://nark.cc/p/?p=65), but have not written benchmarks with other serilization libraries. 20 | Fortunately, there is a [benchmark of many serialization library](https://github.com/thekvs/cpp-serializers), including boost-serialization. 21 | 22 | You can run benchmark of [nark-serialization vs boost-serialization](#compile) yourself. 23 | 24 | ## Quick Start 25 | 26 | nark-serialization is powerful, but using it is very simple: 27 | 28 | ```c++ 29 | #include 30 | #include 31 | #include 32 | 33 | struct MyData1 { 34 | int a, b, c; 35 | var_int32_t d; // d.t is int32 value 36 | var_uint64_t e; // e.t is uint64 value 37 | std::string f; 38 | std::map g; 39 | std::set h; 40 | 41 | // The simplest use case(without version control): 42 | DATA_IO_LOAD_SAVE(MyData1, &a&b&c&d&e&f&g&h) 43 | }; 44 | 45 | struct MyData2 { 46 | int a, b, c; 47 | var_int32_t d; 48 | var_uint64_t e; 49 | std::string f; 50 | std::map g; 51 | std::set h; 52 | 53 | DATA_IO_LOAD_SAVE_V(MyData2, // With version control 54 | 1, // 1 is current version 55 | &a&b&c&d&e&f&g&h) 56 | }; 57 | 58 | struct MyData3 { 59 | int a, b, c; 60 | boost::int32_t d; 61 | boost::uint64_t e; 62 | std::string f; 63 | std::map g; 64 | std::set h; 65 | std::multiset i; 66 | unsigned version; 67 | 68 | DATA_IO_LOAD_SAVE_V(MyData3, // With version control 69 | 2, // current version 70 | &a &b &c 71 | &as_var_int(d) // 'd' defined as int32_t, serialized as var_int32_t 72 | &as_var_int(e) // 'e' defined as uint64_t, serialized as var_uint64_t 73 | &f &g &h 74 | &vmg.since(2, i) // 'i' is added in version=2 75 | &vmg.get_version(version) // optional, you can keep version number for latter use 76 | ) 77 | }; 78 | 79 | // in system or third-party's header, can not be changed 80 | struct SysData1 { 81 | int a; 82 | unsigned b; 83 | string c; 84 | }; 85 | DATA_IO_LOAD_SAVE_E(SysData1, &a &b &c) 86 | 87 | struct SysData2 { 88 | int a; 89 | unsigned b; 90 | string c; 91 | }; 92 | DATA_IO_LOAD_SAVE_EV(SysData2, &a &b &vmg.since(2, c)) 93 | 94 | int main(int argc, char* argv[]) { 95 | PortableDataOutput output; // 'Portable' is BigEndian 96 | PortableDataInput input; // 'Portable' is BigEndian 97 | 98 | MyData1 d1; 99 | // set d1 values 100 | // ... 101 | MyData2 d2; 102 | // set d2 values 103 | // ... 104 | MyData3 d3; 105 | // set d3 values 106 | // ... 107 | SysData1 sd1; 108 | SysData2 sd2; 109 | output << d1 << d2 << d3 << sd1 << sd2; // saving 110 | 111 | input = output.head(); // shallow copy, input is the written part of output 112 | input >> d1 >> d2 >> d3 >> sd1 >> sd2; // loading 113 | 114 | output.rewind(); // rewind the write pointer 115 | output & d1 & d2 & d3 & sd1 & sd2; // saving, '&' is an alias of '<<' 116 | 117 | input = output.head(); // shallow copy, input is the written part of output 118 | input & d1 & d2 & d3 & sd1 & sd2; // loading, '&' is an alias of '>>' 119 | } 120 | ``` 121 | Is it a magic? I wrote the first version of nark-serialization at July 2006, three months later, I wrote [nark-rpc](https://github.com/rockeet/nark-rpc) on top of nark-serialization. 122 | 123 | ## Compile 124 | ```bash 125 | $ cd path/to/nark-base 126 | $ make # compile nark-base 127 | $ cd test-serialization 128 | $ make # compile test and benchmark 129 | $ rls/bench.exe # run benchmark 130 | ``` 131 | 132 | ## More 133 | 134 | To be done 135 | 136 | 137 | -------------------------------------------------------------------------------- /compile-bench/GenCompileBench/GenCompileBench.cpp: -------------------------------------------------------------------------------- 1 | // GenCompileBench.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | void gen_pod_serialize(FILE* fp, const char* prefix, const vector& types) 12 | { 13 | for (int i = 0; i != (int)types.size(); ++i) 14 | { 15 | fprintf(fp, " & a%d", i); 16 | } 17 | } 18 | 19 | void gen_pod(FILE* fp, const char* prefix, int no, const vector& types) 20 | { 21 | fprintf(fp, "struct %s_pod_%d\n", prefix, no); 22 | fprintf(fp, "{\n"); 23 | for (int i = 0; i != (int)types.size(); ++i) 24 | { 25 | fprintf(fp, " %s a%d;\n", types[i].c_str(), i); 26 | } 27 | fprintf(fp, "\n"); 28 | fprintf(fp, " DATA_IO_LOAD_SAVE(%s_pod_%d, ", prefix, no); 29 | gen_pod_serialize(fp, prefix, types); 30 | fprintf(fp, ")\n"); 31 | fprintf(fp, "};\n"); 32 | } 33 | 34 | void gen_complex_serialize(FILE* fp, const char* prefix, const vector& types) 35 | { 36 | fprintf(fp, "\n"); 37 | for (int i = 0; i != (int)types.size(); ++i) 38 | { 39 | fprintf(fp, " & map_%s_%d\n", types[i].c_str(), i); 40 | fprintf(fp, " & multimap_%s_%d\n", types[i].c_str(), i); 41 | fprintf(fp, " & set_%s_%d\n", types[i].c_str(), i); 42 | fprintf(fp, " & multiset_%s_%d\n", types[i].c_str(), i); 43 | fprintf(fp, " & vector_%s_%d\n", types[i].c_str(), i); 44 | fprintf(fp, " & deque_%s_%d\n", types[i].c_str(), i); 45 | fprintf(fp, " & list_%s_%d\n", types[i].c_str(), i); 46 | } 47 | } 48 | 49 | void gen_complex(FILE* fp, const char* prefix, int no, const vector& types) 50 | { 51 | fprintf(fp, "struct %s_complex_%d\n", prefix, no); 52 | fprintf(fp, "{\n"); 53 | for (int i = 0; i != (int)types.size(); ++i) 54 | { 55 | fprintf(fp, " std::map map_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 56 | fprintf(fp, " std::multimap multimap_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 57 | fprintf(fp, " std::set<%s > set_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 58 | fprintf(fp, " std::multiset<%s > multiset_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 59 | fprintf(fp, " std::vector<%s > vector_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 60 | fprintf(fp, " std::deque<%s > deque_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 61 | fprintf(fp, " std::list<%s > list_%s_%d;\n", types[i].c_str(), types[i].c_str(), i); 62 | } 63 | fprintf(fp, "\n"); 64 | 65 | fprintf(fp, " DATA_IO_LOAD_SAVE(%s_complex_%d, ", prefix, no); 66 | gen_complex_serialize(fp, prefix, types); 67 | fprintf(fp, ")\n"); 68 | 69 | fprintf(fp, "};\n"); 70 | } 71 | 72 | void gen(FILE* fp, int count, const char* prefix, const vector& types) 73 | { 74 | vector types2 = types; 75 | gen_pod(fp, prefix, 0, types); 76 | gen_complex(fp, prefix, 0, types); 77 | 78 | for (int i = 1; i < count; ++i) 79 | { 80 | std::random_shuffle(types2.begin(), types2.end()); 81 | gen_pod(fp, prefix, i, types2); 82 | gen_complex(fp, prefix, i, types2); 83 | } 84 | 85 | fprintf(fp, "template void %s_foo(Archive& ar)\n", prefix); 86 | fprintf(fp, "{\n"); 87 | for (int i = 0; i < count; ++i) 88 | { 89 | fprintf(fp, " %s_pod_%d a_%s_pod_%d;\n", prefix, i, prefix, i); 90 | fprintf(fp, " %s_complex_%d a_%s_complex_%d;\n", prefix, i, prefix, i); 91 | } 92 | for (int i = 0; i < count; ++i) 93 | { 94 | fprintf(fp, " ar & a_%s_pod_%d;\n", prefix, i); 95 | fprintf(fp, " ar & a_%s_complex_%d;\n", prefix, i); 96 | } 97 | fprintf(fp, "}\n"); 98 | } 99 | 100 | int main(int argc, char* argv[]) 101 | { 102 | int count = argc >= 2 ? atoi(argv[1]) : 20; 103 | const char* fname = "data_nark.h"; 104 | FILE* fp = fopen(fname, "w+"); 105 | if (0 == fp) 106 | { 107 | fprintf(stderr, "open %s error\n", fname); 108 | exit(-1); 109 | } 110 | vector types; 111 | types.push_back("char"); 112 | types.push_back("uchar"); 113 | types.push_back("schar"); 114 | types.push_back("schar"); 115 | 116 | types.push_back("short"); 117 | types.push_back("ushort"); 118 | 119 | types.push_back("wchar_t"); 120 | types.push_back("wchar_t"); 121 | types.push_back("float"); 122 | 123 | types.push_back("double"); 124 | types.push_back("int"); 125 | types.push_back("unsigned"); 126 | types.push_back("long"); 127 | types.push_back("ulong"); 128 | types.push_back("longlong"); 129 | types.push_back("ulonglong"); 130 | 131 | gen(fp, count, "nark", types); 132 | 133 | fclose(fp); 134 | 135 | fname = "data_boost.h"; 136 | fp = fopen(fname, "w+"); 137 | if (0 == fp) 138 | { 139 | fprintf(stderr, "open %s error\n", fname); 140 | exit(-1); 141 | } 142 | gen(fp, count, "boost", types); 143 | 144 | fclose(fp); 145 | 146 | printf("ok!\n"); 147 | 148 | return 0; 149 | } 150 | 151 | -------------------------------------------------------------------------------- /compile-bench/GenCompileBench/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : GenCompileBench Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this GenCompileBench application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your GenCompileBench application. 9 | 10 | 11 | GenCompileBench.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | GenCompileBench.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named GenCompileBench.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /compile-bench/Makefile: -------------------------------------------------------------------------------- 1 | ../test/Makefile -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedBoost/CompileSpeedBoost.cpp: -------------------------------------------------------------------------------- 1 | // CompileSpeedBoost.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define DATA_IO_LOAD_SAVE(Class, Members) \ 15 | friend class boost::serialization::access; \ 16 | template \ 17 | void serialize(Archive & ar, const unsigned int version) \ 18 | { ar Members; } 19 | 20 | using namespace boost; 21 | using namespace std; 22 | 23 | typedef unsigned char uchar; 24 | typedef signed char schar; 25 | 26 | typedef unsigned short ushort; 27 | typedef unsigned long ulong; 28 | 29 | typedef long long longlong; 30 | typedef unsigned long long ulonglong; 31 | 32 | 33 | #include "data_boost.h" 34 | 35 | using namespace boost::archive; 36 | 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | boost_pod_0 bp0; 41 | boost_pod_1 bp1; 42 | boost_pod_2 bp2; 43 | boost_complex_0 bc0; 44 | boost_complex_1 bc1; 45 | boost_complex_2 bc2; 46 | 47 | { 48 | std::ofstream file("boost.bin", ios::binary); 49 | binary_oarchive ar(file); 50 | ar & bp0; 51 | ar & bp1; 52 | ar & bp2; 53 | ar & bc0; 54 | ar & bc1; 55 | ar & bc2; 56 | boost_foo(ar); 57 | } 58 | { 59 | std::ifstream file("boost.bin", ios::binary); 60 | binary_iarchive ar(file); 61 | ar & bp0; 62 | ar & bp1; 63 | ar & bp2; 64 | ar & bc0; 65 | ar & bc1; 66 | ar & bc2; 67 | boost_foo(ar); 68 | } 69 | return 0; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedBoost/Makefile: -------------------------------------------------------------------------------- 1 | 2 | COMPILER := $(shell ${CXX} --version | head -1 | awk '{split($$3, Ver, "."); printf("%s-%d.%d", $$1, Ver[1], Ver[2]);}') 3 | 4 | CompileSpeedBoost : CompileSpeedBoost.cpp 5 | ${CXX} -time -lboost_serialization -o $@ $^ 6 | -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedBoost/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : CompileSpeedBoost Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this CompileSpeedBoost application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your CompileSpeedBoost application. 9 | 10 | 11 | CompileSpeedBoost.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | CompileSpeedBoost.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named CompileSpeedBoost.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedNark/CompileSpeedNark.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace boost; 8 | using namespace nark; 9 | using namespace std; 10 | 11 | typedef unsigned char uchar; 12 | typedef signed char schar; 13 | 14 | typedef long long longlong; 15 | typedef unsigned long long ulonglong; 16 | 17 | #include "data_nark.h" 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | nark_pod_0 bp0; 22 | nark_pod_1 bp1; 23 | nark_pod_2 bp2; 24 | nark_complex_0 bc0; 25 | nark_complex_1 bc1; 26 | nark_complex_2 bc2; 27 | 28 | { 29 | FileStream file("boost.bin", "w+"); 30 | NativeDataOutput ar; 31 | ar.attach(&file); 32 | ar & bp0; 33 | ar & bp1; 34 | ar & bp2; 35 | ar & bc0; 36 | ar & bc1; 37 | ar & bc2; 38 | nark_foo(ar); 39 | } 40 | 41 | { 42 | FileStream file("boost.bin", "r"); 43 | NativeDataInput ar; 44 | ar.attach(&file); 45 | ar & bp0; 46 | ar & bp1; 47 | ar & bp2; 48 | ar & bc0; 49 | ar & bc1; 50 | ar & bc2; 51 | nark_foo(ar); 52 | } 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedNark/Makefile: -------------------------------------------------------------------------------- 1 | 2 | COMPILER := $(shell ${CXX} --version | head -1 | awk '{split($$3, Ver, "."); printf("%s-%d.%d", $$1, Ver[1], Ver[2]);}') 3 | 4 | #override CXXFLAGS += -I ../../../src 5 | 6 | CompileSpeedFebird : CompileSpeedFebird.cpp 7 | ${CXX} ${CXXFLAGS} -time -I../../../src -L../../../lib -lnark-${COMPILER}-d -lboost_system${BOOST_SUFFIX} -o $@ $^ 8 | 9 | -------------------------------------------------------------------------------- /compile-bench/src/CompileSpeedNark/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : CompileBench Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this CompileBench application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your CompileBench application. 9 | 10 | 11 | CompileBench.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | CompileBench.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named CompileBench.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /doc/DataIO-representation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/doc/DataIO-representation.pptx -------------------------------------------------------------------------------- /doc/DataIO.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/doc/DataIO.doc -------------------------------------------------------------------------------- /gen_env_conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | 4 | CXX=$1 5 | COMPILER=$2 6 | EnvConf=$3 7 | echo COMPILER=$COMPILER 1>&2 8 | 9 | #EnvConf=Make.env.conf-${COMPILER} 10 | 11 | rm -f $EnvConf 12 | mkdir -p `dirname $EnvConf` 13 | 14 | hasboost=0 15 | if [ -z "$BOOST_INC" ]; then 16 | boost_prefix="" 17 | else 18 | boost_prefix=`dirname $BOOST_INC` 19 | fi 20 | for dir in "$boost_prefix" /usr /usr/local /opt $HOME $HOME/opt 21 | do 22 | vf=${dir}/include/boost/version.hpp 23 | # echo dir=$dir >&2 24 | if test -s $vf; then 25 | if test -d ${dir}/lib32; then 26 | DIR_LIB32=${dir}/lib32 27 | else 28 | DIR_LIB32=${dir}/lib 29 | fi 30 | if test -d ${dir}/lib64; then 31 | DIR_LIB64=${dir}/lib64 32 | else 33 | DIR_LIB64=${dir}/lib 34 | fi 35 | WORD_BITS=`uname -m | sed 's/.*_\(64\|32\)/\1/'` 36 | DIR_LIB="DIR_LIB${WORD_BITS}" 37 | BOOST_VERSION=`sed -n '/define\s\+BOOST_VERSION/s/^.*BOOST_VERSION\s\+\([0-9]*\).*/\1/p' $vf` 38 | BOOST_LIB_VERSION=`sed -n '/define\s\+BOOST_LIB_VERSION/s/.*BOOST_LIB_VERSION[^"]*"\([0-9_.]*\)".*/\1/p' $vf` 39 | if test -z "$BOOST_SUFFIX"; then 40 | for lib in $DIR_LIB32 $DIR_LIB64; do 41 | for suf in \ 42 | -${COMPILER}-mt-d-${BOOST_LIB_VERSION}.a \ 43 | -${COMPILER}-mt-d-${BOOST_LIB_VERSION}.so \ 44 | -${COMPILER}-mt-d-${BOOST_LIB_VERSION}.so \ 45 | -mt.so \ 46 | -mt.so.5 \ 47 | -mt.so.6 \ 48 | ".a" 49 | do 50 | if test -e $lib/libboost_thread$suf -a -z "$BOOST_SUFFIX"; then 51 | BOOST_SUFFIX=$suf 52 | fi 53 | done 54 | done 55 | if expr match "$BOOST_SUFFIX" '.*\.a$' > /dev/null; then 56 | BOOST_SUFFIX=${BOOST_SUFFIX%.a*} 57 | fi 58 | if expr match "$BOOST_SUFFIX" '.*\.so' > /dev/null; then 59 | BOOST_SUFFIX=${BOOST_SUFFIX%.so*} 60 | fi 61 | fi 62 | cat >> $EnvConf <<- EOF 63 | WORD_BITS := ${WORD_BITS} 64 | DIR_LIB32 := ${DIR_LIB32} 65 | DIR_LIB64 := ${DIR_LIB64} 66 | DIR_LIB := `eval 'echo ${'$DIR_LIB'}'` 67 | BOOST_LIB_VERSION := ${BOOST_LIB_VERSION} 68 | BOOST_INC := ${dir}/include 69 | BOOST_LIB := ${dir}/lib64 70 | BOOST_SUFFIX := ${BOOST_SUFFIX} 71 | EOF 72 | if test "${COMPILER%-*}" = gcc && expr "${COMPILER#*-} < 4.7"; then 73 | if test ${BOOST_VERSION} -lt 104900; then 74 | echo BOOST_VERSION=${BOOST_VERSION} will wrongly define BOOST_DISABLE_THREADS for ${COMPILER} >&2 75 | fi 76 | fi 77 | hasboost=1 78 | break 79 | fi 80 | done 81 | 82 | if [ $hasboost -eq 0 ]; then 83 | echo $'\33[31m\33[1mFATAL: can not find boost\33[0m' 1>&2 84 | exit 1 85 | fi 86 | 87 | cat > is_cygwin.cpp << "EOF" 88 | #include 89 | int main() { 90 | #ifdef __CYGWIN__ 91 | printf("1"); 92 | #else 93 | printf("0"); 94 | #endif 95 | return 0; 96 | } 97 | EOF 98 | if $CXX is_cygwin.cpp -o is_cygwin.exe; then 99 | IS_CYGWIN=`./is_cygwin.exe` 100 | echo IS_CYGWIN=$IS_CYGWIN >> $EnvConf 101 | fi 102 | rm -f is_cygwin.* 103 | 104 | if [ "$IS_CYGWIN" = 0 ]; then 105 | cat > get_glibc_version.cpp << "EOF" 106 | #include 107 | int main() { 108 | printf("%d.%d\n", __GLIBC__, __GLIBC_MINOR__); 109 | return 0; 110 | } 111 | EOF 112 | if $CXX get_glibc_version.cpp -o get_glibc_version.exe; then 113 | GLIBC_VERSION=`./get_glibc_version.exe` 114 | echo GLIBC_VERSION_FULL=${GLIBC_VERSION} >> $EnvConf 115 | echo GLIBC_VERSION_MAJOR=`echo ${GLIBC_VERSION} | cut -d. -f1` >> $EnvConf 116 | echo GLIBC_VERSION_MINOR=`echo ${GLIBC_VERSION} | cut -d. -f2` >> $EnvConf 117 | else 118 | echo "can not detect glibc version" 1>&2 119 | fi 120 | rm -f get_glibc_version.* 121 | fi 122 | 123 | cat > has_inheriting_cons.cpp << "EOF" 124 | struct A { 125 | A(int) {} 126 | A(int,int){} 127 | }; 128 | struct B : public A { 129 | using A::A; 130 | }; 131 | int main() { 132 | B b1(111); 133 | B b2(2,2); 134 | return 0; 135 | } 136 | EOF 137 | rm -f src/nark/my_auto_config.hpp 138 | touch src/nark/my_auto_config.hpp 139 | if $CXX -std=c++11 has_inheriting_cons.cpp > /dev/null 2>&1; then 140 | echo '#define NARK_HAS_INHERITING_CONSTRUCTORS' >> src/nark/my_auto_config.hpp 141 | fi 142 | rm -f has_inheriting_cons.cpp 143 | 144 | if [ "$IS_CYGWIN" -eq 1 ]; then 145 | rm -f a.exe 146 | else 147 | rm -f a.out 148 | fi 149 | 150 | -------------------------------------------------------------------------------- /src/nark/io/BzipStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "BzipStream.hpp" 3 | 4 | #include 5 | #include 6 | 7 | #ifdef _MSC_VER 8 | # pragma comment(lib, "libbz2.lib") 9 | #endif 10 | /* 11 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 12 | # include 13 | #else 14 | # include 15 | # include 16 | # include 17 | # include 18 | # include 19 | #endif 20 | */ 21 | 22 | #include 23 | 24 | #include "byte_io_impl.hpp" 25 | #include 26 | 27 | static const char* strbzerr(int err) 28 | { 29 | switch (err) 30 | { 31 | default: 32 | { 33 | static char szbuf[64]; 34 | sprintf(szbuf, "unknow err=%d", err); 35 | return szbuf; 36 | } 37 | case BZ_OK: return "BZ_OK"; 38 | case BZ_RUN_OK: return "BZ_RUN_OK"; 39 | case BZ_FLUSH_OK: return "BZ_FLUSH_OK"; 40 | case BZ_FINISH_OK: return "BZ_FINISH_OK"; 41 | case BZ_STREAM_END: return "BZ_STREAM_END"; 42 | 43 | case BZ_CONFIG_ERROR: return "BZ_CONFIG_ERROR"; 44 | case BZ_SEQUENCE_ERROR: return "BZ_SEQUENCE_ERROR"; 45 | case BZ_PARAM_ERROR: return "BZ_PARAM_ERROR"; 46 | case BZ_MEM_ERROR: return "BZ_MEM_ERROR"; 47 | case BZ_DATA_ERROR: return "BZ_DATA_ERROR"; 48 | case BZ_DATA_ERROR_MAGIC:return "BZ_DATA_ERROR_MAGIC"; 49 | case BZ_UNEXPECTED_EOF: return "BZ_UNEXPECTED_EOF"; 50 | case BZ_OUTBUFF_FULL: return "BZ_OUTBUFF_FULL"; 51 | case BZ_IO_ERROR: return "BZ_IO_ERROR"; 52 | } 53 | } 54 | 55 | namespace nark { 56 | 57 | // only can call on unopened BzipInputStream 58 | void BzipInputStream::open(const char* fpath, const char* mode) 59 | { 60 | assert(0 == m_fp); 61 | 62 | int err; 63 | m_cf = fopen(fpath, mode); 64 | if (0 == m_cf) 65 | { 66 | string_appender<> oss; 67 | oss << "mode=" << mode; 68 | throw OpenFileException(fpath, oss.str().c_str()); 69 | } 70 | m_fp = BZ2_bzReadOpen(&err, m_cf 71 | , 0 // verbosity, 0 will not print msg 72 | , 0 // small 73 | , NULL // unused 74 | , 0 // nUnused 75 | ); 76 | if (0 == m_fp) 77 | { 78 | string_appender<> oss; 79 | oss << "mode=" << mode << ", err=" << strbzerr(err); 80 | throw OpenFileException(fpath, oss.str().c_str()); 81 | } 82 | } 83 | 84 | void BzipInputStream::dopen(int fd, const char* mode) 85 | { 86 | assert(0 == m_fp); 87 | 88 | int err; 89 | #ifdef _MSC_VER 90 | m_cf = _fdopen(fd, mode); 91 | #else 92 | m_cf = fdopen(fd, mode); 93 | #endif 94 | if (0 == m_cf) 95 | { 96 | string_appender<> oss; 97 | oss << "fd=" << fd << ", mode=" << mode; 98 | throw OpenFileException("", oss.str().c_str()); 99 | } 100 | m_fp = BZ2_bzReadOpen(&err, m_cf 101 | , 0 // verbosity, 0 will not print msg 102 | , 0 // small 103 | , NULL // unused 104 | , 0 // nUnused 105 | ); 106 | if (0 == m_fp) 107 | { 108 | string_appender<> oss; 109 | oss << "fd=" << fd << ", mode=" << mode << ", err=" << strbzerr(err); 110 | throw OpenFileException("", oss.str().c_str()); 111 | } 112 | } 113 | 114 | void BzipInputStream::close() 115 | { 116 | assert(m_fp); 117 | assert(m_cf); 118 | int err; 119 | BZ2_bzReadClose(&err, m_fp); 120 | ::fclose(m_cf); 121 | m_fp = 0; 122 | m_cf = 0; 123 | if (BZ_OK != err) 124 | { 125 | string_appender<> oss; 126 | oss << "BZ2_bzReadClose err=" << strbzerr(err) 127 | << ", in " << BOOST_CURRENT_FUNCTION; 128 | throw OpenFileException("", oss.str().c_str()); 129 | } 130 | } 131 | 132 | BzipInputStream::~BzipInputStream() 133 | { 134 | if (m_fp) 135 | this->close(); 136 | } 137 | 138 | BzipInputStream::BzipInputStream(const char* fpath, const char* mode) 139 | { 140 | m_fp = 0; 141 | m_cf = 0; 142 | open(fpath, mode); 143 | } 144 | 145 | BzipInputStream::BzipInputStream(int fd, const char* mode) 146 | { 147 | m_fp = 0; 148 | m_cf = 0; 149 | dopen(fd, mode); 150 | } 151 | 152 | bool BzipInputStream::eof() const 153 | { 154 | assert(m_cf); 155 | assert(m_fp); 156 | return !!feof(m_cf); 157 | } 158 | 159 | size_t BzipInputStream::read(void* buf, size_t size) 160 | { 161 | assert(m_cf); 162 | assert(m_fp); 163 | int err = BZ_OK; 164 | int nRead = BZ2_bzRead(&err, m_fp, buf, size); 165 | if (BZ_OK != err) 166 | { 167 | string_appender<> oss; 168 | oss << "BZ2_bzRead err=" << strbzerr(err) 169 | << ", in " << BOOST_CURRENT_FUNCTION; 170 | throw OpenFileException("", oss.str().c_str()); 171 | } 172 | assert(nRead <= (int)size); 173 | return (size_t)nRead; 174 | } 175 | 176 | NARK_GEN_ensureRead (BzipInputStream::) 177 | 178 | /////////////////////////////////////////////////////// 179 | 180 | // only can call on unopened BzipOutputStream 181 | void BzipOutputStream::open(const char* fpath, const char* mode) 182 | { 183 | assert(0 == m_fp); 184 | 185 | int err; 186 | m_cf = fopen(fpath, mode); 187 | if (0 == m_cf) 188 | { 189 | string_appender<> oss; 190 | oss << "mode=" << mode; 191 | throw OpenFileException(fpath, oss.str().c_str()); 192 | } 193 | m_fp = BZ2_bzWriteOpen(&err, m_cf 194 | , 9 // blocksize100k 195 | , 0 // verbosity 196 | , 30 // workFactor, default=30 197 | ); 198 | if (0 == m_fp) 199 | { 200 | string_appender<> oss; 201 | oss << "mode=" << mode << ", err=" << strbzerr(err); 202 | throw OpenFileException(fpath, oss.str().c_str()); 203 | } 204 | } 205 | 206 | void BzipOutputStream::dopen(int fd, const char* mode) 207 | { 208 | assert(0 == m_fp); 209 | 210 | int err; 211 | #ifdef _MSC_VER 212 | m_cf = _fdopen(fd, mode); 213 | #else 214 | m_cf = fdopen(fd, mode); 215 | #endif 216 | if (0 == m_cf) 217 | { 218 | string_appender<> oss; 219 | oss << "fd=" << fd << ", mode=" << mode; 220 | throw OpenFileException("", oss.str().c_str()); 221 | } 222 | m_fp = BZ2_bzWriteOpen(&err, m_cf 223 | , 9 // blocksize100k 224 | , 0 // verbosity 225 | , 30 // workFactor, default=30 226 | ); 227 | if (0 == m_fp) 228 | { 229 | string_appender<> oss; 230 | oss << "fd=" << fd << ", mode=" << mode << ", err=" << strbzerr(err); 231 | throw OpenFileException("", oss.str().c_str()); 232 | } 233 | } 234 | 235 | void BzipOutputStream::close() 236 | { 237 | assert(m_fp); 238 | assert(m_cf); 239 | int err = BZ_OK; 240 | int abandon = 0; 241 | unsigned in_lo32, in_hi32, out_lo32, out_hi32; 242 | BZ2_bzWriteClose64(&err, m_fp, abandon, &in_lo32, &in_hi32, &out_lo32, &out_hi32); 243 | ::fclose(m_cf); 244 | m_fp = 0; 245 | m_cf = 0; 246 | if (BZ_OK != err) 247 | { 248 | string_appender<> oss; 249 | oss << "BZ2_bzWriteClose64 err=" << strbzerr(err) 250 | << ", in " << BOOST_CURRENT_FUNCTION; 251 | throw IOException(oss.str().c_str()); 252 | } 253 | } 254 | 255 | BzipOutputStream::~BzipOutputStream() 256 | { 257 | if (m_fp) 258 | this->close(); 259 | } 260 | 261 | BzipOutputStream::BzipOutputStream(const char* fpath, const char* mode) 262 | { 263 | m_fp = 0; 264 | m_cf = 0; 265 | open(fpath, mode); 266 | } 267 | 268 | BzipOutputStream::BzipOutputStream(int fd, const char* mode) 269 | { 270 | m_fp = 0; 271 | m_cf = 0; 272 | dopen(fd, mode); 273 | } 274 | 275 | void BzipOutputStream::flush() 276 | { 277 | assert(m_fp); 278 | assert(m_cf); 279 | if (fflush(m_cf) == EOF) 280 | throw DelayWriteException(BOOST_CURRENT_FUNCTION); 281 | } 282 | 283 | size_t BzipOutputStream::write(const void* buf, size_t size) 284 | { 285 | assert(m_fp); 286 | assert(m_cf); 287 | int err = BZ_OK; 288 | BZ2_bzWrite(&err, m_fp, (void*)buf, size); 289 | if (BZ_OK != err) 290 | { 291 | string_appender<> oss; 292 | oss << "BZ2_bzWrite err=" << strbzerr(err) 293 | << ", in " << BOOST_CURRENT_FUNCTION; 294 | throw IOException(oss.str().c_str()); 295 | } 296 | return size; 297 | } 298 | NARK_GEN_ensureWrite(BzipOutputStream::) 299 | 300 | } // namespace nark 301 | 302 | -------------------------------------------------------------------------------- /src/nark/io/BzipStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_BzipStream_h__ 3 | #define __nark_io_BzipStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include "IOException.hpp" 14 | #include "IStream.hpp" 15 | 16 | namespace nark { 17 | 18 | class NARK_DLL_EXPORT BzipInputStream : public RefCounter, public IInputStream 19 | { 20 | DECLARE_NONE_COPYABLE_CLASS(BzipInputStream) 21 | void* m_fp; 22 | FILE* m_cf; 23 | 24 | public: 25 | explicit BzipInputStream(const char* fpath, const char* mode = "rb"); 26 | explicit BzipInputStream(int fd, const char* mode = "rb"); 27 | BzipInputStream() : m_fp(0), m_cf(0) {} 28 | ~BzipInputStream(); 29 | 30 | void open(const char* fpath, const char* mode = "rb"); 31 | void dopen(int fd, const char* mode = "rb"); 32 | 33 | void close(); 34 | 35 | bool isOpen() const { return 0 != m_fp; } 36 | bool eof() const; 37 | 38 | void ensureRead(void* vbuf, size_t length); 39 | size_t read(void* buf, size_t size); 40 | }; 41 | 42 | class NARK_DLL_EXPORT BzipOutputStream : public RefCounter, public IOutputStream 43 | { 44 | DECLARE_NONE_COPYABLE_CLASS(BzipOutputStream) 45 | void* m_fp; 46 | FILE* m_cf; 47 | 48 | public: 49 | explicit BzipOutputStream(const char* fpath, const char* mode = "wb"); 50 | explicit BzipOutputStream(int fd, const char* mode = "wb"); 51 | BzipOutputStream() : m_fp(0), m_cf(0) {} 52 | ~BzipOutputStream(); 53 | 54 | void close(); 55 | 56 | void open(const char* fpath, const char* mode = "wb"); 57 | void dopen(int fd, const char* mode = "wb"); 58 | bool isOpen() const { return 0 != m_fp; } 59 | 60 | void ensureWrite(const void* vbuf, size_t length); 61 | size_t write(const void* buf, size_t size); 62 | void flush(); 63 | }; 64 | 65 | } // namespace nark 66 | 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_Dump.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_Dump_h__ 3 | #define __nark_io_DataIO_Dump_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | namespace nark { 10 | 11 | //! called by dump_load_from_file/dump_save_to_file... 12 | #define DATA_IO_DUMP_LOAD_SAVE(Class) \ 13 | template \ 14 | friend void DataIO_dump_load_object(Input& in, Class& x) \ 15 | { \ 16 | x.dump_load(in); \ 17 | } \ 18 | template \ 19 | friend void DataIO_dump_save_object(Output& out, const Class& x)\ 20 | { \ 21 | x.dump_save(out); \ 22 | } 23 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 | 25 | //! @{ 26 | //! default dump_load/dump_save 27 | //! 28 | //! @note 29 | //! if dump_load/dump_save is not public member, 30 | //! please use DATA_IO_DUMP_LOAD_SAVE 31 | template 32 | void DataIO_dump_load_object(Input& in, Class& x) 33 | { 34 | x.dump_load(in); 35 | } 36 | template 37 | void DataIO_dump_save_object(Output& out, const Class& x) 38 | { 39 | x.dump_save(out); 40 | } 41 | //@} 42 | 43 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | template 45 | void DataIO_dump_load_object(DataIO& dio, std::vector& vec) 46 | { 47 | uint32_t size; 48 | dio >> size; 49 | vec.resize(size); 50 | dio.ensureRead(&*vec.begin(), sizeof(T)*size); 51 | } 52 | template 53 | void DataIO_dump_save_object(DataIO& dio, const std::vector& vec) 54 | { 55 | uint32_t size = vec.size(); 56 | dio << size; 57 | dio.ensureWrite(&*vec.begin(), sizeof(T)*size); 58 | } 59 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60 | 61 | //! 62 | #define DATA_IO_SMART_PTR_DUMP_LOAD_SAVE(SmartPtrTemplate) \ 63 | template \ 64 | void DataIO_dump_load_object(DataIO& dio, SmartPtrTemplate& x) \ 65 | { \ 66 | x.reset(new T); \ 67 | dio >> *x; \ 68 | } \ 69 | template \ 70 | void DataIO_dump_save_object(DataIO& dio, const SmartPtrTemplate& x)\ 71 | { \ 72 | dio << *x; \ 73 | } 74 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | 76 | DATA_IO_SMART_PTR_DUMP_LOAD_SAVE(std::auto_ptr) 77 | DATA_IO_SMART_PTR_DUMP_LOAD_SAVE(boost::intrusive_ptr) 78 | DATA_IO_SMART_PTR_DUMP_LOAD_SAVE(boost::scoped_ptr) 79 | DATA_IO_SMART_PTR_DUMP_LOAD_SAVE(boost::shared_ptr) 80 | 81 | 82 | } // namespace nark 83 | 84 | #endif // __nark_io_DataIO_Dump_h__ 85 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_Exception.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | 3 | #include "DataIO_Exception.hpp" 4 | #include // for sprintf 5 | #include 6 | 7 | namespace nark { 8 | 9 | DataFormatException::DataFormatException(const char* szMsg) 10 | : m_message(szMsg) 11 | { } 12 | 13 | DataFormatException::DataFormatException(const std::string& strMsg) 14 | : m_message(strMsg) 15 | { } 16 | 17 | DataFormatException::~DataFormatException() throw() 18 | {} 19 | 20 | InvalidObjectException::InvalidObjectException(const char* szMsg) 21 | : DataFormatException(szMsg) 22 | { } 23 | 24 | InvalidObjectException::InvalidObjectException(const std::string& strMsg) 25 | : DataFormatException(strMsg) 26 | { } 27 | 28 | // a size value is too large, such as container's size 29 | // 30 | void SizeValueTooLargeException::checkSizeValue(size_t value, size_t maxValue) 31 | { 32 | if (value > maxValue) 33 | throw SizeValueTooLargeException(value, maxValue); 34 | } 35 | SizeValueTooLargeException::SizeValueTooLargeException(size_t value, size_t maxValue, const char* szMsg) 36 | : DataFormatException(szMsg) 37 | { 38 | char szBuf[256]; 39 | sprintf(szBuf, "[value=%zd(0x%zX), maxValue=%zd(0x%zX)]", value, value, maxValue, maxValue); 40 | m_message.append(szBuf); 41 | } 42 | SizeValueTooLargeException::SizeValueTooLargeException(const std::string& strMsg) 43 | : DataFormatException(strMsg) 44 | { } 45 | 46 | BadVersionException::BadVersionException(unsigned loaded_version, unsigned curr_version, const char* className) 47 | : DataFormatException("") 48 | { 49 | static_cast&>(m_message = "") 50 | << "class=\"" << className << "\", version[loaded=" << loaded_version << ", current=" << curr_version << "]"; 51 | } 52 | 53 | NotFoundFactoryException::NotFoundFactoryException(const char* szMsg) 54 | : DataFormatException(szMsg) 55 | { } 56 | NotFoundFactoryException::NotFoundFactoryException(const std::string& strMsg) 57 | : DataFormatException(strMsg) 58 | { } 59 | 60 | 61 | } // namespace nark 62 | 63 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_Exception.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_Exception_h__ 3 | #define __nark_io_DataIO_Exception_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace nark { 14 | 15 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 16 | // non dll-interface class 'std::exception' used as base for dll-interface 17 | #pragma warning(push) 18 | #pragma warning(disable:4275) 19 | #endif 20 | class NARK_DLL_EXPORT DataFormatException : public std::exception 21 | { 22 | protected: 23 | std::string m_message; 24 | public: 25 | explicit DataFormatException(const char* szMsg = "nark::DataFormatException"); 26 | explicit DataFormatException(const std::string& strMsg); 27 | virtual ~DataFormatException() throw(); 28 | 29 | const char* what() const throw() { return m_message.c_str(); } 30 | }; 31 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 32 | #pragma warning(pop) 33 | #endif 34 | 35 | class NARK_DLL_EXPORT InvalidObjectException : public DataFormatException 36 | { 37 | public: 38 | explicit InvalidObjectException(const char* szMsg = "nark::InvalidObjectException"); 39 | explicit InvalidObjectException(const std::string& strMsg); 40 | }; 41 | 42 | // a size value is too large, such as container's size 43 | // 44 | class NARK_DLL_EXPORT SizeValueTooLargeException : public DataFormatException 45 | { 46 | public: 47 | static void checkSizeValue(size_t value, size_t maxValue); 48 | SizeValueTooLargeException(size_t value, size_t maxValue, const char* szMsg = "nark::SizeValueTooLargeException"); 49 | explicit SizeValueTooLargeException(const std::string& strMsg); 50 | }; 51 | 52 | class NARK_DLL_EXPORT BadVersionException : public DataFormatException 53 | { 54 | public: 55 | explicit BadVersionException(unsigned loaded_version, unsigned curr_version, const char* className); 56 | }; 57 | 58 | class NARK_DLL_EXPORT NotFoundFactoryException : public DataFormatException 59 | { 60 | public: 61 | explicit NotFoundFactoryException(const char* szMsg = "nark::NotFoundFactoryException"); 62 | explicit NotFoundFactoryException(const std::string& strMsg); 63 | }; 64 | 65 | 66 | } // namespace nark 67 | 68 | #endif // __nark_io_DataIO_Exception_h__ 69 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_SmartPtr.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_SmartPtr_h__ 3 | #define __nark_io_DataIO_SmartPtr_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | 12 | namespace nark { 13 | 14 | //! 15 | #define DATA_IO_SMART_PTR_LOAD_SAVE(SmartPtrTemplate) \ 16 | template \ 17 | void DataIO_loadObject(DataIO& dio, SmartPtrTemplate& x) \ 18 | { \ 19 | x.reset(new T); \ 20 | dio >> *x; \ 21 | } \ 22 | template \ 23 | void DataIO_saveObject(DataIO& dio, const SmartPtrTemplate& x)\ 24 | { \ 25 | dio << *x; \ 26 | } 27 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | 29 | DATA_IO_SMART_PTR_LOAD_SAVE(std::auto_ptr) 30 | DATA_IO_SMART_PTR_LOAD_SAVE(boost::intrusive_ptr) 31 | DATA_IO_SMART_PTR_LOAD_SAVE(boost::scoped_ptr) 32 | DATA_IO_SMART_PTR_LOAD_SAVE(boost::shared_ptr) 33 | 34 | 35 | } // namespace nark 36 | 37 | #endif // __nark_io_DataIO_SmartPtr_h__ 38 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_Tuple.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_Tuple_h__ 3 | #define __nark_io_DataIO_Tuple_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace nark { 14 | ////////////////////////////////////////////////////////////////////////// 15 | //! boost::tuple io 16 | 17 | template 20 | inline void DataIO_loadObject(DataIO& dio, boost::tuple& t) 21 | { 22 | typedef typename boost::tuple::inherited cons_t; 23 | DataIO_loadObject(dio, static_cast(t)); 24 | } 25 | 26 | template 27 | inline void DataIO_loadObject(DataIO& dio, boost::tuples::cons& t) 28 | { 29 | dio >> t.head; 30 | } 31 | 32 | template 33 | inline void DataIO_loadObject(DataIO&, boost::tuples::null_type&) 34 | { } 35 | 36 | template 37 | inline void DataIO_loadObject(DataIO& dio, boost::tuples::cons& t) 38 | { 39 | dio >> t.head; 40 | 41 | #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) 42 | if (boost::tuples::length::value == 0) 43 | return dio; 44 | #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 45 | 46 | DataIO_loadObject(dio, t.tail); 47 | } 48 | 49 | //--------------------------------------------------------------------------------------------------- 50 | 51 | template 54 | inline void DataIO_saveObject(DataIO& dio, const boost::tuple& t) 55 | { 56 | typedef typename boost::tuple::inherited cons_t; 57 | DataIO_saveObject(dio, static_cast(t)); 58 | } 59 | 60 | template 61 | inline void DataIO_saveObject(DataIO& dio, const boost::tuples::cons& t) 62 | { 63 | dio << t.head; 64 | } 65 | 66 | template 67 | inline void DataIO_saveObject(DataIO&, const boost::tuples::null_type&) 68 | { } 69 | 70 | template 71 | inline void DataIO_saveObject(DataIO& dio, const boost::tuples::cons& t) 72 | { 73 | dio << t.head; 74 | 75 | #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) 76 | if (boost::tuples::length::value == 0) 77 | return; 78 | #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 79 | 80 | DataIO_saveObject(dio, t.tail); 81 | } 82 | 83 | 84 | } // namespace nark 85 | 86 | #endif // __nark_io_DataIO_Tuple_h__ 87 | -------------------------------------------------------------------------------- /src/nark/io/DataIO_Version.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_Version_h__ 3 | #define __nark_io_DataIO_Version_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | //#include "var_int.hpp" 11 | #include 12 | #include 13 | 14 | namespace nark { 15 | 16 | BOOST_STRONG_TYPEDEF(uint32_t, serialize_version_t) 17 | 18 | //! 可以在 DATA_IO_VERSIONED_LOAD_SAVE 宏中使用 19 | //! 20 | //! 用来声明只序列化更高 version 的对象成员 21 | //! @see DataIO_version_manager::since 22 | //! 23 | template 24 | class DataIO_since_version_proxy 25 | { 26 | unsigned int m_min_owner_version; 27 | unsigned int m_version; 28 | Class& m_object; 29 | 30 | public: 31 | DataIO_since_version_proxy(unsigned int min_owner_version, unsigned int loaded_owner_version, Class& object) 32 | : m_min_owner_version(min_owner_version) 33 | , m_version(loaded_owner_version) 34 | , m_object(object) 35 | { 36 | } 37 | template friend void 38 | DataIO_loadObject(Input& input, DataIO_since_version_proxy x) 39 | { 40 | if (x.m_version >= x.m_min_owner_version) 41 | { 42 | input >> x.m_object; 43 | } 44 | } 45 | template friend void 46 | DataIO_saveObject(Output& output, const DataIO_since_version_proxy& x) 47 | { 48 | if (x.m_version >= x.m_min_owner_version) 49 | { 50 | output << x.m_object; 51 | } 52 | } 53 | }; 54 | 55 | //! 可以在 DATA_IO_VERSIONED_LOAD_SAVE 宏中使用 56 | //! 57 | //! 当载入对象时,用来把 version 拷贝到成员 58 | //! @see DataIO_version_manager::get_version 59 | //! 60 | class DataIO_copy_version_proxy 61 | { 62 | uint32_t& m_version; 63 | uint32_t m_loadedVersion; 64 | public: 65 | DataIO_copy_version_proxy(uint32_t& version, uint32_t loadedVersion) 66 | : m_version(version), m_loadedVersion(loadedVersion) {} 67 | 68 | template friend void 69 | DataIO_loadObject(Input&, DataIO_copy_version_proxy x) 70 | { 71 | x.m_version = x.m_loadedVersion; 72 | } 73 | 74 | template friend void 75 | DataIO_saveObject(Output&, const DataIO_copy_version_proxy&) 76 | { 77 | // ignore 78 | } 79 | }; 80 | 81 | //! 可以在 DATA_IO_REG_LOAD_SAVE_V 宏中使用 82 | //! 83 | //! 用来在派生类中调用基类的 dio_load(object, version)/dio_save(object, version) 84 | //! 85 | //! @see DataIO_version_manager::base 86 | template 87 | class DataIO_base_class_version_load_save 88 | { 89 | BaseClassPtr m_base; 90 | unsigned int m_version; 91 | 92 | public: 93 | DataIO_base_class_version_load_save(BaseClassPtr pbase, unsigned int version) 94 | : m_base(pbase), m_version(version) {} 95 | 96 | template friend void 97 | DataIO_loadObject(Input& input, DataIO_base_class_version_load_save x) 98 | { 99 | x.m_base->dio_load(input, x.m_version); 100 | } 101 | template friend void 102 | DataIO_saveObject(Output& output, const DataIO_base_class_version_load_save& x) 103 | { 104 | x.m_base->dio_save(output, x.m_version); 105 | } 106 | }; 107 | 108 | //! 版本管理 109 | //! 110 | //! @see DATA_IO_REG_VERSION_SERIALIZE/DATA_IO_REG_LOAD_SAVE_V 111 | //! 112 | template class DataIO_version_manager 113 | { 114 | unsigned int m_version; 115 | 116 | public: 117 | DataIO_version_manager(unsigned int loaded_owner_version) 118 | : m_version(loaded_owner_version) 119 | { 120 | } 121 | 122 | template 123 | pass_by_value > 124 | since(unsigned int min_owner_version, Class& object) 125 | { 126 | return pass_by_value > 127 | (DataIO_since_version_proxy(min_owner_version, m_version, object)); 128 | } 129 | template 130 | DataIO_since_version_proxy 131 | since(unsigned int min_owner_version, const Class& object) 132 | { 133 | return DataIO_since_version_proxy(min_owner_version, m_version, object); 134 | } 135 | 136 | pass_by_value 137 | get_version(uint32_t& version) 138 | { 139 | return pass_by_value 140 | (DataIO_copy_version_proxy(version, m_version)); 141 | } 142 | 143 | //! version is const when dio_save() 144 | DataIO_copy_version_proxy 145 | get_version(const uint32_t&/*version*/) 146 | { 147 | static uint32_t v2; 148 | return DataIO_copy_version_proxy(v2, m_version); 149 | } 150 | 151 | //! @{ 152 | //! if base class version is same with the derived class, 153 | //! use this function to read base object 154 | //! for loading 155 | template 156 | pass_by_value > 157 | base(BaseClass* self) 158 | { 159 | return pass_by_value > 160 | (DataIO_base_class_version_load_save(self, m_version)); 161 | } 162 | 163 | //! for saving 164 | template 165 | DataIO_base_class_version_load_save 166 | base(const BaseClass* self) 167 | { 168 | return DataIO_base_class_version_load_save(self, m_version); 169 | } 170 | //@} 171 | 172 | //! @{ 173 | //! if base class is a prev version, use this function to read base object 174 | //! for loading 175 | template 176 | pass_by_value > 177 | base(BaseClass* self, unsigned base_version) 178 | { 179 | return pass_by_value > 180 | (DataIO_base_class_version_load_save(self, base_version)); 181 | } 182 | 183 | //! for saving 184 | template 185 | DataIO_base_class_version_load_save 186 | base(const BaseClass* self, unsigned base_version) 187 | { 188 | return DataIO_base_class_version_load_save(self, base_version); 189 | } 190 | //@} 191 | }; 192 | 193 | } // namespace nark 194 | 195 | #endif // __nark_io_DataIO_Version_h__ 196 | 197 | -------------------------------------------------------------------------------- /src/nark/io/DataInputIterator.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataInputIterator_h__ 3 | #define __nark_io_DataInputIterator_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #ifndef __nark_io_DataInput_h__ 10 | #include "DataInput.hpp" 11 | #endif 12 | 13 | namespace nark { 14 | 15 | template 16 | LittleEndianDataInput LittleEndianDataInputer(StreamClass* stream) 17 | { 18 | return LittleEndianDataInput(stream); 19 | } 20 | 21 | template 22 | PortableDataInput PortableDataInputer(StreamClass* stream) 23 | { 24 | return PortableDataInput(stream); 25 | } 26 | ////////////////////////////////////////////////////////////////////////// 27 | 28 | template 29 | class DataInputIterator : 30 | public boost::input_iterator_helper, T> 31 | { 32 | DataInput m_input; 33 | size_t m_count; 34 | 35 | public: 36 | //! 序列的 count 已知,构造这个序列 iterator 37 | DataInputIterator(DataInput input, size_t count) 38 | : m_input(input), m_count(count) 39 | { 40 | assert(m_count > 0); 41 | } 42 | 43 | //! 序列的 count 还在 stream 中,构造时读取它(var_uint32_t 的 count) 44 | DataInputIterator(DataInput input) 45 | : m_input(input) 46 | { 47 | var_uint32_t x; input >> x; 48 | m_count = x.t; 49 | } 50 | 51 | DataInputIterator() 52 | : m_count(0) {} 53 | 54 | //! 读取之后立即往前走,所以,同一个位置只能读取一次 55 | T operator*() 56 | { 57 | assert(m_count > 0); 58 | --m_count; 59 | 60 | T x; m_input >> x; 61 | return x; 62 | } 63 | 64 | //! 无操作 65 | DataInputIterator& operator++() 66 | { 67 | assert(m_count >= 0); 68 | return *this; 69 | } 70 | 71 | bool operator==(const DataInputIterator& r) const 72 | { 73 | return r.m_count == this->m_count; 74 | } 75 | 76 | bool is_end() const { return 0 == m_count; } 77 | 78 | size_t count() const { return m_count; } 79 | }; 80 | 81 | ////////////////////////////////////////////////////////////////////////// 82 | 83 | } 84 | 85 | #endif // __nark_io_DataInputIterator_h__ 86 | 87 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_Basic.hpp: -------------------------------------------------------------------------------- 1 | 2 | typedef boost::mpl::true_ is_loading; 3 | typedef boost::mpl::false_ is_saving; 4 | typedef var_uint32_t my_var_uint32_t; // for decompose & argument dependent lookup 5 | typedef var_uint64_t my_var_uint64_t; 6 | typedef var_size_t my_var_size_t; 7 | typedef DataFormatException my_DataFormatException; 8 | typedef BadVersionException my_BadVersionException; 9 | 10 | // endian of float types are same as corresponding size integer's 11 | MyType& operator>>(float& x) { 12 | BOOST_STATIC_ASSERT(sizeof(float) == 4); 13 | *this >> *(uint32_t*)(&x); 14 | return *this; 15 | } 16 | MyType& operator>>(double& x) { 17 | BOOST_STATIC_ASSERT(sizeof(double) == 8); 18 | *this >> *(uint64_t*)(&x); 19 | return *this; 20 | } 21 | MyType& operator>>(long double& x) { 22 | // wire format of 'long double' is same as double 23 | double y; 24 | *this >> y; 25 | x = y; 26 | return *this; 27 | } 28 | 29 | MyType& operator>>(var_size_t& x) { 30 | // default same with 'var_size_t_base' 31 | // can be overload and hidden by derived 32 | *this >> static_cast(x); 33 | return *this; 34 | } 35 | 36 | ////////////////////////////////////////////////////////////////////////// 37 | //! dual operator, for auto dispatch single serialize proc... 38 | //! 39 | //! for DataInput , operator& is input, 40 | //! for DataOutput, operator& is output. 41 | template MyType& operator&(T& x) { return operator>>(x); } 42 | 43 | //------------------------------------------------------------------------------------------------- 44 | //! can not bound temp object to non-const reference, 45 | //! so use pass_by_value object in this case 46 | //! @{ 47 | template MyType& operator& (pass_by_value x) { return (*this) >> x.val; } 48 | template MyType& operator>>(pass_by_value x) { return (*this) >> x.val; } 49 | //@} 50 | //------------------------------------------------------------------------------------------------- 51 | 52 | template MyType& operator& (boost::reference_wrapper x) { return (*this) >> x.get(); } 53 | template MyType& operator>>(boost::reference_wrapper x) { return (*this) >> x.get(); } 54 | 55 | template MyType& operator>>(char (&x)[Dim]) { return this->load(x, Dim); } 56 | template MyType& operator>>(unsigned char (&x)[Dim]) { return this->load(x, Dim); } 57 | template MyType& operator>>( signed char (&x)[Dim]) { return this->load(x, Dim); } 58 | 59 | #ifdef DATA_IO_SUPPORT_SERIALIZE_PTR 60 | template MyType& operator>>(T*& x) 61 | { 62 | x = new T; 63 | *this >> *x; 64 | return *this; 65 | } 66 | #else 67 | template MyType& operator>>(T*&) 68 | { 69 | T::NotSupportSerializePointer(); 70 | return *this; 71 | } 72 | #endif 73 | 74 | //!@{ 75 | //! standard container this->.... 76 | 77 | template 78 | MyType& operator>>(std::pair& x) 79 | { 80 | return *this >> x.first >> x.second; 81 | } 82 | 83 | template 84 | MyType& operator>>(std::map& x) 85 | { 86 | var_size_t size; *this >> size; 87 | x.clear(); 88 | for (size_t i = 0; i < size.t; ++i) 89 | { 90 | std::pair e; 91 | *this >> e; 92 | x.insert(x.end(), e); // x.end() as hint, time complexity is O(1) 93 | } 94 | return *this; 95 | } 96 | 97 | template 98 | MyType& operator>>(std::multimap& x) 99 | { 100 | var_size_t size; *this >> size; 101 | x.clear(); 102 | for (size_t i = 0; i < size.t; ++i) 103 | { 104 | std::pair e; 105 | *this >> e; 106 | x.insert(x.end(), e); // x.end() as hint, time complexity is O(1) 107 | } 108 | return *this; 109 | } 110 | 111 | template 112 | MyType& operator>>(std::set& x) 113 | { 114 | x.clear(); 115 | var_size_t size; 116 | *this >> size; 117 | for (size_t i = 0; i < size.t; ++i) 118 | { 119 | ValueT e; 120 | *this >> e; 121 | x.insert(x.end(), e); // x.end() as hint, time complexity is O(1) 122 | } 123 | return *this; 124 | } 125 | 126 | template 127 | MyType& operator>>(std::multiset& x) 128 | { 129 | x.clear(); 130 | var_size_t size; 131 | *this >> size; 132 | for (size_t i = 0; i < size.t; ++i) 133 | { 134 | ValueT e; 135 | *this >> e; 136 | x.insert(x.end(), e); // x.end() as hint, time complexity is O(1) 137 | } 138 | return *this; 139 | } 140 | 141 | template 142 | MyType& operator>>(std::list& x) 143 | { 144 | x.clear(); 145 | var_size_t size; 146 | *this >> size; 147 | for (size_t i = 0; i < size.t; ++i) 148 | { 149 | x.push_back(ValueT()); 150 | *this >> x.back(); 151 | } 152 | return *this; 153 | } 154 | 155 | template 156 | MyType& operator>>(std::deque& x) 157 | { 158 | x.clear(); 159 | var_size_t size; 160 | *this >> size; 161 | for (size_t i = 0; i < size.t; ++i) 162 | { 163 | x.push_back(ValueT()); 164 | *this >> x.back(); 165 | } 166 | return *this; 167 | } 168 | //!@} 169 | 170 | template 171 | T load_as() { 172 | T x; 173 | *this >> x; 174 | return x; 175 | } 176 | 177 | template 178 | void skip_obj() { 179 | T x; 180 | *this >> x; 181 | } 182 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_BigEndian.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | 3 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(short) 4 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(unsigned short) 5 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(int) 6 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(unsigned int) 7 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(long) 8 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(unsigned long) 9 | 10 | #if defined(BOOST_HAS_LONG_LONG) 11 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(long long) 12 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(unsigned long long) 13 | #elif defined(BOOST_HAS_MS_INT64) 14 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(__int64) 15 | DATA_IO_GEN_BIG_ENDIAN_INT_INPUT(unsigned __int64) 16 | #endif 17 | 18 | MyType& load(wchar_t* s, size_t n) 19 | { 20 | this->ensureRead(s, sizeof(wchar_t)*n); 21 | #ifdef BOOST_LITTLE_ENDIAN 22 | byte_swap(s, n); 23 | #endif 24 | return *this; 25 | } 26 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T 27 | MyType& operator>>(wchar_t& x) 28 | { 29 | this->ensureRead(&x, sizeof(x)); 30 | #ifdef BOOST_LITTLE_ENDIAN 31 | x = byte_swap(x); 32 | #endif 33 | return *this; 34 | } 35 | #endif 36 | 37 | template MyType& operator>>(T& x) 38 | { 39 | DataIO_load_elem(*this, x, DATA_IO_BSWAP_FOR_BIG(T)()); 40 | return *this; 41 | } 42 | 43 | template 44 | MyType& operator>>(T (&x)[Dim]) 45 | { 46 | DataIO_load_array(*this, x, Dim, DATA_IO_BSWAP_FOR_BIG(T)()); 47 | return *this; 48 | } 49 | 50 | template 51 | MyType& operator>>(valvec& x) 52 | { 53 | DataIO_load_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_BIG(T)()); 54 | return *this; 55 | } 56 | 57 | template 58 | MyType& operator>>(std::vector& x) 59 | { 60 | DataIO_load_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_BIG(T)()); 61 | return *this; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_LittleEndian.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | 3 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(short) 4 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(unsigned short) 5 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(int) 6 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(unsigned int) 7 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(long) 8 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(unsigned long) 9 | 10 | #if defined(BOOST_HAS_LONG_LONG) 11 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(long long) 12 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(unsigned long long) 13 | #elif defined(BOOST_HAS_MS_INT64) 14 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(__int64) 15 | DATA_IO_GEN_LITTLE_ENDIAN_INT_INPUT(unsigned __int64) 16 | #endif 17 | 18 | MyType& load(wchar_t* s, size_t n) 19 | { 20 | this->ensureRead(s, sizeof(wchar_t)*n); 21 | #ifdef BOOST_BIG_ENDIAN 22 | byte_swap(s, n); 23 | #endif 24 | return *this; 25 | } 26 | 27 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T 28 | MyType& operator>>(wchar_t& x) 29 | { 30 | this->ensureRead(&x, sizeof(x)); 31 | #ifdef BOOST_BIG_ENDIAN 32 | x = byte_swap(x); 33 | #endif 34 | return *this; 35 | } 36 | #endif 37 | 38 | template MyType& operator>>(T& x) 39 | { 40 | DataIO_load_elem(*this, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 41 | return *this; 42 | } 43 | 44 | template 45 | MyType& operator>>(T (&x)[Dim]) 46 | { 47 | DataIO_load_array(*this, x, Dim, DATA_IO_BSWAP_FOR_LITTLE(T)()); 48 | return *this; 49 | } 50 | 51 | template 52 | MyType& operator>>(valvec& x) 53 | { 54 | DataIO_load_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 55 | return *this; 56 | } 57 | 58 | template 59 | MyType& operator>>(std::vector& x) 60 | { 61 | DataIO_load_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 62 | return *this; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_String.hpp: -------------------------------------------------------------------------------- 1 | 2 | MyType& operator>>( char& x) { x = ( char)getStream()->readByte(); return *this; } 3 | MyType& operator>>(unsigned char& x) { x = (unsigned char)getStream()->readByte(); return *this; } 4 | MyType& operator>>( signed char& x) { x = ( signed char)getStream()->readByte(); return *this; } 5 | 6 | MyType& load( char* s, size_t n) { this->ensureRead(s, n); return *this; } 7 | MyType& load(unsigned char* s, size_t n) { this->ensureRead(s, n); return *this; } 8 | MyType& load( signed char* s, size_t n) { this->ensureRead(s, n); return *this; } 9 | 10 | MyType& operator>>(std::string& x) 11 | { 12 | this->getStream()->read_string(x); 13 | return *this; 14 | } 15 | // MyType& operator>>(std:: string& x) { return load_s1(x); } 16 | MyType& operator>>(std::wstring& x) { return load_s1(x); } 17 | 18 | private: 19 | //! string in file format: [length : ....content.... ] 20 | template 21 | MyType& load_s1(std::basic_string& x) 22 | { 23 | var_size_t length; 24 | *this >> length; 25 | x.resize(length.t); // str will be allocated at least (length+1) chars.. 26 | if (nark_likely(length.t)) { 27 | // CharType* data = const_cast(str.data()); 28 | CharType* data = &*x.begin(); // this will make a mutable string content 29 | this->load(data, length.t); 30 | // data[length.t] = 0; // in most string implementation, this is accessible 31 | // data[length.t] = 0; // in some string implementation, this is out of string bound 32 | } 33 | return *this; 34 | } 35 | 36 | #ifdef NARK_DATA_IO_ENABLE_LOAD_RAW_CHAR_PTR 37 | public: 38 | MyType& operator>>(char*& s) { return load_s0(s); } 39 | MyType& operator>>(wchar_t*& s) { return load_s0(s); } 40 | private: 41 | template MyType& load_s0(ChT*& s) 42 | { 43 | assert(0 == s); 44 | var_size_t n; 45 | *this >> n; 46 | s = new ChT[n.t+1]; 47 | this->load(s, n.t); 48 | s[n] = 0; 49 | return *this; 50 | } 51 | #endif 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_VarIntAsFixLen.hpp: -------------------------------------------------------------------------------- 1 | MyType& operator>>(var_int32_t & x) { return *this >> x.t; } 2 | MyType& operator>>(var_uint32_t& x) { return *this >> x.t; } 3 | 4 | #if !defined(BOOST_NO_INT64_T) 5 | MyType& operator>>(var_int64_t & x) { return *this >> x.t; } 6 | MyType& operator>>(var_uint64_t& x) { return *this >> x.t; } 7 | #endif 8 | MyType& operator>>(serialize_version_t& x) { return *this >> x.t; } 9 | 10 | MyType& operator>>(var_int30_t & x) { return *this >> x.t; } 11 | MyType& operator>>(var_uint30_t& x) { return *this >> x.t; } 12 | 13 | #if !defined(BOOST_NO_INT64_T) 14 | MyType& operator>>(var_int61_t & x) { return *this >> x.t; } 15 | MyType& operator>>(var_uint61_t& x) { return *this >> x.t; } 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /src/nark/io/DataInput_VarIntAsVarLen.hpp: -------------------------------------------------------------------------------- 1 | #ifdef NARK_DATA_IO_SLOW_VAR_INT 2 | protected: 3 | template 4 | UInt load_var_uint() 5 | { 6 | const int maxshift = sizeof(UInt) == 4 ? 28 : 63; 7 | UInt x = 0; 8 | for (int shift = 0; shift <= maxshift; shift += 7) 9 | { 10 | byte b; *this >> b; 11 | x |= UInt(b & 0x7F) << shift; 12 | if ((b & 0x80) == 0) 13 | return x; 14 | } 15 | assert(0); // should not get here 16 | throw std::runtime_error(BOOST_CURRENT_FUNCTION); 17 | } 18 | public: 19 | MyType& operator>>(var_int32_t& x) 20 | { 21 | x.t = var_int32_u2s(load_var_uint()); 22 | return *this; 23 | } 24 | MyType& operator>>(var_uint32_t& x) 25 | { 26 | x.t = load_var_uint(); 27 | return *this; 28 | } 29 | 30 | #if !defined(BOOST_NO_INT64_T) 31 | MyType& operator>>(var_int64_t& x) 32 | { 33 | x.t = var_int64_u2s(load_var_uint()); 34 | return *this; 35 | } 36 | MyType& operator>>(var_uint64_t& x) 37 | { 38 | x.t = load_var_uint(); 39 | return *this; 40 | } 41 | #endif 42 | MyType& operator>>(serialize_version_t& x) 43 | { 44 | x.t = load_var_uint(); 45 | return *this; 46 | } 47 | 48 | #else // NARK_DATA_IO_SLOW_VAR_INT 49 | 50 | // fast var_*int* 51 | MyType& operator>>(var_int32_t& x) 52 | { 53 | x.t = this->getStream()->read_var_int32(); 54 | return *this; 55 | } 56 | MyType& operator>>(var_uint32_t& x) 57 | { 58 | x.t = this->getStream()->read_var_uint32(); 59 | return *this; 60 | } 61 | 62 | #if !defined(BOOST_NO_INT64_T) 63 | MyType& operator>>(var_int64_t& x) 64 | { 65 | x.t = this->getStream()->read_var_int64(); 66 | return *this; 67 | } 68 | MyType& operator>>(var_uint64_t& x) 69 | { 70 | x.t = this->getStream()->read_var_uint64(); 71 | return *this; 72 | } 73 | #endif 74 | MyType& operator>>(serialize_version_t& x) 75 | { 76 | x.t = this->getStream()->read_var_uint32(); 77 | return *this; 78 | } 79 | #endif // NARK_DATA_IO_SLOW_VAR_INT 80 | 81 | //------------------------------------------------------------- 82 | MyType& operator>>(var_int30_t& x) 83 | { 84 | x.t = this->getStream()->read_var_int30(); 85 | return *this; 86 | } 87 | MyType& operator>>(var_uint30_t& x) 88 | { 89 | x.t = this->getStream()->read_var_uint30(); 90 | return *this; 91 | } 92 | 93 | #if !defined(BOOST_NO_INT64_T) 94 | MyType& operator>>(var_int61_t& x) 95 | { 96 | x.t = this->getStream()->read_var_int61(); 97 | return *this; 98 | } 99 | MyType& operator>>(var_uint61_t& x) 100 | { 101 | x.t = this->getStream()->read_var_uint61(); 102 | return *this; 103 | } 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_Basic.hpp: -------------------------------------------------------------------------------- 1 | typedef boost::mpl::false_ is_loading; 2 | typedef boost::mpl::true_ is_saving; 3 | typedef var_uint32_t my_var_uint32_t; // for decompose & argument dependent lookup 4 | typedef var_uint64_t my_var_uint64_t; 5 | typedef var_size_t my_var_size_t; 6 | 7 | ////////////////////////////////////////////////////////////////////////// 8 | //! dual operator, for auto dispatch single serialize proc... 9 | //! 10 | //! for PrimitiveOutputImpl, operator& is output, 11 | //! for DataOutput, operator& is output. 12 | template MyType& operator&(const T& x) { return operator<<(x); } 13 | 14 | template MyType& operator& (pass_by_value x) { return operator<<(x.val); } 15 | template MyType& operator<<(pass_by_value x) { return operator<<(x.val); } 16 | 17 | template MyType& operator& (boost::reference_wrapper x) { return operator<<(x.get()); } 18 | template MyType& operator<<(boost::reference_wrapper x) { return operator<<(x.get()); } 19 | 20 | template MyType& operator<<(const char (&x)[Dim]) { return this->save(x, Dim); } 21 | template MyType& operator<<(const byte (&x)[Dim]) { return this->save(x, Dim); } 22 | 23 | #ifdef DATA_IO_SUPPORT_SERIALIZE_PTR 24 | template MyType& operator<<(T*& x) 25 | { 26 | *this << *x; 27 | return *this; 28 | } 29 | template MyType& operator<<(const T*& x) 30 | { 31 | *this << *x; 32 | return *this; 33 | } 34 | #else 35 | template MyType& operator<<(T*&) 36 | { 37 | T::NotSupportSerializePointer(); 38 | return *this; 39 | } 40 | template MyType& operator<<(const T*&) 41 | { 42 | T::NotSupportSerializePointer(); 43 | return *this; 44 | } 45 | #endif 46 | 47 | template 48 | MyType& container_save(const Container& x) 49 | { 50 | var_size_t size(x.size()); 51 | *this << size; 52 | typename Container::const_iterator i = x.begin(); 53 | for (; i != x.end(); ++i) *this << *i; 54 | return *this; 55 | } 56 | 57 | //!@{ 58 | //! standard container output..... 59 | template 60 | MyType& operator<<(const std::map& x) 61 | { 62 | return container_save(x); 63 | } 64 | template 65 | MyType& operator<<(const std::multimap& x) 66 | { 67 | return container_save(x); 68 | } 69 | template 70 | MyType& operator<<(const std::set& x) 71 | { 72 | return container_save(x); 73 | } 74 | template 75 | MyType& operator<<(const std::multiset& x) 76 | { 77 | return container_save(x); 78 | } 79 | template 80 | MyType& operator<<(const std::list& x) 81 | { 82 | return container_save(x); 83 | } 84 | template 85 | MyType& operator<<(const std::deque& x) 86 | { 87 | return container_save(x); 88 | } 89 | 90 | // endian of float types are same as corresponding size integer's 91 | MyType& operator<<(const float x) { 92 | BOOST_STATIC_ASSERT(sizeof(float) == 4); 93 | uint32_t ix; 94 | memcpy(&ix, &x, 4); 95 | *this << ix; 96 | return *this; 97 | } 98 | MyType& operator<<(const double x) { 99 | BOOST_STATIC_ASSERT(sizeof(double) == 8); 100 | uint64_t ix; 101 | memcpy(&ix, &x, 8); 102 | *this << ix; 103 | return *this; 104 | } 105 | MyType& operator<<(const long double x) { 106 | // wire format of 'long double' is same as double 107 | *this << double(x); 108 | return *this; 109 | } 110 | MyType& operator<<(const var_size_t x) { 111 | // default same with 'var_size_t_base' 112 | // can be overload and hidden by derived 113 | *this << static_cast(x); 114 | return *this; 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_BigEndian.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | 3 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(short) 4 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(unsigned short) 5 | 6 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(int) 7 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(unsigned int) 8 | 9 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(long) 10 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(unsigned long) 11 | 12 | #if defined(BOOST_HAS_LONG_LONG) 13 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(long long) 14 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(unsigned long long) 15 | #elif defined(BOOST_HAS_MS_INT64) 16 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(__int64) 17 | DATA_IO_GEN_BIG_ENDIAN_INT_OUTPUT(unsigned __int64) 18 | #endif 19 | 20 | MyType& save(const wchar_t* s, size_t n) 21 | { 22 | #ifdef BOOST_BIG_ENDIAN 23 | this->ensureWrite(s, sizeof(wchar_t)*n); 24 | #else 25 | std::vector tempv(s, s + n); 26 | byte_swap(&*tempv.begin(), n); 27 | this->ensureWrite(&*tempv.begin(), sizeof(wchar_t)*n); 28 | #endif 29 | return *this; 30 | } 31 | 32 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T 33 | MyType& operator<<(wchar_t x) 34 | { 35 | #ifdef BOOST_LITTLE_ENDIAN 36 | x = byte_swap(x); 37 | #endif 38 | this->ensureWrite(&x, sizeof(x)); 39 | return *this; 40 | } 41 | #endif 42 | 43 | template MyType& operator<<(const T& x) 44 | { 45 | DataIO_save_elem(*this, x, DATA_IO_BSWAP_FOR_BIG(T)()); 46 | return *this; 47 | } 48 | 49 | template 50 | MyType& operator<<(const T (&x)[Dim]) 51 | { 52 | DataIO_save_array(*this, x, Dim, DATA_IO_BSWAP_FOR_BIG(T)()); 53 | return *this; 54 | } 55 | 56 | template 57 | MyType& operator<<(const valvec& x) 58 | { 59 | DataIO_save_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_BIG(T)()); 60 | return *this; 61 | } 62 | 63 | template 64 | MyType& operator<<(const std::vector& x) 65 | { 66 | DataIO_save_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_BIG(T)()); 67 | return *this; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_LittleEndian.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | 3 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(short) 4 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(unsigned short) 5 | 6 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(int) 7 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(unsigned int) 8 | 9 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(long) 10 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(unsigned long) 11 | 12 | #if defined(BOOST_HAS_LONG_LONG) 13 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(long long) 14 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(unsigned long long) 15 | #elif defined(BOOST_HAS_MS_INT64) 16 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(__int64) 17 | DATA_IO_GEN_LITTLE_ENDIAN_INT_OUTPUT(unsigned __int64) 18 | #endif 19 | 20 | MyType& save(const wchar_t* s, size_t n) 21 | { 22 | #ifdef BOOST_LITTLE_ENDIAN 23 | this->ensureWrite(s, sizeof(wchar_t)*n); 24 | #else 25 | std::vector tempv(s, s + n); 26 | byte_swap(&*tempv.begin(), n); 27 | this->ensureWrite(&*tempv.begin(), sizeof(wchar_t)*n); 28 | #endif 29 | return *this; 30 | } 31 | 32 | #ifndef BOOST_NO_INTRINSIC_WCHAR_T 33 | MyType& operator<<(wchar_t x) 34 | { 35 | #ifdef BOOST_BIG_ENDIAN 36 | x = byte_swap(x); 37 | #endif 38 | this->ensureWrite(&x, sizeof(x)); 39 | return *this; 40 | } 41 | #endif 42 | 43 | template MyType& operator<<(const T& x) 44 | { 45 | DataIO_save_elem(*this, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 46 | return *this; 47 | } 48 | 49 | template 50 | MyType& operator<<(const T (&x)[Dim]) 51 | { 52 | DataIO_save_array(*this, x, Dim, DATA_IO_BSWAP_FOR_LITTLE(T)()); 53 | return *this; 54 | } 55 | 56 | template 57 | MyType& operator<<(const valvec& x) 58 | { 59 | DataIO_save_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 60 | return *this; 61 | } 62 | 63 | template 64 | MyType& operator<<(const std::vector& x) 65 | { 66 | DataIO_save_vector(*this, (T*)NULL, x, DATA_IO_BSWAP_FOR_LITTLE(T)()); 67 | return *this; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_String.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | MyType& operator<<( char x) { this->writeByte((byte)x); return *this; } 3 | MyType& operator<<( signed char x) { this->writeByte((byte)x); return *this; } 4 | MyType& operator<<(unsigned char x) { this->writeByte((byte)x); return *this; } 5 | 6 | MyType& save(const char* s, size_t n) { this->ensureWrite(s, n); return *this; } 7 | MyType& save(const signed char* s, size_t n) { this->ensureWrite(s, n); return *this; } 8 | MyType& save(const unsigned char* s, size_t n) { this->ensureWrite(s, n); return *this; } 9 | 10 | MyType& operator<<(const char* s) 11 | { 12 | var_size_t n(strlen(s)); 13 | *this << n; 14 | this->ensureWrite(s, n.t); 15 | return *this; 16 | } 17 | MyType& operator<<(const wchar_t* s) 18 | { 19 | var_size_t n(wcslen(s)); 20 | *this << n; 21 | this->save(s, n.t); 22 | return *this; 23 | } 24 | 25 | template 26 | MyType& operator<<(const std::basic_string& x) 27 | { 28 | var_size_t length(x.size()); 29 | *this << (length); 30 | this->save(x.data(), length.t); 31 | return *this; 32 | } 33 | 34 | MyType& operator<<(const std::string& x) 35 | { 36 | #if 0 37 | var_size_t length(x.size()); 38 | *this << (length); 39 | this->save(x.data(), length.t); 40 | #else 41 | this->getStream()->write_string(x); 42 | #endif 43 | return *this; 44 | } 45 | 46 | MyType& operator<<(const std::wstring& x) 47 | { 48 | var_size_t length(x.size()); 49 | *this << (length); 50 | this->save(x.data(), length.t); 51 | return *this; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_VarIntAsFixLen.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | MyType& operator<<(var_int32_t x) { return this->operator<<(x.t); } 3 | MyType& operator<<(var_uint32_t x) { return this->operator<<(x.t); } 4 | 5 | #if !defined(BOOST_NO_INT64_T) 6 | MyType& operator<<(var_int64_t x) { return this->operator<<(x.t); } 7 | MyType& operator<<(var_uint64_t x) { return this->operator<<(x.t); } 8 | #endif 9 | 10 | MyType& operator<<(serialize_version_t x) { return this->operator<<(x.t); } 11 | 12 | //----------------------------------------------------------------------------------- 13 | MyType& operator<<(var_int30_t x) { return this->operator<<(x.t); } 14 | MyType& operator<<(var_uint30_t x) { return this->operator<<(x.t); } 15 | 16 | #if !defined(BOOST_NO_INT64_T) 17 | MyType& operator<<(var_int61_t x) { return this->operator<<(x.t); } 18 | MyType& operator<<(var_uint61_t x) { return this->operator<<(x.t); } 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /src/nark/io/DataOutput_VarIntAsVarLen.hpp: -------------------------------------------------------------------------------- 1 | public: 2 | #ifdef NARK_DATA_IO_SLOW_VAR_INT 3 | 4 | MyType& operator<<(var_int32_t x) 5 | { 6 | byte buf[5]; 7 | this->ensureWrite(buf, save_var_int32(buf, x.t) - buf); 8 | return *this; 9 | } 10 | 11 | MyType& operator<<(var_uint32_t x) 12 | { 13 | byte buf[5]; 14 | this->ensureWrite(buf, save_var_uint32(buf, x.t) - buf); 15 | return *this; 16 | } 17 | 18 | #if !defined(BOOST_NO_INT64_T) 19 | MyType& operator<<(var_int64_t x) 20 | { 21 | byte buf[9]; 22 | this->ensureWrite(buf, save_var_int64(buf, x.t) - buf); 23 | return *this; 24 | } 25 | MyType& operator<<(var_uint64_t x) 26 | { 27 | byte buf[9]; 28 | this->ensureWrite(buf, save_var_uint64(buf, x.t) - buf); 29 | return *this; 30 | } 31 | #endif 32 | MyType& operator<<(serialize_version_t x) 33 | { 34 | byte buf[5]; 35 | this->ensureWrite(buf, save_var_uint32(buf, x.t) - buf); 36 | return *this; 37 | } 38 | #else // NARK_DATA_IO_SLOW_VAR_INT 39 | // fast var_*int* 40 | MyType& operator<<(var_int32_t x) 41 | { 42 | this->getStream()->write_var_int32(x); 43 | return *this; 44 | } 45 | 46 | MyType& operator<<(var_uint32_t x) 47 | { 48 | this->getStream()->write_var_uint32(x); 49 | return *this; 50 | } 51 | 52 | #if !defined(BOOST_NO_INT64_T) 53 | MyType& operator<<(var_int64_t x) 54 | { 55 | this->getStream()->write_var_int64(x); 56 | return *this; 57 | } 58 | MyType& operator<<(var_uint64_t x) 59 | { 60 | this->getStream()->write_var_uint64(x); 61 | return *this; 62 | } 63 | #endif 64 | MyType& operator<<(serialize_version_t x) 65 | { 66 | this->getStream()->write_var_uint32(x.t); 67 | return *this; 68 | } 69 | #endif // NARK_DATA_IO_SLOW_VAR_INT 70 | 71 | //-------------------------------------------------------- 72 | MyType& operator<<(var_int30_t x) 73 | { 74 | this->getStream()->write_var_int30(x); 75 | return *this; 76 | } 77 | 78 | MyType& operator<<(var_uint30_t x) 79 | { 80 | this->getStream()->write_var_uint30(x); 81 | return *this; 82 | } 83 | 84 | #if !defined(BOOST_NO_INT64_T) 85 | MyType& operator<<(var_int61_t x) 86 | { 87 | this->getStream()->write_var_int61(x); 88 | return *this; 89 | } 90 | MyType& operator<<(var_uint61_t x) 91 | { 92 | this->getStream()->write_var_uint61(x); 93 | return *this; 94 | } 95 | #endif 96 | 97 | -------------------------------------------------------------------------------- /src/nark/io/FileDataIO.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __nark_FileDataIO_hpp__ 2 | #define __nark_FileDataIO_hpp__ 3 | 4 | #include "DataIO.hpp" 5 | #include "FileStream.hpp" 6 | #include "StreamBuffer.hpp" 7 | 8 | namespace nark { 9 | template 10 | class FileDataInput : public DataIO { 11 | public: 12 | FileStream file; 13 | FileDataInput(const char* fname) : file(fname, "rb") { 14 | this->attach(&file); 15 | } 16 | }; 17 | template 18 | class FileDataOutput : public DataIO { 19 | public: 20 | FileStream file; 21 | FileDataOutput(const char* fname) : file(fname, "wb") { 22 | this->attach(&file); 23 | } 24 | ~FileDataOutput() { 25 | this->flush(); 26 | this->attach(NULL); 27 | } 28 | }; 29 | 30 | typedef FileDataInput > NativeFileDataInput; 31 | typedef FileDataOutput > NativeFileDataOutput; 32 | typedef FileDataInput > PortableFileDataInput; 33 | typedef FileDataOutput > PortableFileDataOutput; 34 | 35 | typedef FileDataInput > BigEndianFileDataInput; 36 | typedef FileDataOutput > BigEndianFileDataOutput; 37 | typedef FileDataInput > LittleEndianFileDataInput; 38 | typedef FileDataOutput > LittleEndianFileDataOutput; 39 | } 40 | 41 | #endif // __nark_FileDataIO_hpp__ 42 | 43 | -------------------------------------------------------------------------------- /src/nark/io/FileStream.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/src/nark/io/FileStream.hpp -------------------------------------------------------------------------------- /src/nark/io/GzipStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "GzipStream.hpp" 3 | 4 | #include 5 | #include 6 | 7 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 8 | # include 9 | # if 1 //ZLIB_VERNUM >= 0x1240 10 | # pragma comment(lib, "zlibwapi.lib") 11 | # else 12 | # pragma comment(lib, "zlib.lib") 13 | # endif 14 | #else 15 | # include 16 | # include 17 | # include 18 | # include 19 | # include 20 | #endif 21 | 22 | #if defined(__CYGWIN__) || defined(__CYGWIN32__) 23 | # define off64_t _off64_t 24 | #endif 25 | 26 | //#define ZLIB_DLL 27 | #define ZLIB_WINAPI 28 | #include 29 | #include // for sprintf and EOF 30 | 31 | #include "byte_io_impl.hpp" 32 | 33 | #ifndef ZLIB_VERNUM 34 | # error "ZLIB_VERNUM is not defined" 35 | #endif 36 | 37 | #include 38 | 39 | namespace nark { 40 | 41 | void GzipStreamBase::ThrowOpenFileException(const char* fpath, const char* mode) 42 | { 43 | string_appender<> oss; 44 | oss << "mode=" << mode; 45 | throw OpenFileException(fpath, oss.str().c_str()); 46 | } 47 | 48 | // only can call on unopened GzipInputStream 49 | void GzipStreamBase::open(const char* fpath, const char* mode) 50 | { 51 | assert(0 == m_fp); 52 | m_fp = gzopen(fpath, mode); 53 | if (0 == m_fp) 54 | ThrowOpenFileException(fpath, mode); 55 | } 56 | 57 | bool GzipStreamBase::xopen(const char* fpath, const char* mode) 58 | { 59 | assert(0 == m_fp); 60 | m_fp = gzopen(fpath, mode); 61 | return 0 != m_fp; 62 | } 63 | 64 | void GzipStreamBase::dopen(int fd, const char* mode) 65 | { 66 | assert(0 == m_fp); 67 | m_fp = gzdopen(fd, mode); 68 | if (0 == m_fp) 69 | { 70 | char szbuf[64]; 71 | sprintf(szbuf, "fd=%d", fd); 72 | ThrowOpenFileException(szbuf, mode); 73 | } 74 | } 75 | 76 | void GzipStreamBase::close() 77 | { 78 | assert(m_fp); 79 | gzclose((gzFile)m_fp); 80 | m_fp = 0; 81 | } 82 | 83 | GzipStreamBase::~GzipStreamBase() 84 | { 85 | if (m_fp) 86 | gzclose((gzFile)m_fp); 87 | } 88 | 89 | /////////////////////////////////////////////////////////////////////////////////////// 90 | 91 | GzipInputStream::GzipInputStream(const char* fpath, const char* mode) 92 | { 93 | m_fp = 0; 94 | open(fpath, mode); 95 | } 96 | 97 | GzipInputStream::GzipInputStream(int fd, const char* mode) 98 | { 99 | m_fp = 0; 100 | dopen(fd, mode); 101 | } 102 | 103 | bool GzipInputStream::eof() const 104 | { 105 | return !!gzeof((gzFile)m_fp); 106 | } 107 | 108 | size_t GzipInputStream::read(void* buf, size_t size) throw() 109 | { 110 | assert(m_fp); 111 | return gzread((gzFile)m_fp, buf, size); 112 | } 113 | 114 | NARK_GEN_ensureRead (GzipInputStream::) 115 | 116 | /////////////////////////////////////////////////////// 117 | 118 | GzipOutputStream::GzipOutputStream(const char* fpath, const char* mode) 119 | { 120 | m_fp = 0; 121 | open(fpath, mode); 122 | } 123 | 124 | GzipOutputStream::GzipOutputStream(int fd, const char* mode) 125 | { 126 | m_fp = 0; 127 | dopen(fd, mode); 128 | } 129 | 130 | void GzipOutputStream::flush() 131 | { 132 | assert(m_fp); 133 | if (gzflush((gzFile)m_fp, Z_SYNC_FLUSH) == EOF) 134 | throw DelayWriteException(BOOST_CURRENT_FUNCTION); 135 | } 136 | 137 | size_t GzipOutputStream::write(const void* buf, size_t size) throw() 138 | { 139 | assert(m_fp); 140 | return gzwrite((gzFile)m_fp, buf, size); 141 | } 142 | NARK_GEN_ensureWrite(GzipOutputStream::) 143 | 144 | } // namespace nark 145 | 146 | -------------------------------------------------------------------------------- /src/nark/io/GzipStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_GzipStream_h__ 3 | #define __nark_io_GzipStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include "IOException.hpp" 12 | #include "IStream.hpp" 13 | 14 | namespace nark { 15 | 16 | class NARK_DLL_EXPORT GzipStreamBase : public RefCounter 17 | { 18 | protected: 19 | void* m_fp; 20 | void ThrowOpenFileException(const char* fpath, const char* mode); 21 | 22 | public: 23 | GzipStreamBase() : m_fp(0) {} 24 | virtual ~GzipStreamBase(); 25 | 26 | bool isOpen() const { return 0 != m_fp; } 27 | 28 | void open(const char* fpath, const char* mode); 29 | bool xopen(const char* fpath, const char* mode); 30 | void dopen(int fd, const char* mode); 31 | void close(); 32 | }; 33 | 34 | class NARK_DLL_EXPORT GzipInputStream : public IInputStream, public GzipStreamBase 35 | { 36 | DECLARE_NONE_COPYABLE_CLASS(GzipInputStream) 37 | 38 | public: 39 | explicit GzipInputStream(const char* fpath, const char* mode = "rb"); 40 | explicit GzipInputStream(int fd, const char* mode = "rb"); 41 | GzipInputStream() throw() {} 42 | 43 | bool eof() const; 44 | 45 | void ensureRead(void* vbuf, size_t length); 46 | size_t read(void* buf, size_t size) throw(); 47 | }; 48 | 49 | class NARK_DLL_EXPORT GzipOutputStream : public IOutputStream, public GzipStreamBase 50 | { 51 | DECLARE_NONE_COPYABLE_CLASS(GzipOutputStream) 52 | 53 | public: 54 | explicit GzipOutputStream(const char* fpath, const char* mode = "wb"); 55 | explicit GzipOutputStream(int fd, const char* mode = "wb"); 56 | GzipOutputStream() throw() {} 57 | 58 | void ensureWrite(const void* vbuf, size_t length); 59 | size_t write(const void* buf, size_t size) throw(); 60 | void flush(); 61 | }; 62 | 63 | } // namespace nark 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /src/nark/io/HexCodingStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "HexCodingStream.hpp" 3 | #include "DataInput.hpp" 4 | #include 5 | 6 | namespace nark { 7 | 8 | // '0' == 0x30 9 | // 'a' == 0x61 10 | // 'A' == 0x41 11 | const unsigned char G_hex_val_hexTab[] = 12 | { 13 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 14 | 255, 255, 255, 255, 255, 255, 15 | // below, begin with '0' + 16 = 0x40 16 | 255, 17 | 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 18 | 255, 255, 255, 255, 255, 19 | 255, 255, 255, 255, 255, 20 | // below, begin with 'A' + 16 = 0x51 21 | 255, 255, 255, 255, 22 | 255, 255, 255, 255, 23 | 255, 255, 255, 255, 24 | 255, 255, 255, 255, 25 | // below, begin with 'a' = 0x61 26 | 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 27 | }; 28 | 29 | void invalid_hex_char(unsigned char ch, const char* func) 30 | { 31 | string_appender<> oss; 32 | oss << "invalid hex char(ch=" << char(ch) << ",ascii=" << int(ch) << ") in func: " << func; 33 | throw DataFormatException(oss.str()); 34 | } 35 | 36 | } // namespace nark 37 | -------------------------------------------------------------------------------- /src/nark/io/HexCodingStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_HexCodingStream_h__ 3 | #define __nark_io_HexCodingStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | //#include 11 | #include 12 | #include 13 | #include 14 | #include "IOException.hpp" 15 | #include "MemStream.hpp" 16 | #include 17 | 18 | namespace nark { 19 | 20 | extern const unsigned char G_hex_val_hexTab[]; 21 | 22 | void invalid_hex_char(unsigned char ch, const char* func); 23 | 24 | inline unsigned char hex_val(unsigned char ch, const char* func) 25 | { 26 | if (ch < '0' || ch >= 'f') 27 | invalid_hex_char(ch, func); 28 | unsigned char hv = G_hex_val_hexTab[ch-'0']; 29 | if (255 == hv) 30 | invalid_hex_char(ch, func); 31 | return hv; 32 | } 33 | 34 | inline unsigned char hex_val(unsigned char ch) 35 | { 36 | return hex_val(ch, BOOST_CURRENT_FUNCTION); 37 | } 38 | 39 | template 40 | class HexCodingStream 41 | { 42 | ByteStream* m_bs; 43 | 44 | unsigned char do_readByte(const char* func) 45 | { 46 | unsigned char h4 = m_bs->readByte(); 47 | unsigned char l4 = m_bs->readByte(); 48 | 49 | return hex_val(h4, func) << 4 | hex_val(l4, func); 50 | } 51 | 52 | public: 53 | typedef typename ByteStream::is_seekable is_seekable; 54 | 55 | explicit HexCodingStream(ByteStream* bs) : m_bs(bs) {} 56 | 57 | bool eof() const throw() { return m_bs->eof(); } 58 | void flush() { m_bs->flush(); } 59 | 60 | unsigned char readByte() 61 | { 62 | return do_readByte(BOOST_CURRENT_FUNCTION); 63 | } 64 | int getByte() 65 | { 66 | try { 67 | return do_readByte(BOOST_CURRENT_FUNCTION); 68 | } catch (const EndOfFileException& exp) { 69 | return -1; 70 | } 71 | } 72 | void writeByte(unsigned char b) 73 | { 74 | const char hexChar[] = "0123456789ABCDEF"; 75 | m_bs->writeByte(hexChar[b >> 4]); 76 | m_bs->writeByte(hexChar[b & 15]); 77 | } 78 | void ensureRead(void* data, size_t length) 79 | { 80 | unsigned char* pb = (unsigned char*)(data); 81 | while (length) 82 | { 83 | *pb = do_readByte(BOOST_CURRENT_FUNCTION); 84 | pb++; length--; 85 | } 86 | } 87 | void ensureWrite(const void* data, size_t length) 88 | { 89 | const unsigned char* pb = (const unsigned char*)(data); 90 | while (length) 91 | { 92 | writeByte(*pb); 93 | pb++; length--; 94 | } 95 | } 96 | size_t read(void* data, size_t length) 97 | { 98 | unsigned char* pb = (unsigned char*)(data); 99 | try { 100 | while (length) 101 | { 102 | *pb = do_readByte(BOOST_CURRENT_FUNCTION); 103 | pb++; length--; 104 | } 105 | } catch (const EndOfFileException& exp) { 106 | // ignore 107 | } 108 | return pb - (unsigned char*)(data); 109 | } 110 | size_t write(const void* data, size_t length) 111 | { 112 | const unsigned char* pb = (const unsigned char*)(data); 113 | try { 114 | while (length) 115 | { 116 | writeByte(*pb); 117 | pb++; length--; 118 | } 119 | } catch (const OutOfSpaceException&) { 120 | // ignore 121 | } 122 | return pb - (unsigned char*)(data); 123 | } 124 | }; 125 | 126 | //class AutoGrownMemIO; // declare 127 | typedef HexCodingStream HexAutoGrownMemIO; 128 | 129 | template 130 | DstStream& bin_dump_hex(SrcStream& src, DstStream& dst) 131 | { 132 | const size_t buf_len = 4*1024; 133 | DataBufferPtr data_buf(buf_len); 134 | AutoGrownMemIO hex_buf(2*buf_len); 135 | HexCodingStream hexMS(&hex_buf); 136 | try { 137 | while (true) 138 | { 139 | size_t len = src.read(data_buf->data(), buf_len); 140 | if (len) { 141 | hex_buf.seek(0); 142 | hexMS.write(data_buf->data(), len); 143 | dst.write((char*)hex_buf.buf(), 2*len); 144 | } else 145 | break; 146 | } 147 | } catch (EndOfFileException&) { 148 | // ignore... 149 | } 150 | return dst; 151 | } 152 | 153 | template 154 | class bin_dump_hex_manip 155 | { 156 | SrcStream& m_src; 157 | 158 | public: 159 | explicit bin_dump_hex_manip(SrcStream& src) : m_src(src) {} 160 | 161 | friend std::ostream& operator<<(std::ostream& os, bin_dump_hex_manip x) 162 | { 163 | bin_dump_hex(x.m_src, os); 164 | return os; 165 | } 166 | }; 167 | 168 | template 169 | bin_dump_hex_manip 170 | bin_dump_hex(SrcStream& src) 171 | { 172 | return bin_dump_hex_manip(src); 173 | } 174 | 175 | } // namespace nark 176 | 177 | #endif 178 | 179 | -------------------------------------------------------------------------------- /src/nark/io/IOException.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "IOException.hpp" 3 | #include 4 | 5 | #include 6 | 7 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 8 | # include 9 | #else 10 | # include 11 | #endif 12 | 13 | namespace nark { 14 | 15 | IOException::IOException(const char* szMsg) 16 | : m_message(szMsg), m_errCode(lastError()) 17 | { 18 | m_message += ": "; 19 | m_message += errorText(m_errCode); 20 | } 21 | 22 | IOException::IOException(const std::string& msg) 23 | : m_message(msg), m_errCode(lastError()) 24 | { 25 | m_message += ": "; 26 | m_message += errorText(m_errCode); 27 | } 28 | 29 | IOException::IOException(int errCode, const char* szMsg) 30 | : m_message(szMsg), m_errCode(errCode) 31 | { 32 | m_message += ": "; 33 | m_message += errorText(m_errCode); 34 | } 35 | 36 | int IOException::lastError() 37 | { 38 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 39 | return ::GetLastError(); 40 | #else 41 | return errno; 42 | #endif 43 | } 44 | 45 | std::string IOException::errorText(int errCode) 46 | { 47 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 48 | HLOCAL hLocal = NULL; 49 | DWORD dwTextLength = FormatMessageA( 50 | FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 51 | NULL, 52 | errCode, 53 | 0, //MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) 54 | (LPSTR)&hLocal, 55 | 0, 56 | NULL 57 | ); 58 | string_appender<> oss; 59 | LPCSTR pszMsg = (LPCSTR)LocalLock(hLocal); 60 | oss << "error[code=" << errCode << ", message=" << pszMsg << "]"; 61 | LocalFree(hLocal); 62 | #else 63 | string_appender<> oss; 64 | oss << "error[code=" << errCode << ", message=" << ::strerror(errCode) << "]"; 65 | #endif 66 | return oss.str(); 67 | } 68 | 69 | ////////////////////////////////////////////////////////////////////////// 70 | 71 | OpenFileException::OpenFileException(const char* path, const char* szMsg) 72 | : IOException(szMsg), m_path(path) 73 | { 74 | m_message += ": "; 75 | m_message += m_path; 76 | } 77 | 78 | } // namespace nark 79 | -------------------------------------------------------------------------------- /src/nark/io/IOException.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_IOException_h__ 3 | #define __nark_io_IOException_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace nark { 14 | 15 | #if defined(_MSC_VER) 16 | // non dll-interface class 'std::exception' used as base for dll-interface 17 | #pragma warning(push) 18 | #pragma warning(disable:4275) 19 | #endif 20 | class NARK_DLL_EXPORT IOException : public std::exception 21 | { 22 | protected: 23 | std::string m_message; 24 | int m_errCode; 25 | public: 26 | explicit IOException(const char* szMsg = "nark::IOException"); 27 | explicit IOException(const std::string& msg); 28 | explicit IOException(int errCode, const char* szMsg = "nark::IOException"); 29 | virtual ~IOException() throw() {} 30 | 31 | const char* what() const throw() { return m_message.c_str(); } 32 | int errCode() const throw() { return m_errCode; } 33 | 34 | static int lastError(); 35 | static std::string errorText(int errCode); 36 | }; 37 | #if defined(_MSC_VER) 38 | #pragma warning(pop) 39 | #endif 40 | 41 | class NARK_DLL_EXPORT OpenFileException : public IOException 42 | { 43 | std::string m_path; 44 | public: 45 | explicit OpenFileException(const char* path, const char* szMsg = "nark::OpenFileException"); 46 | explicit OpenFileException(const std::string& msg) : IOException(msg) {} 47 | ~OpenFileException() throw() {} 48 | }; 49 | 50 | // blocked streams read 0 bytes will cause this exception 51 | // other streams read not enough maybe cause this exception 52 | // all streams read 0 bytes will cause this exception 53 | class NARK_DLL_EXPORT EndOfFileException : public IOException 54 | { 55 | public: 56 | explicit EndOfFileException(const char* szMsg = "nark::EndOfFileException") 57 | : IOException(szMsg) 58 | { } 59 | explicit EndOfFileException(const std::string& msg) : IOException(msg) {} 60 | }; 61 | 62 | class NARK_DLL_EXPORT OutOfSpaceException : public IOException 63 | { 64 | public: 65 | explicit OutOfSpaceException(const char* szMsg = "nark::OutOfSpaceException") 66 | : IOException(szMsg) 67 | { } 68 | explicit OutOfSpaceException(const std::string& msg) : IOException(msg) {} 69 | }; 70 | 71 | class NARK_DLL_EXPORT DelayWriteException : public IOException 72 | { 73 | public: 74 | DelayWriteException(const char* szMsg = "nark::DelayWriteException") 75 | : IOException(szMsg) 76 | { } 77 | DelayWriteException(const std::string& msg) : IOException(msg) {} 78 | // size_t streamPosition; 79 | }; 80 | 81 | class NARK_DLL_EXPORT BrokenPipeException : public IOException 82 | { 83 | public: 84 | BrokenPipeException(const char* szMsg = "nark::BrokenPipeException") 85 | : IOException(szMsg) 86 | { } 87 | BrokenPipeException(const std::string& msg) : IOException(msg) {} 88 | }; 89 | 90 | 91 | } // namespace nark 92 | 93 | #endif // __nark_io_IOException_h__ 94 | -------------------------------------------------------------------------------- /src/nark/io/IStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "IStream.hpp" 3 | #include 4 | 5 | namespace nark { 6 | 7 | ISeekable::~ISeekable() 8 | { 9 | } 10 | /* 11 | stream_position_t ISeekable::size() 12 | { 13 | stream_position_t old_pos = tell(); 14 | seek(0, 2); // seek to end 15 | stream_position_t nsize = tell(); 16 | seek(old_pos); 17 | return nsize; 18 | } 19 | */ 20 | void ISeekable::rewind() 21 | { 22 | this->seek(0); 23 | } 24 | 25 | void ISeekable::seek(stream_position_t position) 26 | { 27 | seek(stream_offset_t(position), 0); 28 | } 29 | 30 | 31 | IAcceptor::~IAcceptor() 32 | { 33 | 34 | } 35 | 36 | ///////////////////////////////////////////////////// 37 | // 38 | 39 | IInputStream::~IInputStream() 40 | { 41 | } 42 | 43 | IOutputStream::~IOutputStream() 44 | { 45 | } 46 | 47 | //////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | size_t ISeekableInputStream::pread(stream_position_t pos, void* vbuf, size_t length) 50 | { 51 | stream_position_t old = this->tell(); 52 | this->seek(pos); 53 | size_t n = this->read(vbuf, length); 54 | this->seek(old); 55 | return n; 56 | } 57 | 58 | size_t ISeekableOutputStream::pwrite(stream_position_t pos, const void* vbuf, size_t length) 59 | { 60 | stream_position_t old = this->tell(); 61 | this->seek(pos); 62 | size_t n = this->write(vbuf, length); 63 | this->seek(old); 64 | return n; 65 | } 66 | 67 | size_t ISeekableStream::pread(stream_position_t pos, void* vbuf, size_t length) 68 | { 69 | stream_position_t old = this->tell(); 70 | this->seek(pos); 71 | size_t nread = this->read(vbuf, length); 72 | this->seek(old); 73 | return nread; 74 | } 75 | size_t ISeekableStream::pwrite(stream_position_t pos, const void* vbuf, size_t length) 76 | { 77 | stream_position_t old = this->tell(); 78 | this->seek(pos); 79 | size_t n = this->write(vbuf, length); 80 | this->seek(old); 81 | return n; 82 | } 83 | 84 | 85 | /////////////////////////////////////////////////////// 86 | // 87 | #if defined(__GLIBC__) || defined(__CYGWIN__) 88 | 89 | ssize_t 90 | OutputStream_write(void *cookie, const char *buf, size_t size) 91 | { 92 | IOutputStream* output = (IOutputStream*)cookie; 93 | return output->write(buf, size); 94 | } 95 | 96 | ssize_t 97 | InputStream_read(void *cookie, char *buf, size_t size) 98 | { 99 | IInputStream* input = (IInputStream*)cookie; 100 | return input->read(buf, size); 101 | } 102 | 103 | /** 104 | * @note must call fclose after use of returned FILE 105 | */ 106 | FILE* IInputStream::forInputFILE() 107 | { 108 | cookie_io_functions_t func = { 109 | InputStream_read, 110 | NULL, 111 | NULL, 112 | NULL 113 | }; 114 | assert(this); 115 | void* cookie = this; 116 | FILE* fp = fopencookie(cookie,"r", func); 117 | if (fp == NULL) { 118 | perror("fopencookie@IInputStream::forInputFILE"); 119 | return NULL; 120 | } 121 | return fp; 122 | } 123 | 124 | /** 125 | * @note must call fclose after use of returned FILE 126 | */ 127 | FILE* IOutputStream::forOutputFILE() 128 | { 129 | cookie_io_functions_t func = { 130 | NULL, 131 | OutputStream_write, 132 | NULL, 133 | NULL 134 | }; 135 | assert(this); 136 | void* cookie = this; 137 | FILE* fp = fopencookie(cookie,"w", func); 138 | if (fp == NULL) { 139 | perror("fopencookie@IOutputStream::forOutputFILE"); 140 | return NULL; 141 | } 142 | return fp; 143 | } 144 | 145 | #endif 146 | 147 | 148 | } // namespace nark 149 | 150 | -------------------------------------------------------------------------------- /src/nark/io/IStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_IStream_h__ 3 | #define __nark_io_IStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include // for getFILE 11 | #include 12 | 13 | namespace nark { 14 | 15 | class NARK_DLL_EXPORT ISeekable 16 | { 17 | public: 18 | typedef boost::mpl::true_ is_seekable; 19 | 20 | virtual ~ISeekable(); 21 | virtual void rewind(); 22 | virtual void seek(stream_position_t position); 23 | virtual void seek(stream_offset_t offset, int origin) = 0; 24 | virtual stream_position_t tell() const = 0; 25 | virtual stream_position_t size() const = 0; 26 | }; 27 | 28 | class NARK_DLL_EXPORT IInputStream 29 | { 30 | public: 31 | typedef boost::mpl::false_ is_seekable; 32 | 33 | virtual ~IInputStream(); 34 | 35 | virtual size_t read(void* vbuf, size_t length) = 0; 36 | 37 | /** 38 | @brief End Of File 39 | 40 | only InputStream has eof() mark, OutputStream does not have eof() 41 | */ 42 | virtual bool eof() const = 0; 43 | 44 | #if defined(__GLIBC__) || defined(__CYGWIN__) 45 | FILE* forInputFILE(); 46 | #endif 47 | }; 48 | 49 | class NARK_DLL_EXPORT IOutputStream 50 | { 51 | public: 52 | typedef boost::mpl::false_ is_seekable; 53 | 54 | virtual ~IOutputStream(); 55 | 56 | virtual size_t write(const void* vbuf, size_t length) = 0; 57 | virtual void flush() = 0; 58 | 59 | #if defined(__GLIBC__) || defined(__CYGWIN__) 60 | FILE* forOutputFILE(); 61 | #endif 62 | }; 63 | 64 | class NARK_DLL_EXPORT IDuplexStream : public IInputStream, public IOutputStream 65 | { 66 | public: 67 | typedef boost::mpl::false_ is_seekable; 68 | }; 69 | 70 | class NARK_DLL_EXPORT ISeekableInputStream : public ISeekable, public IInputStream 71 | { 72 | public: 73 | typedef boost::mpl::true_ is_seekable; 74 | virtual size_t pread(stream_position_t pos, void* vbuf, size_t length); 75 | }; 76 | class NARK_DLL_EXPORT ISeekableOutputStream : public ISeekable, public IOutputStream 77 | { 78 | public: 79 | typedef boost::mpl::true_ is_seekable; 80 | virtual size_t pwrite(stream_position_t pos, const void* vbuf, size_t length); 81 | }; 82 | class NARK_DLL_EXPORT ISeekableStream : public ISeekable, public IInputStream, public IOutputStream 83 | { 84 | public: typedef boost::mpl::true_ is_seekable; 85 | virtual size_t pread(stream_position_t pos, void* vbuf, size_t length); 86 | virtual size_t pwrite(stream_position_t pos, const void* vbuf, size_t length); 87 | }; 88 | 89 | class NARK_DLL_EXPORT IAcceptor 90 | { 91 | public: 92 | virtual ~IAcceptor(); 93 | virtual IDuplexStream* accept() = 0; 94 | }; 95 | 96 | } // namespace nark 97 | 98 | #endif 99 | 100 | -------------------------------------------------------------------------------- /src/nark/io/MemMapStream.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/src/nark/io/MemMapStream.hpp -------------------------------------------------------------------------------- /src/nark/io/RangeStream.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __nark_io_stream_range_hpp__ 3 | #define __nark_io_stream_range_hpp__ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | //#include 10 | #include 11 | #include "var_int.hpp" 12 | #include "var_int_inline.hpp" 13 | 14 | namespace nark { 15 | 16 | template 17 | class RangeStream : public Stream { 18 | size_t m_len; 19 | 20 | public: 21 | RangeStream() { m_len = 0; } 22 | void setRangeLen(size_t len) { m_len = len; } 23 | bool eof() const { return 0 == m_len; } 24 | int getByte() { 25 | assert(m_len > 0); 26 | m_len--; 27 | return Stream::getByte(); 28 | } 29 | byte readByte() { 30 | assert(m_len > 0); 31 | m_len--; 32 | return Stream::readByte(); 33 | } 34 | void ensureRead(void* vbuf, size_t length) { 35 | assert(length <= m_len); 36 | Stream::ensureRead(vbuf, length); 37 | m_len -= length; 38 | } 39 | size_t read(void* vbuf, size_t length) { 40 | size_t ret = Stream::read(vbuf, length); 41 | m_len -= ret; 42 | return ret; 43 | } 44 | 45 | template 46 | void readAll(ByteArray& ba) { 47 | BOOST_STATIC_ASSERT(sizeof(ba[0]) == 1); 48 | ba.resize(m_len); 49 | if (m_len) { 50 | // must be a continuous memory block 51 | assert(&*ba.begin() + m_len == &*(ba.end()-1) + 1); 52 | Stream::ensureRead(&*ba.begin(), ba.size()); 53 | m_len = 0; 54 | } 55 | } 56 | 57 | uint32_t read_var_uint32() { return gg_load_var_uint_slow(*this, BOOST_CURRENT_FUNCTION); } 58 | uint32_t read_var_uint30() { return gg_load_var_uint30_slow(*this); } 59 | uint64_t read_var_uint64() { return gg_load_var_uint_slow(*this, BOOST_CURRENT_FUNCTION); } 60 | uint64_t read_var_uint61() { return gg_load_var_uint61_slow(*this); } 61 | int32_t read_var_int32() { return var_int32_u2s(read_var_uint32()); } 62 | int32_t read_var_int30() { return var_int30_u2s(read_var_uint30()); } 63 | int64_t read_var_int64() { return var_int64_u2s(read_var_uint64()); } 64 | int64_t read_var_int61() { return var_int61_u2s(read_var_uint61()); } 65 | 66 | void read_string(std::string& s) { 67 | size_t len = NARK_IF_WORD_BITS_64(read_var_uint64, read_var_uint32)(); 68 | s.resize(len); 69 | if (len) 70 | this->ensureRead(&*s.begin(), len); 71 | } 72 | }; 73 | 74 | template 75 | class RestAllTpl { 76 | public: 77 | RestAllTpl(T& x) : p(&x) {} 78 | 79 | private: 80 | T* p; 81 | 82 | template 83 | static 84 | typename boost::enable_if_cbegin()) != 0, void>::type 85 | dioLoad(DataIO& dio, ByteArray& ba) { 86 | BOOST_STATIC_ASSERT(sizeof(ba[0]) == 1); 87 | dio.readAll(ba); 88 | assert(dio.eof()); 89 | } 90 | template 91 | static 92 | typename boost::disable_if_cbegin()) != 0, void>::type 93 | dioLoad(DataIO& dio, U& x) { dio >> x; } 94 | 95 | template 96 | static 97 | typename boost::enable_if_cbegin()) != 0, void>::type 98 | dioSave(DataIO& dio, const ByteArray& ba) { 99 | BOOST_STATIC_ASSERT(sizeof(ba[0]) == 1); 100 | dio.ensureWrite(ba.data(), ba.size()); 101 | } 102 | template 103 | static 104 | typename boost::disable_if_cbegin()) != 0, void>::type 105 | dioSave(DataIO& dio, const U& x) { dio << x; } 106 | 107 | template 108 | friend void DataIO_loadObject(DataIO& dio, RestAllTpl x) { 109 | dioLoad(dio, *x.p); 110 | } 111 | 112 | template 113 | friend void DataIO_saveObject(DataIO& dio, RestAllTpl x) { 114 | dioSave(dio, *x.p); 115 | } 116 | }; 117 | 118 | template RestAllTpl RestAll(T& t) { return t; } 119 | 120 | } // namespace nark 121 | 122 | #endif __nark_io_stream_range_hpp__ 123 | -------------------------------------------------------------------------------- /src/nark/io/ZcMemMap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/src/nark/io/ZcMemMap.cpp -------------------------------------------------------------------------------- /src/nark/io/ZcMemMap.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_ZcMemMap_h__ 3 | #define __nark_io_ZcMemMap_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | //#include 10 | #include 11 | #include // for memcpy 12 | 13 | #include 14 | #include "IStream.hpp" 15 | #include "ZeroCopy.hpp" 16 | 17 | //#include 18 | #include 19 | #include 20 | #include 21 | 22 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 23 | # include 24 | # include 25 | # include 26 | # include 27 | # include 28 | #else 29 | # include 30 | # include 31 | # include 32 | # include 33 | # include 34 | # include 35 | #endif 36 | 37 | namespace nark { 38 | 39 | class NARK_DLL_EXPORT ZcMemMap 40 | : public IZeroCopyInputStream 41 | , public IZeroCopyOutputStream 42 | , public ISeekable 43 | { 44 | DECLARE_NONE_COPYABLE_CLASS(ZcMemMap) 45 | 46 | public: 47 | typedef boost::mpl::true_ is_seekable; 48 | 49 | static void ThrowOpenFileException(const char* fpath, int mode); 50 | 51 | public: 52 | ZcMemMap(stream_position_t new_file_size, const std::string& fpath, int mode); 53 | ZcMemMap(); 54 | ~ZcMemMap(); 55 | 56 | bool is_open() const throw(); 57 | void open(stream_position_t new_file_size, const std::string& fpath, int mode); 58 | void clone(const ZcMemMap& source); 59 | void close(); 60 | 61 | bool eof() const; 62 | 63 | size_t zcRead(const void** ppbuf, size_t length); 64 | size_t zcWrite(void** ppbuf, size_t length); 65 | 66 | void zcFlush(size_t nWritten); 67 | 68 | void seek(stream_offset_t offset, int origin); 69 | void seek(stream_position_t pos); 70 | stream_position_t tell() const; 71 | stream_position_t size() const; 72 | 73 | void remap(stream_position_t aligned_fpos, size_t unaligned_size); 74 | bool try_remap(stream_position_t aligned_fpos, size_t unaligned_size); 75 | void unaligned_remap(stream_position_t unaligned_fpos, size_t unaligned_size); 76 | 77 | void set_fsize(stream_position_t fsize); 78 | 79 | void* map(stream_position_t fpos, size_t size); 80 | void* map(stream_position_t fpos, size_t size, int mode); 81 | void unmap(void* base, size_t size); 82 | 83 | size_t page_size() const { return m_page_size; } 84 | size_t best_block_size() const { return m_best_block_size; } 85 | void set_best_block_size(size_t n) { m_best_block_size = n; } 86 | 87 | const std::string& fpath() const { return m_fpath; } 88 | 89 | // int errcode() const throw() { return m_errno; } 90 | // std::string errmsg() const throw(); 91 | 92 | int file_handle() const { return (int)(size_t)m_hFile; } 93 | 94 | void align(stream_position_t* fpos, size_t* size) 95 | { 96 | stream_position_t base_off = align_down(*fpos, m_page_size); 97 | *size = align_up(*fpos - base_off + *size, m_page_size); 98 | *fpos = base_off; 99 | } 100 | 101 | protected: 102 | unsigned char* m_beg; 103 | unsigned char* m_pos; 104 | unsigned char* m_end; 105 | 106 | #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) 107 | HANDLE m_hFile; 108 | HANDLE m_hMap; 109 | #else 110 | int m_hFile; 111 | #endif 112 | 113 | int m_mode; 114 | // int m_errno; 115 | 116 | stream_position_t m_file_size; 117 | stream_position_t m_file_pos; 118 | 119 | size_t m_best_block_size; 120 | size_t m_page_size; 121 | size_t m_AllocationGranularity; 122 | std::string m_fpath; 123 | 124 | void init(); 125 | void init(stream_position_t new_file_size, const std::string& fpath, int mode); 126 | 127 | stream_position_t get_fsize(); 128 | 129 | bool remap_impl(stream_position_t fpos, size_t size); 130 | 131 | void cleanup_and_throw(const char* msg); 132 | }; 133 | 134 | 135 | 136 | } // namespace nark 137 | 138 | #endif 139 | 140 | -------------------------------------------------------------------------------- /src/nark/io/ZeroCopy.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "ZeroCopy.hpp" 3 | #include "IOException.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(_MSC_VER) 9 | #pragma warning(disable:4819) 10 | #include 11 | #pragma intrinsic(_BitScanReverse) 12 | //#pragma intrinsic(_BitScanReverse64) 13 | #endif 14 | 15 | #include 16 | #if BOOST_VERSION < 103301 17 | # include 18 | # include 19 | #else 20 | # include 21 | #endif 22 | 23 | #include "var_int.hpp" 24 | 25 | namespace nark { 26 | 27 | //////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | // 29 | 30 | using namespace std; // for min, max 31 | 32 | IZeroCopyInputStream::~IZeroCopyInputStream() 33 | { 34 | 35 | } 36 | 37 | IZeroCopyOutputStream::~IZeroCopyOutputStream() 38 | { 39 | 40 | } 41 | 42 | 43 | size_t ZcReader::fill_and_read(void* vbuf, size_t length) 44 | { 45 | assert(NULL != m_is); 46 | assert(0 != m_bufsize); 47 | return do_fill_and_read(vbuf, length); 48 | } 49 | 50 | // this function should not inline 51 | size_t ZcReader::do_fill_and_read(void* vbuf, size_t length) 52 | { 53 | // assert(length != 0); 54 | // assert(m_pos + length > m_end); 55 | assert(NULL != m_is); 56 | assert(0 != m_bufsize); 57 | 58 | if (nark_unlikely(NULL == m_is)) 59 | { 60 | throw std::invalid_argument("(NULL==m_is) in ZcReader::do_fill_and_read"); 61 | } 62 | 63 | size_t n1 = m_end - m_pos; // remain bytes in buffer 64 | size_t n2 = length - n1; // remain bytes to read 65 | 66 | memcpy(vbuf, m_pos, n1); // read data remain inbuf 67 | 68 | while (n2 > 0) 69 | { 70 | size_t toRead = max(n2, m_bufsize); 71 | size_t readed; 72 | m_beg = (unsigned char*)m_is->zcRead(toRead, &readed); 73 | if (nark_unlikely(0 == readed)) { 74 | if (0 == n1) { // eof before this call `do_fill_and_read` 75 | char szMsg[128]; 76 | sprintf(szMsg, "ZcReader::do_fill_and_read, 1 read 0 byte, n1=%lld, n2=%lld" 77 | , (long long)n1 78 | , (long long)n2 79 | ); 80 | throw EndOfFileException(szMsg); 81 | } 82 | else { 83 | m_beg = m_pos = m_end = NULL; 84 | return n1; 85 | } 86 | } 87 | size_t n3 = min(n2, readed); 88 | memcpy((byte*)vbuf + n1, m_beg, n3); 89 | n2 -= n3; 90 | n1 += n3; 91 | m_pos = m_beg + n3; 92 | m_end = m_beg + readed; 93 | } 94 | assert(n1 == length); 95 | return length; 96 | } 97 | 98 | // this function should not inline 99 | void ZcReader::fill_and_ensureRead(void* vbuf, size_t length) 100 | { 101 | assert(NULL != m_is); 102 | assert(0 != m_bufsize); 103 | size_t n = do_fill_and_read(vbuf, length); 104 | if (nark_unlikely(n != length)) 105 | { 106 | char szbuf[256]; 107 | sprintf(szbuf, "\"%s\", ReadBytes[want=%lld, read=%lld]" 108 | , BOOST_CURRENT_FUNCTION 109 | , (long long)length 110 | , (long long)n 111 | ); 112 | throw EndOfFileException(szbuf); 113 | } 114 | } 115 | 116 | // this function should not inline 117 | byte ZcReader::fill_and_read_byte() 118 | { 119 | assert(NULL != m_is); 120 | assert(0 != m_bufsize); 121 | byte b; 122 | if (nark_likely(do_fill_and_read(&b, 1))) 123 | return b; 124 | else 125 | throw EndOfFileException(BOOST_CURRENT_FUNCTION); 126 | } 127 | 128 | /** 129 | @brief 检测是否真的到了 eof 130 | 131 | 在 fileptr 到达文件末尾但之前的一次 fread(buf,1,len,fp)==len 时, 132 | feof(fp) 返回 false,并非应该预期的 true 133 | 所以,在这里,做一次真实的判断,看是否的确到了 eof 134 | 135 | @note 136 | -# 只有当 m_pos == m_end 时,该函数才会被调用 137 | */ 138 | int ZcReader::test_eof() 139 | { 140 | // 只有当 m_pos == m_end 时,该函数才会被调用 141 | assert(m_pos == m_end); 142 | assert(NULL != m_is); 143 | assert(0 != m_bufsize); 144 | 145 | if (nark_unlikely(0 == m_is)) 146 | return 1; 147 | 148 | try { 149 | byte tmp; 150 | if (nark_likely(do_fill_and_read(&tmp, 1))) { 151 | // readed 1 byte 152 | assert(m_beg + 1 == m_pos); 153 | m_pos = m_beg; // push_back this byte 154 | return 0; 155 | } else 156 | return 1; 157 | } 158 | catch (const EndOfFileException&) 159 | { 160 | return 1; 161 | } 162 | } 163 | 164 | void ZcReader::getline(std::string& line, size_t maxlen) 165 | { 166 | assert(NULL != m_is); 167 | assert(0 != m_bufsize); 168 | 169 | line.resize(0); 170 | size_t len = 0; 171 | for (;;) 172 | { 173 | for (byte* p = m_pos; ; ++p, ++len) 174 | { 175 | if (nark_unlikely(len == maxlen)) 176 | { 177 | line.append((char*)m_pos, (char*)p); 178 | assert(line.size() == len); 179 | m_pos = p; 180 | return; 181 | } 182 | if (nark_unlikely(p == m_end)) 183 | { 184 | line.append((char*)m_pos, (char*)m_end); 185 | assert(line.size() == len); 186 | 187 | size_t nRead; 188 | m_beg = (unsigned char*)m_is->zcRead(m_bufsize, &nRead); 189 | m_end = m_beg + nRead; 190 | m_pos = m_beg; 191 | if (0 == nRead) 192 | { 193 | if (line.empty()) 194 | throw EndOfFileException("ZcReader::getline, read 0 byte"); 195 | else { 196 | m_pos = m_end = m_beg = NULL; 197 | return; 198 | } 199 | } 200 | break; 201 | } 202 | // 换行有三种,在这里都支持 203 | // 1. "\r\n" 204 | // 2. "\r" 205 | // 3. "\n" 206 | if (nark_unlikely('\r' == *p)) 207 | { 208 | line.append((char*)m_pos, (char*)p); 209 | assert(line.size() == len); 210 | 211 | // m_pos move to next char point by p, maybe p+1 == m_end 212 | m_pos = p + 1; 213 | 214 | // 如果下一个字符是换行,就直接吃掉它 215 | // 如果是文件末尾,直接返回 216 | try { 217 | int nextCh = readByte(); 218 | if ('\n' != nextCh) 219 | // not line feed, push back the byte 220 | --m_pos; 221 | } 222 | catch (const EndOfFileException&) { 223 | // ignore 224 | } 225 | return; 226 | } 227 | if (nark_unlikely('\n' == *p)) 228 | { 229 | line.append((char*)m_pos, (char*)p); 230 | assert(line.size() == len); 231 | m_pos = p + 1; 232 | return; 233 | } 234 | } 235 | } 236 | } 237 | 238 | ////////////////////////////////////////////////////////////////////////////////// 239 | ////////////////////////////////////////////////////////////////////////////////// 240 | 241 | ZcWriter::~ZcWriter() 242 | { 243 | flush(); 244 | } 245 | 246 | size_t ZcWriter::flush_and_write(const void* vbuf, size_t length) 247 | { 248 | assert(NULL != m_os); 249 | return do_flush_and_write(vbuf, length); 250 | } 251 | 252 | void ZcWriter::flush_and_ensureWrite(const void* vbuf, size_t length) 253 | { 254 | assert(NULL != m_os); 255 | size_t n = do_flush_and_write(vbuf, length); 256 | if (n != length) 257 | { 258 | char szbuf[256]; 259 | sprintf(szbuf, "\"%s\", WriteBytes[want=%lld, read=%lld]" 260 | , BOOST_CURRENT_FUNCTION 261 | , (long long)length 262 | , (long long)n 263 | ); 264 | throw OutOfSpaceException(szbuf); 265 | } 266 | } 267 | 268 | void ZcWriter::flush_and_write_byte(byte b) 269 | { 270 | assert(NULL != m_os); 271 | assert(m_pos == m_end); 272 | do_flush_and_write(&b, 1); 273 | } 274 | 275 | size_t ZcWriter::do_flush_and_write(const void* vbuf, size_t length) 276 | { 277 | assert(NULL != m_os); 278 | 279 | size_t n1 = m_end - m_pos; // remain bytes in buffer 280 | size_t n2 = length - n1; // remain bytes to read 281 | 282 | memcpy(m_pos, vbuf, n1); // write data to available space remain inbuf 283 | 284 | while (n2 > 0) 285 | { 286 | size_t toWrite = max(n2, m_bufsize); 287 | size_t writable; 288 | m_beg = (unsigned char*)m_os->zcWrite(toWrite, &writable); 289 | if (nark_unlikely(0 == writable)) { 290 | char szMsg[128]; 291 | sprintf(szMsg, "ZcWriter::do_flush_and_write, 1 write 0 byte, n1=%u, n2=%u", (unsigned)n1, (unsigned)n2); 292 | throw DelayWriteException(szMsg); 293 | // throw BrokenPipeException(szMsg); 294 | } 295 | size_t n3 = min(n2, writable); 296 | memcpy(m_beg, (byte*)vbuf + n1, n3); 297 | n2 -= n3; 298 | n1 += n3; 299 | m_pos = m_beg + n3; 300 | m_end = m_beg + writable; 301 | } 302 | assert(n1 == length); 303 | return length; 304 | } 305 | 306 | void ZcWriter::flush() 307 | { 308 | assert(NULL != m_os); 309 | m_os->zcFlush(m_pos - m_beg); 310 | } 311 | 312 | #define STREAM_READER ZcReader 313 | #define STREAM_WRITER ZcWriter 314 | #include "var_int_io.hpp" 315 | 316 | } // namespace nark 317 | 318 | -------------------------------------------------------------------------------- /src/nark/io/ZeroCopy.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_ZeroCopy_h__ 3 | #define __nark_io_ZeroCopy_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include // for getFILE 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace nark { 18 | 19 | class NARK_DLL_EXPORT IZeroCopyInputStream 20 | { 21 | public: 22 | typedef boost::mpl::false_ is_seekable; 23 | 24 | virtual ~IZeroCopyInputStream(); 25 | 26 | /** 27 | * get readbuffer for zero copy 28 | */ 29 | virtual const void* zcRead(size_t length, size_t* readed) = 0; 30 | 31 | /** 32 | @brief End Of File 33 | 34 | only InputStream has eof() mark, OutputStream does not have eof() 35 | */ 36 | virtual bool eof() const = 0; 37 | }; 38 | 39 | class NARK_DLL_EXPORT IZeroCopyOutputStream 40 | { 41 | public: 42 | typedef boost::mpl::false_ is_seekable; 43 | 44 | virtual ~IZeroCopyOutputStream(); 45 | 46 | /** 47 | * get write buffer for zero copy 48 | */ 49 | virtual void* zcWrite(size_t length, size_t* writable) = 0; 50 | 51 | /** 52 | * after last zcWrite, caller may be not have written the whole buffer 53 | * zcFlush tells the Stream how many bytes has actual written, 54 | * next zcWrite will get the unwritten buffer lies in last buffer end. 55 | */ 56 | virtual void zcFlush(size_t nWritten) = 0; 57 | }; 58 | 59 | class NARK_DLL_EXPORT ZeroCopyBase 60 | { 61 | protected: 62 | unsigned char* m_beg; 63 | unsigned char* m_pos; 64 | unsigned char* m_end; 65 | size_t m_bufsize; 66 | 67 | void init(size_t bufsize) 68 | { 69 | m_beg = NULL; 70 | m_pos = NULL; 71 | m_end = NULL; 72 | m_bufsize = bufsize; 73 | } 74 | 75 | public: 76 | typedef boost::mpl::false_ is_seekable; 77 | 78 | ptrdiff_t buf_remain_bytes() const { return m_end - m_pos; } 79 | }; 80 | 81 | class NARK_DLL_EXPORT ZcReader : public ZeroCopyBase 82 | { 83 | IZeroCopyInputStream* m_is; 84 | 85 | public: 86 | explicit ZcReader(IZeroCopyInputStream* stream = NULL, size_t bufsize = BUFSIZ) 87 | { 88 | attach(stream, BUFSIZ); 89 | } 90 | 91 | void attach(IZeroCopyInputStream* stream, size_t bufsize = BUFSIZ) 92 | { 93 | init(bufsize); 94 | m_is = stream; 95 | } 96 | 97 | bool eof() { return m_pos == m_end && test_eof(); } 98 | 99 | /** 100 | * @return actually readed bytes, never return 0 101 | * - if actually readed bytes is 0, throw EndOfFileException 102 | */ 103 | size_t read(void* vbuf, size_t length) 104 | { 105 | if (nark_likely(m_pos+length <= m_end)) { 106 | memcpy(vbuf, m_pos, length); 107 | m_pos += length; 108 | return length; 109 | } else 110 | return fill_and_read(vbuf, length); 111 | } 112 | 113 | /** 114 | * always read requested bytes, or throw EndOfFileException 115 | */ 116 | void ensureRead(void* vbuf, size_t length) 117 | { 118 | // 为了效率,这么实现可以让编译器更好地 inline 这个函数 119 | // inline 后的函数体并尽可能小 120 | if (nark_likely(m_pos+length <= m_end)) { 121 | memcpy(vbuf, m_pos, length); 122 | m_pos += length; 123 | } else 124 | fill_and_ensureRead(vbuf, length); 125 | } 126 | 127 | byte readByte() 128 | { 129 | if (nark_likely(m_pos < m_end)) 130 | return *m_pos++; 131 | else 132 | return fill_and_read_byte(); 133 | } 134 | 135 | void getline(std::string& line, size_t maxlen = UINT_MAX); 136 | 137 | #include "var_int_declare_read.hpp" 138 | 139 | protected: 140 | size_t fill_and_read(void* vbuf, size_t length); 141 | void fill_and_ensureRead(void* vbuf, size_t length); 142 | byte fill_and_read_byte(); 143 | int test_eof(); 144 | 145 | size_t do_fill_and_read(void* vbuf, size_t length); 146 | }; 147 | 148 | class NARK_DLL_EXPORT ZcWriter : public ZeroCopyBase 149 | { 150 | IZeroCopyOutputStream* m_os; 151 | 152 | public: 153 | explicit ZcWriter(IZeroCopyOutputStream* stream = NULL, size_t bufsize = BUFSIZ) 154 | { 155 | attach(stream, BUFSIZ); 156 | } 157 | ~ZcWriter(); 158 | 159 | void attach(IZeroCopyOutputStream* stream, size_t bufsize = BUFSIZ) 160 | { 161 | init(bufsize); 162 | m_os = stream; 163 | } 164 | 165 | void flush(); 166 | 167 | size_t write(const void* vbuf, size_t length) 168 | { 169 | if (nark_likely(m_pos+length <= m_end)) { 170 | memcpy(m_pos, vbuf, length); 171 | m_pos += length; 172 | return length; 173 | } else 174 | return flush_and_write(vbuf, length); 175 | } 176 | 177 | void ensureWrite(const void* vbuf, size_t length) 178 | { 179 | // 为了效率,这么实现可以让编译器更好地 inline 这个函数 180 | // inline 后的函数体并尽可能小 181 | if (nark_likely(m_pos+length <= m_end)) { 182 | memcpy(m_pos, vbuf, length); 183 | m_pos += length; 184 | } else 185 | flush_and_ensureWrite(vbuf, length); 186 | } 187 | 188 | void writeByte(byte b) 189 | { 190 | if (nark_likely(m_pos < m_end)) 191 | *m_pos++ = b; 192 | else 193 | flush_and_write_byte(b); 194 | } 195 | 196 | size_t printf(const char* format, ...) 197 | #ifdef __GNUC__ 198 | __attribute__ ((__format__ (__printf__, 2, 3))) 199 | #endif 200 | ; 201 | 202 | size_t vprintf(const char* format, va_list ap) 203 | #ifdef __GNUC__ 204 | __attribute__ ((__format__ (__printf__, 2, 0))) 205 | #endif 206 | ; 207 | 208 | #include "var_int_declare_write.hpp" 209 | 210 | protected: 211 | size_t flush_and_write(const void* vbuf, size_t length); 212 | void flush_and_ensureWrite(const void* vbuf, size_t length); 213 | void flush_and_write_byte(byte b); 214 | 215 | size_t do_flush_and_write(const void* vbuf, size_t length); 216 | }; 217 | 218 | 219 | } // namespace nark 220 | 221 | #endif 222 | 223 | -------------------------------------------------------------------------------- /src/nark/io/avro.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_avro_h__ 3 | #define __nark_io_avro_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include "DataIO.hpp" 10 | #include "../hash_strmap.hpp" 11 | 12 | namespace nark { 13 | 14 | template 15 | class AvroDataInput : public StreamT { 16 | public: 17 | AvroDataInput& operator>>(var_size_t& x) { 18 | var_int64_t y; 19 | *this >> y; 20 | x.t = y.t; 21 | return *this; 22 | } 23 | AvroDataInput& operator>>(std::string& x) { 24 | var_int64_t len; 25 | *this >> len; 26 | load(&x[0], len.t); 27 | return *this; 28 | } 29 | template 30 | AvroDataInput& operator>>(std::vector& x) { 31 | var_int64_t len; 32 | *this >> len; 33 | x.resize(len.t); 34 | load(&x[0], len.t); 35 | return *this; 36 | } 37 | template 38 | AvroDataInput& operator>>(std::vector& x) { 39 | var_int64_t len; 40 | size_t pos = 0; 41 | x.resize(0); 42 | do { 43 | *this >> len; 44 | load(&x[0], len.t); 45 | if (len < 0) { 46 | len.t = -len.t; 47 | var_int64_t bytes_of_block; 48 | *this >> bytes_of_block; // skip bytes_of_block 49 | } 50 | x.resize(pos + len.t); 51 | DataIO_load_array(*this, &x[pos], len.t, DATA_IO_BSWAP_FOR_LITTLE(T)); 52 | pos += len.t; 53 | } while (len.t); 54 | return *this; 55 | } 56 | template 57 | AvroDataInput& operator>>(hash_strmap& x) { 58 | x.clear(); 59 | std::string key; 60 | Value val; 61 | var_int64_t len; 62 | do { 63 | *this >> len; 64 | if (len < 0) { 65 | len = -len; 66 | var_int64_t bytes_of_block; 67 | *this >> bytes_of_block; // skip bytes_of_block 68 | } 69 | for (size_t i = 0, n = len.t; i != n; ++i) { 70 | *this >> key; 71 | *this >> val; 72 | std::pair ib = x.insert_i(key, val); 73 | if (!ib.second) { 74 | throw std::runtime_error("duplicate key"); 75 | } 76 | } 77 | } while (len.t); 78 | return *this; 79 | } 80 | }; 81 | 82 | template 83 | class AvroDataOutput : public StreamT { 84 | public: 85 | AvroDataOutput& operator<<(const var_size_t x) { 86 | var_int64_t y(x.t); 87 | *this << y; 88 | return *this; 89 | } 90 | AvroDataOutput& operator<<(const std::string& x) { 91 | fstring y(x); 92 | return *this << y; 93 | } 94 | AvroDataOutput& operator<<(const fstring x) { 95 | var_int64_t len(x.n); 96 | *this << len; 97 | save(x.p, len.t); 98 | return *this; 99 | } 100 | template 101 | AvroDataInput& operator<<(const std::vector& x) { 102 | var_int64_t len(x.size()); 103 | *this << len; 104 | load(&x[0], len.t); 105 | return *this; 106 | } 107 | template 108 | AvroDataInput& operator<<(const std::vector& x) { 109 | var_int64_t len(x.size()); 110 | *this << len; 111 | DataIO_save_array(*this, &x[0], len.t, DATA_IO_BSWAP_FOR_LITTLE(T)); 112 | *this << byte(0); // var_int64_t(0) 113 | return *this; 114 | } 115 | template 116 | AvroDataOutput& operator<<(const hash_strmap& x) { 117 | var_int64_t len(x.size); 118 | *this << len; 119 | if (x.delcnt()) { 120 | for (size_t i = 0, n = x.end_i(); i != n; i = x.next_i(i)) { 121 | if (!x.is_deleted()) { 122 | *this << x.key(i); 123 | *this << x.val(i); 124 | } 125 | } 126 | } 127 | else { 128 | for (size_t i = 0, n = x.end_i(); i != n; ++i) { 129 | *this << x.key(i); 130 | *this << x.val(i); 131 | } 132 | } 133 | *this << byte(0); // var_int64_t(0) 134 | return *this; 135 | } 136 | }; 137 | 138 | } // namespace nark::avro 139 | 140 | #endif // __nark_io_avro_h__ 141 | 142 | -------------------------------------------------------------------------------- /src/nark/io/byte_io_impl.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_byte_io_impl_h__ 3 | #define __nark_io_byte_io_impl_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | // #include "IOException.hpp" 10 | 11 | #define BYTE_IO_EMPTY 12 | 13 | #define NARK_GEN_ensureRead(prefix) \ 14 | void prefix ensureRead(void* vbuf, size_t length) \ 15 | { \ 16 | size_t n = this->read(vbuf, length); \ 17 | if (n != length) \ 18 | { \ 19 | string_appender<> oss; \ 20 | oss << "\"" << BOOST_CURRENT_FUNCTION << "\"" \ 21 | << ", ReadBytes[want=" << length << ", read=" << n << "]"; \ 22 | throw EndOfFileException(oss.str().c_str()); \ 23 | } \ 24 | } 25 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | 27 | #define NARK_GEN_ensureWrite(prefix) \ 28 | void prefix ensureWrite(const void* vbuf, size_t length) \ 29 | { \ 30 | size_t n = this->write(vbuf, length); \ 31 | if (n != length) \ 32 | { \ 33 | string_appender<> oss; \ 34 | oss << "\"" << BOOST_CURRENT_FUNCTION << "\"" \ 35 | << ", WriteBytes[want=" << length << ", written=" << n << "]"; \ 36 | throw OutOfSpaceException(oss.str().c_str()); \ 37 | } \ 38 | } 39 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 40 | 41 | #define NARK_GEN_getByte(prefix) \ 42 | int prefix getByte() \ 43 | { \ 44 | unsigned char b; \ 45 | if (this->read(&b, 1) == 0) \ 46 | return -1; \ 47 | return b; \ 48 | } 49 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 50 | 51 | #define NARK_GEN_readByte(prefix) \ 52 | unsigned char prefix readByte() \ 53 | { \ 54 | unsigned char b; \ 55 | if (this->read(&b, 1) == 0) \ 56 | throw EndOfFileException(BOOST_CURRENT_FUNCTION); \ 57 | return b; \ 58 | } 59 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60 | 61 | #define NARK_GEN_writeByte(prefix) \ 62 | void prefix writeByte(unsigned char b) \ 63 | { \ 64 | if (this->write(&b, 1) == 0) \ 65 | throw OutOfSpaceException(BOOST_CURRENT_FUNCTION); \ 66 | } 67 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | /* 70 | namespace nark { 71 | 72 | template 73 | class InputStream_Method_Impl 74 | { 75 | public: 76 | unsigned char readByte() 77 | { 78 | unsigned char b; 79 | if (static_cast(*this).read(&b, 1) == 0) 80 | throw EndOfFileException(BOOST_CURRENT_FUNCTION); 81 | return b; 82 | } 83 | 84 | void ensureRead(void* vbuf, size_t length) 85 | { 86 | size_t n = static_cast(*this).read(vbuf, length); 87 | if (n != length) 88 | { 89 | string_appender<> oss; 90 | oss << "\"" << BOOST_CURRENT_FUNCTION << "\"" 91 | << ", ReadBytes[want=" << length << ", read=" << n << "]"; 92 | throw EndOfFileException(oss.str().c_str()); 93 | } 94 | } 95 | }; 96 | 97 | template 98 | class OutputStream_Method_Impl 99 | { 100 | public: 101 | void writeByte(unsigned char b) 102 | { 103 | if (static_cast(*this).write(&b, 1) == 0) 104 | throw OutOfSpaceException(BOOST_CURRENT_FUNCTION); 105 | } 106 | 107 | void ensureWrite(const void* vbuf, size_t length) 108 | { 109 | size_t n = static_cast(*this).write(vbuf, length); 110 | if (n != length) 111 | { 112 | string_appender<> oss; 113 | oss << "\"" << BOOST_CURRENT_FUNCTION << "\"" 114 | << ", WriteBytes[want=" << length << ", written=" << n << "]"; 115 | throw OutOfSpaceException(oss.str().c_str()); 116 | } 117 | } 118 | }; 119 | 120 | template 121 | class ByteIoImplement : 122 | public InputStream_Method_Impl, 123 | public OutputStream_Method_Impl 124 | { 125 | public: 126 | }; 127 | 128 | } // namespace nark 129 | */ 130 | 131 | #endif 132 | 133 | -------------------------------------------------------------------------------- /src/nark/io/byte_swap.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_byte_swap_h__ 3 | #define __nark_io_byte_swap_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | # pragma warning(disable: 4127) 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace nark { 16 | 17 | // inline void byte_swap_in(float&) {} 18 | // inline void byte_swap_in(double&) {} 19 | // inline void byte_swap_in(long double&) {} 20 | // inline void byte_swap_in(char&) {} 21 | // inline void byte_swap_in(signed char&) {} 22 | // inline void byte_swap_in(unsigned char&) {} 23 | 24 | inline void byte_swap_in(unsigned short& x, boost::mpl::true_) 25 | { 26 | x = byte_swap(x); 27 | } 28 | inline void byte_swap_in(short& x, boost::mpl::true_) 29 | { 30 | x = byte_swap(x); 31 | } 32 | 33 | inline void byte_swap_in(unsigned int& i, boost::mpl::true_) 34 | { 35 | i = byte_swap(i); 36 | } 37 | inline void byte_swap_in(int& i, boost::mpl::true_) 38 | { 39 | i = byte_swap((unsigned int)i); 40 | } 41 | inline void byte_swap_in(float& i, boost::mpl::true_) 42 | { 43 | BOOST_STATIC_ASSERT(sizeof(float) == sizeof(unsigned int)); 44 | *(unsigned int*)&i = byte_swap(*(unsigned int*)&i); 45 | } 46 | #if defined(BOOST_HAS_LONG_LONG) 47 | inline void byte_swap_in(unsigned long long& i, boost::mpl::true_) 48 | { 49 | i = byte_swap(i); 50 | } 51 | inline void byte_swap_in(long long& i, boost::mpl::true_) 52 | { 53 | i = byte_swap((unsigned long long)(i)); 54 | } 55 | inline void byte_swap_in(double& i, boost::mpl::true_) 56 | { 57 | BOOST_STATIC_ASSERT(sizeof(double) == sizeof(unsigned long long)); 58 | *(unsigned long long*)&i = byte_swap(*(unsigned long long*)&i); 59 | } 60 | #elif defined(BOOST_HAS_MS_INT64) 61 | inline void byte_swap_in(unsigned __int64& i, boost::mpl::true_) 62 | { 63 | i = byte_swap(i); 64 | } 65 | inline void byte_swap_in(__int64& i, boost::mpl::true_) 66 | { 67 | i = byte_swap((unsigned __int64)(i)); 68 | } 69 | inline void byte_swap_in(double& i, boost::mpl::true_) 70 | { 71 | BOOST_STATIC_ASSERT(sizeof(double) == sizeof(unsigned __int64)); 72 | *(unsigned __int64*)&i = byte_swap(*(unsigned __int64*)&i); 73 | } 74 | #endif 75 | /** 76 | * Don't support 77 | inline void byte_swap_in(long double& i, boost::mpl::true_) 78 | { 79 | } 80 | */ 81 | 82 | #if ULONG_MAX == 0xffffffff 83 | inline void byte_swap_in(unsigned long& x, boost::mpl::true_) 84 | { 85 | x = byte_swap((unsigned int)x); 86 | } 87 | inline void byte_swap_in(long& x, boost::mpl::true_) 88 | { 89 | x = byte_swap((unsigned int)x); 90 | } 91 | #else 92 | inline void byte_swap_in(unsigned long& x, boost::mpl::true_) 93 | { 94 | x = byte_swap((unsigned long long)x); 95 | } 96 | inline void byte_swap_in(long& x, boost::mpl::true_) 97 | { 98 | x = byte_swap((unsigned long long)x); 99 | } 100 | #endif // ULONG_MAX 101 | 102 | template 103 | void byte_swap_in(T (&a)[Dim], boost::mpl::true_) 104 | { 105 | for (int i = 0; i < Dim; ++i) 106 | byte_swap_in(a[i], boost::mpl::true_()); 107 | } 108 | 109 | template 110 | void byte_swap_in(T&, boost::mpl::false_) 111 | { 112 | // do nothing 113 | } 114 | 115 | typedef boost::mpl::true_ ByteSwap_true; 116 | typedef boost::mpl::false_ ByteSwap_false; 117 | 118 | ////////////////////////////////////////////////////////////////////////// 119 | // DataIO_need_bswap 120 | #if defined(BOOST_TYPEOF_NATIVE) 121 | #ifdef BOOST_TYPEOF_KEYWORD 122 | #define NARK_TYPEOF_KEYWORD BOOST_TYPEOF_KEYWORD 123 | #else 124 | #define NARK_TYPEOF_KEYWORD decltype 125 | #endif 126 | template 127 | struct WorkAround_typeof : T {}; 128 | template 129 | ByteSwap_true Deduce_DataIO_need_bswap(T*); 130 | template 131 | struct DataIO_need_bswap : 132 | public WorkAround_typeof< 133 | NARK_TYPEOF_KEYWORD(Deduce_DataIO_need_bswap((T*)NULL)) 134 | > {}; 135 | #else 136 | template 137 | struct DataIO_need_bswap : public boost::mpl::true_ { }; 138 | #endif 139 | #define DATA_IO_NEED_BYTE_SWAP(T, cbool) \ 140 | template<> struct DataIO_need_bswap : public boost::mpl::bool_ {}; 141 | 142 | DATA_IO_NEED_BYTE_SWAP( char, false) 143 | DATA_IO_NEED_BYTE_SWAP( signed char, false) 144 | DATA_IO_NEED_BYTE_SWAP(unsigned char, false) 145 | //DATA_IO_NEED_BYTE_SWAP( float, false) 146 | //DATA_IO_NEED_BYTE_SWAP( double, false) 147 | //DATA_IO_NEED_BYTE_SWAP( long double, false) 148 | 149 | template 150 | struct DataIO_need_bswap > : public 151 | boost::mpl::bool_::value||DataIO_need_bswap::value> 152 | { 153 | }; 154 | 155 | template 156 | void byte_swap_in(std::pair& x, typename DataIO_need_bswap >::type) 157 | { 158 | byte_swap_in(x.first, typename DataIO_need_bswap::type()); 159 | byte_swap_in(x.second, typename DataIO_need_bswap::type()); 160 | } 161 | 162 | template 163 | class ByteSwapChain; 164 | 165 | // only boost::mpl::true_ is applied 166 | template<> class ByteSwapChain 167 | { 168 | public: 169 | template ByteSwapChain operator&(T& x) const 170 | { 171 | // BOOST_STATIC_ASSERT(DataIO_need_bswap::value); 172 | byte_swap_in(x, typename DataIO_need_bswap::type()); 173 | return *this; 174 | } 175 | }; 176 | 177 | template 178 | void byte_swap(T* p, size_t n) 179 | { 180 | for (size_t i = n; i; --i, ++p) 181 | byte_swap_in(*p, boost::mpl::true_()); 182 | } 183 | 184 | template 185 | void byte_swap(Iter first, Iter last) 186 | { 187 | for (; first != last; ++first) 188 | byte_swap_in(*first, boost::mpl::true_()); 189 | } 190 | 191 | inline void byte_swap(char* /*buffer*/, size_t /*length*/) { } 192 | inline void byte_swap(signed char* /*buffer*/, size_t /*length*/) { } 193 | inline void byte_swap(unsigned char* /*buffer*/, size_t /*length*/) { } 194 | 195 | } // namespace nark 196 | 197 | //#include 198 | 199 | #endif // __nark_io_byte_swap_h__ 200 | 201 | 202 | -------------------------------------------------------------------------------- /src/nark/io/discard/ConcurrentStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __ConcurrentStream_h__ 3 | #define __ConcurrentStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | 12 | namespace nark { 13 | 14 | template 15 | class ConcurrentStreamWrapper : public StreamClass 16 | { 17 | ConcurrentStreamWrapper(const ConcurrentStreamWrapper&); 18 | ConcurrentStreamWrapper& operator=(const ConcurrentStreamWrapper&); 19 | protected: 20 | boost::mutex m_mutex; 21 | public: 22 | ConcurrentStreamWrapper() {} 23 | 24 | template 25 | ConcurrentStreamWrapper(T1 p1) : StreamClass(p1) {} 26 | template 27 | ConcurrentStreamWrapper(T1 p1, T2 p2) : StreamClass(p1, p2) {} 28 | template 29 | ConcurrentStreamWrapper(T1 p1, T2 p2, T3 p3) : StreamClass(p1, p2, p3) {} 30 | 31 | int getByte() 32 | { 33 | boost::mutex::scoped_lock lock(m_mutex) 34 | return StreamClass::getByte(); 35 | } 36 | unsigned char readByte() 37 | { 38 | boost::mutex::scoped_lock lock(m_mutex) 39 | return StreamClass::readByte(); 40 | } 41 | void writeByte(unsigned char b) 42 | { 43 | boost::mutex::scoped_lock lock(m_mutex) 44 | return StreamClass::writeByte(b); 45 | } 46 | size_t read(void* data, size_t length) 47 | { 48 | boost::mutex::scoped_lock lock(m_mutex) 49 | return StreamClass::read(data, length); 50 | } 51 | size_t write(const void* data, size_t length) 52 | { 53 | boost::mutex::scoped_lock lock(m_mutex) 54 | return StreamClass::write(data, length); 55 | } 56 | void flush() 57 | { 58 | boost::mutex::scoped_lock lock(m_mutex) 59 | StreamClass::flush(); 60 | } 61 | bool eof() 62 | { 63 | boost::mutex::scoped_lock lock(m_mutex) 64 | return StreamClass::eof(); 65 | } 66 | 67 | bool seek(size_t newPos) 68 | { 69 | boost::mutex::scoped_lock lock(m_mutex) 70 | return StreamClass::seek(newPos); 71 | } 72 | bool seek(long offset, int origin) 73 | { 74 | boost::mutex::scoped_lock lock(m_mutex) 75 | return StreamClass::seek(offset, origin); 76 | } 77 | size_t tell() 78 | { 79 | boost::mutex::scoped_lock lock(m_mutex) 80 | return StreamClass::tell(); 81 | } 82 | 83 | // for divided dual IO 84 | bool seekp(size_t newPos) 85 | { 86 | boost::mutex::scoped_lock lock(m_mutex) 87 | return StreamClass::seekp(newPos); 88 | } 89 | bool seekp(long offset, int origin) 90 | { 91 | boost::mutex::scoped_lock lock(m_mutex) 92 | return StreamClass::seekp(offset, origin); 93 | } 94 | size_t tellp() 95 | { 96 | boost::mutex::scoped_lock lock(m_mutex) 97 | return StreamClass::tellp(); 98 | } 99 | bool seekg(size_t newPos) 100 | { 101 | boost::mutex::scoped_lock lock(m_mutex) 102 | return StreamClass::seekg(newPos); 103 | } 104 | bool seekg(long offset, int origin) 105 | { 106 | boost::mutex::scoped_lock lock(m_mutex) 107 | return StreamClass::seekg(offset, origin); 108 | } 109 | size_t tellg() 110 | { 111 | boost::mutex::scoped_lock lock(m_mutex) 112 | return StreamClass::tellg(); 113 | } 114 | }; 115 | 116 | } // namespace nark 117 | 118 | #endif // __ConcurrentStream_h__ 119 | 120 | -------------------------------------------------------------------------------- /src/nark/io/discard/DataInput.cpp: -------------------------------------------------------------------------------- 1 | #include "DataInput.hpp" 2 | 3 | namespace nark { 4 | 5 | namespace serialization { namespace polymorphic { 6 | 7 | 8 | } } // serialization::polymorphic 9 | 10 | } // namespace nark 11 | -------------------------------------------------------------------------------- /src/nark/io/discard/custom_int.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_custom_int_h__ 3 | #define __nark_io_custom_int_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // should be the last #include 14 | #include 15 | 16 | namespace nark { 17 | 18 | template 19 | class custom_int 20 | { 21 | BaseInt m_val; 22 | BOOST_STATIC_ASSERT(Bits % 8 == 0); 23 | public: 24 | typedef BaseInt presentation_type; 25 | BOOST_STATIC_CONSTANT(int, bits = Bits); 26 | BOOST_STATIC_CONSTANT(int, bytes = Bits / 8); 27 | 28 | custom_int(BaseInt val = BaseInt()) : m_val(val % (BaseInt(1) << Bits)) {} 29 | 30 | operator BaseInt() const { return m_val; } 31 | 32 | BaseInt& value() { return m_val; } 33 | BaseInt value() const { return m_val; } 34 | 35 | #define NARK_custom_int_gen_operator(op) \ 36 | BaseInt operator op(custom_int y) const { return m_val op y.m_val; } 37 | 38 | NARK_custom_int_gen_operator(+) 39 | NARK_custom_int_gen_operator(-) 40 | NARK_custom_int_gen_operator(*) 41 | NARK_custom_int_gen_operator(/) 42 | NARK_custom_int_gen_operator(%) 43 | NARK_custom_int_gen_operator(^) 44 | NARK_custom_int_gen_operator(&) 45 | NARK_custom_int_gen_operator(|) 46 | NARK_custom_int_gen_operator(<<) 47 | NARK_custom_int_gen_operator(>>) 48 | 49 | #undef NARK_custom_int_gen_operator 50 | 51 | bool operator&&(custom_int y) const { return m_val && y.m_val; } 52 | bool operator||(custom_int y) const { return m_val || y.m_val; } 53 | bool operator!() const { return !m_val; } 54 | 55 | BaseInt operator~() const { return ~m_val; } 56 | BaseInt operator-() const { return -m_val; } 57 | 58 | custom_int operator+() const { return +m_val; } 59 | 60 | custom_int operator++() { return m_val = ++m_val % (BaseInt(1) << Bits); } 61 | custom_int operator--() { return m_val = --m_val % (BaseInt(1) << Bits); } 62 | 63 | custom_int operator++(int) 64 | { 65 | BaseInt t = m_val; 66 | m_val = ++m_val % (BaseInt(1) << Bits); 67 | return t; 68 | } 69 | custom_int operator--(int) 70 | { 71 | BaseInt t = m_val; 72 | m_val = --m_val % (BaseInt(1) << Bits); 73 | return t; 74 | } 75 | 76 | #define NARK_custom_int_gen_assign_op(op)\ 77 | custom_int& operator op(custom_int y) \ 78 | { m_val op y; \ 79 | m_val %= (BaseInt(1) << Bits); \ 80 | return *this; \ 81 | } 82 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | NARK_custom_int_gen_assign_op(+=) 84 | NARK_custom_int_gen_assign_op(-=) 85 | NARK_custom_int_gen_assign_op(*=) 86 | #undef NARK_custom_int_gen_assign_op 87 | 88 | // not need: "m_val %= (BaseInt(1) << Bits);" 89 | #define NARK_custom_int_gen_assign_op(op)\ 90 | custom_int& operator op(custom_int y) \ 91 | { m_val op y; \ 92 | return *this; \ 93 | } 94 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 95 | NARK_custom_int_gen_assign_op(/=) 96 | NARK_custom_int_gen_assign_op(%=) 97 | NARK_custom_int_gen_assign_op(&=) 98 | NARK_custom_int_gen_assign_op(|=) 99 | NARK_custom_int_gen_assign_op(^=) 100 | NARK_custom_int_gen_assign_op(<<=) 101 | NARK_custom_int_gen_assign_op(>>=) 102 | #undef NARK_custom_int_gen_assign_op 103 | 104 | template friend void DataIO_loadObject(Input& input, custom_int& x) 105 | { 106 | unsigned char b; 107 | x.m_val = 0; 108 | for (int bytes = 0; bytes != Bits/8; ++bytes) 109 | { 110 | input >> b; 111 | x.m_val = x.m_val << 8 | b; 112 | } 113 | } 114 | template friend void DataIO_saveObject(Output& output, custom_int x) 115 | { 116 | BaseInt y = x.m_val; 117 | for (int bytes = 0; bytes != Bits/8; ++bytes) 118 | { 119 | output << b; 120 | y >>= 8; 121 | } 122 | } 123 | }; 124 | 125 | typedef custom_int int24_t; 126 | typedef custom_int int40_t; 127 | typedef custom_int int48_t; 128 | typedef custom_int int56_t; 129 | 130 | typedef custom_int uint24_t; 131 | typedef custom_int uint40_t; 132 | typedef custom_int uint48_t; 133 | typedef custom_int uint56_t; 134 | 135 | BOOST_TT_AUX_BOOL_TRAIT_DEF1(is_custom_int, T, false) 136 | 137 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, int24_t, true) 138 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, int40_t, true) 139 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, int48_t, true) 140 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, int56_t, true) 141 | 142 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, uint24_t, true) 143 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, uint40_t, true) 144 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, uint48_t, true) 145 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_custom_int, uint56_t, true) 146 | 147 | //! declaration 148 | template struct presentation_type; 149 | 150 | template<> struct presentation_type { typedef int8_t type; }; 151 | template<> struct presentation_type { typedef int16_t type; }; 152 | template<> struct presentation_type { typedef int32_t type; }; 153 | template<> struct presentation_type { typedef int64_t type; }; 154 | 155 | template<> struct presentation_type { typedef uint8_t type; }; 156 | template<> struct presentation_type { typedef uint16_t type; }; 157 | template<> struct presentation_type { typedef uint32_t type; }; 158 | template<> struct presentation_type { typedef uint64_t type; }; 159 | 160 | template<> struct presentation_type { typedef int32_t type; }; 161 | template<> struct presentation_type { typedef int64_t type; }; 162 | template<> struct presentation_type { typedef int64_t type; }; 163 | template<> struct presentation_type { typedef int64_t type; }; 164 | 165 | template<> struct presentation_type { typedef uint32_t type; }; 166 | template<> struct presentation_type { typedef uint64_t type; }; 167 | template<> struct presentation_type { typedef uint64_t type; }; 168 | template<> struct presentation_type { typedef uint64_t type; }; 169 | 170 | } // namespace nark 171 | 172 | #include "boost/type_traits/detail/bool_trait_undef.hpp" 173 | 174 | #endif // __nark_io_custom_int_h__ 175 | 176 | -------------------------------------------------------------------------------- /src/nark/io/discard/dump_allocator.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_dump_allocator_h__ 3 | #define __nark_io_dump_allocator_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | namespace nark { 10 | 11 | /** 12 | @brief only a proxy, for template typename dispatch 13 | */ 14 | template 15 | class dump_allocator : public BaseAlloc 16 | { 17 | public: 18 | typedef BaseAlloc _MySuper; 19 | 20 | typedef typename BaseAlloc::value_type value_type; 21 | typedef typename BaseAlloc::pointer pointer; 22 | typedef typename BaseAlloc::reference reference; 23 | typedef typename BaseAlloc::const_pointer const_pointer; 24 | typedef typename BaseAlloc::const_reference const_reference; 25 | 26 | typedef typename BaseAlloc::size_type size_type; 27 | typedef typename BaseAlloc::difference_type difference_type; 28 | 29 | template 30 | struct rebind 31 | { // convert an dump_allocator to an dump_allocator <_Other> 32 | private: 33 | typedef typename BaseAlloc::template rebind<_Other>::other BaseRebind; 34 | public: 35 | typedef dump_allocator other; 36 | }; 37 | 38 | dump_allocator() 39 | { // construct default dump_allocator (do nothing) 40 | } 41 | 42 | dump_allocator(const dump_allocator<_Ty>& rhs) 43 | : BaseAlloc(rhs) 44 | { // construct by copying (do nothing) 45 | } 46 | 47 | template 48 | dump_allocator(const dump_allocator<_Other>& other) 49 | : BaseAlloc(static_cast::_MySuper&>(other)) 50 | { // construct from a related dump_allocator (do nothing) 51 | } 52 | 53 | template 54 | dump_allocator<_Ty>& operator=(const dump_allocator<_Other>& other) 55 | { // assign from a related dump_allocator (do nothing) 56 | typedef typename dump_allocator<_Other>::_MySuper _OtherSuper; 57 | BaseAlloc::operator=(static_cast(other)); 58 | return (*this); 59 | } 60 | }; 61 | 62 | // dump_allocator TEMPLATE OPERATORS 63 | template inline 64 | bool operator==(const dump_allocator<_Ty>& l, const dump_allocator<_Other>& r) 65 | { // test for dump_allocator equality (always true) 66 | typedef typename dump_allocator<_Ty>::_MySuper _MySuper; 67 | typedef typename dump_allocator<_Other>::_MySuper _HeSuper; 68 | return static_cast(l) == static_cast(r); 69 | } 70 | 71 | template inline 72 | bool operator!=(const dump_allocator<_Ty>& l, const dump_allocator<_Other>& r) 73 | { // test for dump_allocator inequality (always false) 74 | typedef typename dump_allocator<_Ty>::_MySuper _MySuper; 75 | typedef typename dump_allocator<_Other>::_MySuper _HeSuper; 76 | return static_cast(l) != static_cast(r); 77 | } 78 | 79 | } // namespace nark 80 | 81 | #endif // __nark_io_dump_allocator_h__ 82 | 83 | -------------------------------------------------------------------------------- /src/nark/io/discard/hole_stream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_hole_stream_h__ 3 | #define __nark_io_hole_stream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | //#include 10 | //#include // for memcpy 11 | //#include 12 | //#include 13 | 14 | #include 15 | //#include "IOException.hpp" 16 | 17 | namespace nark { 18 | 19 | class HoleStream 20 | { 21 | public: 22 | explicit HoleStream() : m_pos(0) {} 23 | 24 | // size_t read(void* vbuf, size_t length) { m_pos += length; return length; } 25 | size_t write(const void* vbuf, size_t length) { m_pos += length; return length; } 26 | 27 | // void ensureRead(void* vbuf, size_t length) { m_pos += length; } 28 | void ensureWrite(const void* vbuf, size_t length) { m_pos += length; } 29 | 30 | // byte readByte() { return 0; } 31 | 32 | void writeByte(unsigned char) { m_pos++; } 33 | 34 | private: 35 | stream_position_t m_pos; 36 | }; 37 | 38 | class SeekableHoleStream 39 | { 40 | public: 41 | explicit SeekableHoleStream(stream_position_t size) 42 | { 43 | m_pos = 0; 44 | m_size = size; 45 | } 46 | 47 | private: 48 | stream_position_t m_pos; 49 | stream_position_t m_size; 50 | }; 51 | 52 | } // namespace nark 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /src/nark/io/discard/is_primitive.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_is_primitive_h__ 3 | #define __nark_io_var_int_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | 11 | #include 12 | 13 | // should be the last #include 14 | #include 15 | 16 | namespace nark { 17 | 18 | BOOST_TT_AUX_BOOL_TRAIT_DEF1(is_primitive,T,false) 19 | 20 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, char, true) 21 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned char, true) 22 | 23 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, int, true) 24 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, long, true) 25 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, short, true) 26 | 27 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned int, true) 28 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned long, true) 29 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned short, true) 30 | 31 | #if defined(BOOST_HAS_LONG_LONG) 32 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, long long, true) 33 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned long long, true) 34 | #elif defined(BOOST_HAS_MS_INT64) 35 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, __int64, true) 36 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, unsigned __int64, true) 37 | #endif 38 | 39 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, std::string, true) 40 | BOOST_TT_AUX_BOOL_TRAIT_CV_SPEC1(is_primitive, std::wstring, true) 41 | 42 | 43 | } // namespace nark 44 | 45 | 46 | #include "boost/type_traits/detail/bool_trait_undef.hpp" 47 | 48 | 49 | #endif // __nark_io_var_int_h__ 50 | 51 | -------------------------------------------------------------------------------- /src/nark/io/file_load_save.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __nark_io_file_util_hpp__ 2 | #define __nark_io_file_util_hpp__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace nark { 9 | 10 | template 11 | void native_load_file(const char* fname, Object* obj) { 12 | assert(NULL != fname); 13 | assert(NULL != obj); 14 | FileStream file(fname, "rb"); 15 | NativeDataInput dio; dio.attach(&file); 16 | Object tmp; 17 | dio >> tmp; 18 | obj->swap(tmp); 19 | } 20 | 21 | template 22 | void native_save_file(const char* fname, const Object& obj) { 23 | assert(NULL != fname); 24 | FileStream file(fname, "wb"); 25 | NativeDataOutput dio; dio.attach(&file); 26 | dio << obj; 27 | } 28 | 29 | } // namespace nark 30 | 31 | #endif // __nark_io_file_util_hpp__ 32 | 33 | -------------------------------------------------------------------------------- /src/nark/io/int_diff_coding.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_int_diff_coding_h__ 3 | #define __nark_int_diff_coding_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | //#include 11 | 12 | namespace nark { 13 | 14 | template 15 | class DecodeIntDiff 16 | { 17 | FirstIntType m_cur; 18 | 19 | public: 20 | template 21 | explicit DecodeIntDiff(Input& input, bool firstIsVarInt=true) 22 | { 23 | init(input, firstIsVarInt); 24 | } 25 | DecodeIntDiff() {} 26 | 27 | template 28 | void init(Input& input, bool firstIsVarInt=true) 29 | { 30 | if (firstIsVarInt) { 31 | var_uint64_t x; 32 | input >> x; 33 | m_cur = x.t; 34 | } else 35 | input >> m_cur; 36 | } 37 | 38 | FirstIntType value() const { return m_cur; } 39 | operator FirstIntType() const { return m_cur; } 40 | 41 | template 42 | friend void DataIO_loadObject(Input& in, DecodeIntDiff& x) 43 | { 44 | var_uint64_t diff; 45 | in >> diff; 46 | x.m_cur += diff.t; 47 | } 48 | template 49 | friend void DataIO_saveObject(Output&, const DecodeIntDiff& x) 50 | { 51 | Output::do_not_support_serialize_this_class(x); 52 | } 53 | }; 54 | 55 | template 56 | class EncodeIntDiff 57 | { 58 | FirstIntType m_cur; 59 | 60 | public: 61 | template 62 | EncodeIntDiff(Output& output, FirstIntType first, bool firstIsVarInt=true) 63 | { 64 | init(output, first, firstIsVarInt); 65 | } 66 | EncodeIntDiff() {} 67 | 68 | template 69 | void init(Output& output, FirstIntType first, bool firstIsVarInt=true) 70 | { 71 | m_cur = first; 72 | if (firstIsVarInt) 73 | output << nark::as_var_int(first); 74 | else 75 | output << first; 76 | } 77 | 78 | // FirstIntType value() const { return m_cur; } 79 | // operator FirstIntType() const { return m_cur; } 80 | 81 | //! used as: 82 | //! @code 83 | //! EncodeIntDiff encode_diff(output, iVal); 84 | //! for (...) 85 | //! { 86 | //! iVal = get_next_value(...); 87 | //! output << encode_diff(iVal); 88 | //! } 89 | //! @endcode 90 | var_uint32_t operator()(FirstIntType next) 91 | { 92 | DiffIntType diff = next - m_cur; 93 | m_cur = next; 94 | return var_uint32_t(diff); 95 | } 96 | }; 97 | 98 | } // namespace nark 99 | 100 | #endif // __nark_int_diff_coding_h__ 101 | 102 | -------------------------------------------------------------------------------- /src/nark/io/todo/DataIO_Parser.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_DataIO_Parser_h__ 3 | #define __nark_io_DataIO_Parser_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include "StreamBuffer.hpp" 10 | #include "DataInput.hpp" 11 | #include 12 | 13 | namespace nark { 14 | 15 | template 16 | class DataIO_TextReader : public DataInput > 17 | { 18 | public: 19 | 20 | 21 | protected: 22 | PrimInput* input; 23 | DataIO_Parser* parser; 24 | }; 25 | 26 | template 27 | class DataIO_XML_Reader 28 | { 29 | InputBuffer* buf; 30 | public: 31 | Final_Input& operator>>(int& x) 32 | { 33 | int ch = buf->readByte(); 34 | switch (ch) 35 | { 36 | case 0: // oct 37 | break; 38 | 39 | } 40 | do { 41 | ch = 42 | } while (isdigit(ch)); 43 | } 44 | }; 45 | 46 | class DataIO_Parser 47 | { 48 | public: 49 | 50 | protected: 51 | const char* szMemberText; 52 | std::vector memberNames; 53 | }; 54 | 55 | } 56 | 57 | #endif // __nark_io_DataIO_Parser_h__ 58 | 59 | -------------------------------------------------------------------------------- /src/nark/io/todo/DataIO_Polymorphic.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/src/nark/io/todo/DataIO_Polymorphic.hpp -------------------------------------------------------------------------------- /src/nark/io/todo/inter_thread_pipe.cpp: -------------------------------------------------------------------------------- 1 | #include "inter_thread_pipe.cpp" 2 | 3 | namespace nark { 4 | 5 | class inter_thread_pipe_impl 6 | { 7 | boost::mutex m_mutex; 8 | boost::condition m_cond; 9 | unsigned char *m_bufp, *m_putp, *m_getp; 10 | size_t m_size; 11 | long m_timeout; 12 | 13 | public: 14 | bool eof() 15 | { 16 | boost::mutex::scoped_lock lock(m_mutex); 17 | return (m_size+(m_get-m_putp)) % m_size == 1; 18 | } 19 | 20 | size_t read(void* vbuf, size_t length) 21 | { 22 | boost::mutex::scoped_lock lock(m_mutex); 23 | } 24 | 25 | size_t write(void* vbuf, size_t length) 26 | { 27 | 28 | } 29 | 30 | void flush() 31 | { 32 | } 33 | }; 34 | 35 | inter_thread_pipe::inter_thread_pipe(size_t capacity) 36 | : mio(new capacity) 37 | { 38 | } 39 | 40 | inter_thread_pipe::~inter_thread_pipe() 41 | { 42 | delete capacity; 43 | } 44 | 45 | bool inter_thread_pipe::eof() 46 | { 47 | 48 | return mio->eof(); 49 | } 50 | 51 | size_t inter_thread_pipe::read(void* vbuf, size_t length) 52 | { 53 | return mio->read(vbuf, length); 54 | } 55 | 56 | size_t inter_thread_pipe::write(void* vbuf, size_t length) 57 | { 58 | 59 | } 60 | 61 | void inter_thread_pipe::flush() 62 | { 63 | } 64 | 65 | } // namespace thread 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/nark/io/todo/inter_thread_pipe.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __nark_thread_LockFreeQueue_H__ 2 | #define __nark_thread_LockFreeQueue_H__ 3 | 4 | namespace thread { 5 | 6 | class inter_thread_pipe_impl; 7 | 8 | class inter_thread_pipe 9 | : public RefCounter 10 | , public IInputStream 11 | , public IOutputStream 12 | { 13 | inter_thread_pipe_impl* mio; 14 | public: 15 | explicit inter_thread_pipe(size_t capacity); 16 | ~inter_thread_pipe(); 17 | void eof(); 18 | void read(void* vbuf, size_t length); 19 | void write(void* vbuf, size_t length); 20 | }; 21 | 22 | } // namespace thread 23 | 24 | #endif // __nark_thread_LockFreeQueue_H__ 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/nark/io/var_int.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #include "var_int.hpp" 3 | #include 4 | #include 5 | 6 | #if defined(_MSC_VER) 7 | # include 8 | #pragma intrinsic(_BitScanReverse) 9 | //#pragma intrinsic(_BitScanReverse64) 10 | #endif 11 | 12 | #include 13 | #if BOOST_VERSION < 103301 14 | # include 15 | # include 16 | #else 17 | # include 18 | #endif 19 | 20 | #ifdef _MSC_VER 21 | /* Always compile this module for speed, not size */ 22 | #pragma optimize("t", on) 23 | #endif 24 | 25 | namespace nark { 26 | 27 | #include "var_int_inline.hpp" 28 | 29 | uint32_t load_var_uint32(const unsigned char* buf, const unsigned char** endp) 30 | { 31 | return gg_load_var_uint(buf, endp, BOOST_CURRENT_FUNCTION); 32 | } 33 | 34 | uint64_t load_var_uint64(const unsigned char* buf, const unsigned char** endp) 35 | { 36 | return gg_load_var_uint(buf, endp, BOOST_CURRENT_FUNCTION); 37 | } 38 | 39 | int32_t load_var_int32(const unsigned char* buf, const unsigned char** endp) 40 | { 41 | uint32_t x = load_var_uint32(buf, endp); 42 | return var_int32_u2s(x); 43 | } 44 | 45 | int64_t load_var_int64(const unsigned char* buf, const unsigned char** endp) 46 | { 47 | return var_int64_u2s(load_var_uint64(buf, endp)); 48 | } 49 | 50 | ////////////////////////////////////////////////////////////////////////// 51 | 52 | unsigned char* save_var_uint32(unsigned char* buf, uint32_t x) 53 | { 54 | return gg_save_var_uint(buf, x); 55 | } 56 | 57 | unsigned char* save_var_uint64(unsigned char* p, uint64_t x) 58 | { 59 | #if 0 // save max to 9 bytes 60 | for (int bytes = 0; bytes < 8; ++bytes) 61 | { 62 | if (x & ~(uint64_t)0x7F) { 63 | *p++ = (unsigned char)((x & 0x7f) | 0x80); 64 | x >>= 7; //doing unsigned shift 65 | } else 66 | break; 67 | } 68 | *p++ = (unsigned char)x; 69 | return p; 70 | #else // save max to 10 bytes 71 | return gg_save_var_uint(p, x); 72 | #endif 73 | } 74 | 75 | unsigned char* save_var_int32(unsigned char* buf, int32_t x) { return save_var_uint32(buf, var_int32_s2u(x)); } 76 | unsigned char* save_var_int64(unsigned char* buf, int64_t x) { return save_var_uint64(buf, var_int64_s2u(x)); } 77 | 78 | 79 | //########################################################################################## 80 | 81 | uint32_t load_var_uint30(const unsigned char* buf, const unsigned char** endp) { return gg_load_var_uint30(buf, endp); } 82 | uint64_t load_var_uint61(const unsigned char* buf, const unsigned char** endp) { return gg_load_var_uint61(buf, endp); } 83 | 84 | int32_t load_var_int30(const unsigned char* buf, const unsigned char** endp) { return var_int30_u2s(load_var_uint30(buf, endp)); } 85 | int64_t load_var_int61(const unsigned char* buf, const unsigned char** endp) { return var_int61_u2s(load_var_uint61(buf, endp)); } 86 | 87 | ////////////////////////////////////////////////////////////////////////// 88 | 89 | unsigned char* save_var_uint30(unsigned char* buf, uint32_t x) { return gg_save_var_uint30(buf, x); } 90 | unsigned char* save_var_uint61(unsigned char* buf, uint64_t x) { return gg_save_var_uint61(buf, x); } 91 | 92 | unsigned char* save_var_int30(unsigned char* buf, int32_t x) { return save_var_uint30(buf, var_int30_s2u(x)); } 93 | unsigned char* save_var_int61(unsigned char* buf, int64_t x) { return save_var_uint61(buf, var_int61_s2u(x)); } 94 | 95 | //########################################################################################## 96 | 97 | /** 98 | @brief reverse get var_uint32_t 99 | 100 | @note 101 | - if first var_int has read, *cur == buf-1 102 | - the sequence must all stored var_int, if not, the dilimeter byte's high bit must be 0 103 | */ 104 | uint32_t reverse_get_var_uint32(const unsigned char* buf, unsigned char const ** cur) 105 | { 106 | assert(cur); 107 | assert(*cur); 108 | assert(*cur >= buf); 109 | 110 | const unsigned char* p = *cur; 111 | uint32_t x = 0; 112 | uint32_t w = *p; 113 | assert(!(x & 0x80)); 114 | int shift = 0; 115 | --p; 116 | while (p >= buf && *p & 0x80) 117 | { 118 | x = x << 7 | (uint32_t)(*p & 0x7F); 119 | shift += 7; 120 | --p; 121 | } 122 | x |= w << shift; 123 | *cur = p; 124 | 125 | return x; 126 | } 127 | 128 | /** 129 | @brief reverse get var_int32_t 130 | 131 | @note if first var_int has read, *cur == buf-1 132 | */ 133 | int32_t reverse_get_var_int32(const unsigned char* buf, unsigned char const ** cur) 134 | { 135 | return var_int32_u2s(reverse_get_var_uint32(buf, cur)); 136 | } 137 | 138 | #if !defined(BOOST_NO_INT64_T) 139 | /** 140 | @brief reverse get var_uint64_t 141 | 142 | @note if first var_int has read, *cur == buf-1 143 | */ 144 | uint64_t reverse_get_var_uint64(const unsigned char* buf, unsigned char const ** cur) 145 | { 146 | assert(cur); 147 | assert(*cur); 148 | assert(*cur >= buf); 149 | 150 | const unsigned char* p = *cur; 151 | uint64_t x = 0; 152 | uint64_t w = *p; 153 | int shift = 0; 154 | --p; 155 | while (p >= buf && shift < 56 && *p & 0x80) 156 | { 157 | x = x << 7 | (uint64_t)(*p & 0x7F); 158 | shift += 7; 159 | --p; 160 | } 161 | assert(shift <= 56); 162 | 163 | x |= w << shift; 164 | 165 | *cur = p; // p now point to last byte of prev var_int 166 | 167 | return x; 168 | } 169 | 170 | /** 171 | @brief reverse get var_int64_t 172 | 173 | @note if first var_int has read, *cur == buf-1 174 | */ 175 | int64_t reverse_get_var_int64(const unsigned char* buf, unsigned char const ** cur) 176 | { 177 | return var_int64_u2s(reverse_get_var_uint64(buf, cur)); 178 | } 179 | 180 | #endif //BOOST_NO_INT64_T 181 | 182 | } // namespace nark 183 | 184 | -------------------------------------------------------------------------------- /src/nark/io/var_int_boost_serialization.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __nark_io_var_int_for_boost_serialization_h__ 3 | #define __nark_io_var_int_for_boost_serialization_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "var_int.hpp" 14 | 15 | namespace boost { namespace serialization { 16 | 17 | template 18 | uint32_t load_var_uint32(Archive& ar) 19 | { 20 | uint32_t v = 0; 21 | for (int shift = 0; shift < 35; shift += 7) 22 | { 23 | unsigned char b; ar >> b; 24 | v |= uint32_t(b & 0x7F) << shift; 25 | if ((b & 0x80) == 0) 26 | return v; 27 | } 28 | assert(0); // should not get here 29 | return v; // avoid compile warning 30 | } 31 | 32 | template 33 | uint64_t load_var_uint64(Archive& ar) 34 | { 35 | uint64_t v = 0; 36 | unsigned char b; 37 | for (int shift = 0; shift < 56; shift += 7) 38 | { 39 | ar >> b; 40 | v |= uint64_t(b & 0x7F) << shift; 41 | if ((b & 0x80) == 0) 42 | return v; 43 | } 44 | ar >> b; 45 | v |= uint64_t(b) << 56; 46 | return v; 47 | } 48 | 49 | ////////////////////////////////////////////////////////////////////////// 50 | 51 | template 52 | void load(Archive& ar, nark::var_uint32_t& x, unsigned/*version*/) 53 | { 54 | x.t = load_var_uint32(ar); 55 | } 56 | 57 | template 58 | void load(Archive& ar, nark::var_int32_t& x, unsigned/*version*/) 59 | { 60 | x.t = var_int32_u2s(load_var_uint32(ar)); 61 | } 62 | 63 | template 64 | void save(Archive& ar, nark::var_uint32_t x, unsigned/*version*/) 65 | { 66 | unsigned char buf[5]; 67 | ar.save_binary(buf, nark::save_var_uint32(buf, x.t) - buf); 68 | } 69 | 70 | template 71 | void save(Archive& ar, nark::var_int32_t x, unsigned/*version*/) 72 | { 73 | unsigned char buf[5]; 74 | ar.save_binary(buf, nark::save_var_int32(buf, x.t) - buf); 75 | } 76 | 77 | ////////////////////////////////////////////////////////////////////////// 78 | template 79 | void load(Archive& ar, nark::var_uint64_t& x, unsigned/*version*/) 80 | { 81 | x.t = nark::load_var_uint64(ar); 82 | } 83 | 84 | template 85 | void load(Archive& ar, nark::var_int64_t& x, unsigned/*version*/) 86 | { 87 | x.t = nark::var_int64_u2s(load_var_uint64(ar)); 88 | } 89 | 90 | template 91 | void save(Archive& ar, nark::var_uint64_t x, unsigned/*version*/) 92 | { 93 | unsigned char buf[9]; 94 | ar.save_binary(buf, nark::save_var_uint64(buf, x.t) - buf); 95 | } 96 | 97 | template 98 | void save(Archive& ar, nark::var_int64_t x, unsigned/*version*/) 99 | { 100 | unsigned char buf[9]; 101 | ar.save_binary(buf, nark::save_var_int64(buf, x.t) - buf); 102 | } 103 | 104 | } } // namespace boost::serialization 105 | 106 | BOOST_SERIALIZATION_SPLIT_FREE(nark::var_uint32_t) 107 | BOOST_SERIALIZATION_SPLIT_FREE(nark::var_int32_t) 108 | BOOST_SERIALIZATION_SPLIT_FREE(nark::var_uint64_t) 109 | BOOST_SERIALIZATION_SPLIT_FREE(nark::var_int64_t) 110 | 111 | 112 | #endif // __nark_io_var_int_for_boost_serialization_h__ 113 | 114 | -------------------------------------------------------------------------------- /src/nark/io/var_int_declare_read.hpp: -------------------------------------------------------------------------------- 1 | uint32_t read_var_uint32(); 2 | uint32_t read_var_uint30(); 3 | uint64_t read_var_uint64(); 4 | uint64_t read_var_uint61(); 5 | int32_t read_var_int32(); 6 | int32_t read_var_int30(); 7 | int64_t read_var_int64(); 8 | int64_t read_var_int61(); 9 | void read_string(std::string& str); 10 | 11 | -------------------------------------------------------------------------------- /src/nark/io/var_int_declare_write.hpp: -------------------------------------------------------------------------------- 1 | void write_var_uint32(uint32_t x); 2 | void write_var_uint30(uint32_t x); 3 | void write_var_uint64(uint64_t x); 4 | void write_var_uint61(uint64_t x); 5 | void write_var_int32(int32_t x); 6 | void write_var_int30(int32_t x); 7 | void write_var_int64(int64_t x); 8 | void write_var_int61(int64_t x); 9 | void write_string(const std::string& str); 10 | // void write_string(const char* str, size_t len); 11 | 12 | -------------------------------------------------------------------------------- /src/nark/io/var_int_io.hpp: -------------------------------------------------------------------------------- 1 | // file var_int_io.hpp 2 | // for included by other cpp files 3 | // 4 | // input macro param: 5 | // STREAM_READER 6 | // STREAM_WRITER 7 | // must at least define one of them 8 | // 9 | #if !defined(STREAM_READER) && !defined(STREAM_WRITER) 10 | # error "must define macro STREAM_READER or STREAM_WRITER" 11 | #endif 12 | 13 | #ifdef _MSC_VER 14 | /* Always compile this module for speed, not size */ 15 | #pragma optimize("t", on) 16 | #endif 17 | 18 | #include "var_int_inline.hpp" 19 | 20 | #ifdef STREAM_READER 21 | 22 | uint32_t STREAM_READER::read_var_uint32() 23 | { 24 | if (nark_likely(this->buf_remain_bytes() >= 5)) 25 | { 26 | return gg_load_var_uint(m_pos, (const unsigned char**)&m_pos, BOOST_CURRENT_FUNCTION); 27 | } 28 | else // slower branch 29 | { 30 | return gg_load_var_uint_slow(*this, BOOST_CURRENT_FUNCTION); 31 | } 32 | } 33 | 34 | uint64_t STREAM_READER::read_var_uint64() 35 | { 36 | if (nark_likely(this->buf_remain_bytes() >= 10)) 37 | { 38 | return gg_load_var_uint(m_pos, (const unsigned char**)&m_pos, BOOST_CURRENT_FUNCTION); 39 | } 40 | else // slower branch 41 | { 42 | return gg_load_var_uint_slow(*this, BOOST_CURRENT_FUNCTION); 43 | } 44 | } 45 | 46 | int32_t STREAM_READER::read_var_int32() 47 | { 48 | return var_int32_u2s(read_var_uint32()); 49 | } 50 | 51 | int64_t STREAM_READER::read_var_int64() 52 | { 53 | return var_int64_u2s(read_var_uint64()); 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | uint32_t STREAM_READER::read_var_uint30() 59 | { 60 | if (nark_likely(this->buf_remain_bytes() >= 4)) 61 | { 62 | return gg_load_var_uint30(m_pos, (const unsigned char**)&m_pos); 63 | } 64 | else // slower branch 65 | { 66 | return gg_load_var_uint30_slow(*this); 67 | } 68 | } 69 | 70 | uint64_t STREAM_READER::read_var_uint61() 71 | { 72 | if (nark_likely(this->buf_remain_bytes() >= 8)) 73 | { 74 | return gg_load_var_uint61(m_pos, (const unsigned char**)&m_pos); 75 | } 76 | else // slower branch 77 | { 78 | return gg_load_var_uint61_slow(*this); 79 | } 80 | } 81 | 82 | int32_t STREAM_READER::read_var_int30() 83 | { 84 | return var_int30_u2s(read_var_uint30()); 85 | } 86 | 87 | int64_t STREAM_READER::read_var_int61() 88 | { 89 | return var_int61_u2s(read_var_uint61()); 90 | } 91 | 92 | void STREAM_READER::read_string(std::string& str) 93 | { 94 | size_t len = read_var_uint32(); 95 | str.resize(len); 96 | if (nark_likely(len)) 97 | ensureRead(&str[0], len); 98 | } 99 | 100 | #endif // STREAM_READER 101 | 102 | #ifdef STREAM_WRITER 103 | 104 | void STREAM_WRITER::write_var_uint32(uint32_t x) 105 | { 106 | if (this->buf_remain_bytes() >= 5) 107 | { 108 | unsigned char* endp = gg_save_var_uint(m_pos, x); 109 | assert(endp - m_pos <= 5); 110 | m_pos = endp; 111 | } 112 | else 113 | { 114 | unsigned char tmpbuf[5]; 115 | ptrdiff_t len = gg_save_var_uint(tmpbuf, x) - tmpbuf; 116 | assert(len <= 5); 117 | ensureWrite(tmpbuf, len); 118 | } 119 | } 120 | 121 | void STREAM_WRITER::write_var_uint64(uint64_t x) 122 | { 123 | if (this->buf_remain_bytes() >= 10) 124 | { 125 | unsigned char* endp = gg_save_var_uint(m_pos, x); 126 | assert(endp - m_pos <= 10); 127 | m_pos = endp; 128 | } 129 | else { 130 | unsigned char tmpbuf[10]; 131 | ptrdiff_t len = gg_save_var_uint(tmpbuf, x) - tmpbuf; 132 | assert(len <= 10); 133 | ensureWrite(tmpbuf, len); 134 | } 135 | } 136 | 137 | void STREAM_WRITER::write_var_int32(int32_t x) 138 | { 139 | write_var_uint32(var_int32_s2u(x)); 140 | } 141 | 142 | void STREAM_WRITER::write_var_int64(int64_t x) 143 | { 144 | write_var_uint64(var_int64_s2u(x)); 145 | } 146 | 147 | /////////////////////////////////////////////////////////////////////////////////////////// 148 | 149 | void STREAM_WRITER::write_var_uint30(uint32_t x) 150 | { 151 | if (this->buf_remain_bytes() >= 4) 152 | { 153 | unsigned char* endp = gg_save_var_uint30(m_pos, x); 154 | assert(endp - m_pos <= 4); 155 | m_pos = endp; 156 | } 157 | else 158 | { 159 | unsigned char tmpbuf[4]; 160 | ptrdiff_t len = gg_save_var_uint30(tmpbuf, x) - tmpbuf; 161 | assert(len <= 4); 162 | ensureWrite(tmpbuf, len); 163 | } 164 | } 165 | 166 | void STREAM_WRITER::write_var_uint61(uint64_t x) 167 | { 168 | if (this->buf_remain_bytes() >= 8) 169 | { 170 | unsigned char* endp = gg_save_var_uint61(m_pos, x); 171 | assert(endp - m_pos <= 8); 172 | m_pos = endp; 173 | } 174 | else { 175 | unsigned char tmpbuf[8]; 176 | ptrdiff_t len = gg_save_var_uint61(tmpbuf, x) - tmpbuf; 177 | assert(len <= 8); 178 | ensureWrite(tmpbuf, len); 179 | } 180 | } 181 | 182 | void STREAM_WRITER::write_var_int30(int32_t x) 183 | { 184 | write_var_uint30(var_int30_s2u(x)); 185 | } 186 | 187 | void STREAM_WRITER::write_var_int61(int64_t x) 188 | { 189 | write_var_uint61(var_int61_s2u(x)); 190 | } 191 | 192 | 193 | void STREAM_WRITER::write_string(const std::string& str) 194 | { 195 | write_var_uint32(str.size()); 196 | ensureWrite(str.data(), str.size()); 197 | } 198 | 199 | #if 0 200 | /** 201 | * manually write a string 202 | * 203 | * only for writing, no corresponding read method. 204 | * compitible with `write_string(const std::string& str)`. 205 | */ 206 | void STREAM_WRITER::write_string(const char* str, size_t len) 207 | { 208 | write_var_uint32(len); 209 | ensureWrite(str, len); 210 | } 211 | #endif // 0 212 | 213 | #endif // STREAM_WRITER 214 | 215 | #undef STREAM_READER 216 | #undef STREAM_WRITER 217 | 218 | 219 | -------------------------------------------------------------------------------- /src/nark/io/win/MfcFileStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #if defined(_MSC_VER) 3 | 4 | #include "MfcFileStream.hpp" 5 | #include "byte_io_impl.hpp" 6 | 7 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 8 | # pragma warning(push) 9 | # pragma warning(disable: 4267) 10 | #endif 11 | 12 | namespace nark { 13 | 14 | size_t MfcFileStream::read(void* vbuf, size_t length) 15 | { 16 | return m_fp->Read(vbuf, length); 17 | } 18 | size_t MfcFileStream::write(const void* vbuf, size_t length) 19 | { 20 | TRY 21 | m_fp->Write(vbuf, length); 22 | CATCH(CException, e) 23 | throw OutOfSpaceException("MfcFileStream::Write"); 24 | END_CATCH 25 | return length; 26 | } 27 | bool MfcFileStream::seek(stream_offset_t offset, int origin) 28 | { 29 | TRY 30 | m_fp->Seek(offset, origin); 31 | CATCH(CException, e) 32 | throw OutOfSpaceException("MfcFileStream::Write"); 33 | END_CATCH 34 | return true; 35 | } 36 | void MfcFileStream::flush() 37 | { 38 | m_fp->Flush(); 39 | } 40 | 41 | NARK_GEN_ensureRead (MfcFileStream::) 42 | NARK_GEN_ensureWrite(MfcFileStream::) 43 | NARK_GEN_getByte(MfcFileStream::) 44 | NARK_GEN_readByte(MfcFileStream::) 45 | NARK_GEN_writeByte(MfcFileStream::) 46 | 47 | size_t MfcArchiveStream::read(void* vbuf, size_t length) 48 | { 49 | return m_fp->Read(vbuf, length); 50 | } 51 | size_t MfcArchiveStream::write(const void* vbuf, size_t length) 52 | { 53 | TRY 54 | m_fp->Write(vbuf, length); 55 | CATCH(CException, e) 56 | throw OutOfSpaceException("MfcFileStream::Write"); 57 | END_CATCH 58 | return length; 59 | } 60 | void MfcArchiveStream::flush() { m_fp->Flush(); } 61 | 62 | NARK_GEN_ensureRead (MfcArchiveStream::) 63 | NARK_GEN_ensureWrite(MfcArchiveStream::) 64 | NARK_GEN_getByte(MfcArchiveStream::) 65 | NARK_GEN_readByte(MfcArchiveStream::) 66 | NARK_GEN_writeByte(MfcArchiveStream::) 67 | } 68 | 69 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 70 | # pragma warning(pop) 71 | #endif 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/nark/io/win/MfcFileStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __MfcFileStream_h__ 3 | #define __MfcFileStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | #endif 8 | 9 | #include 10 | #include "IOException.hpp" 11 | #include "IStream.hpp" 12 | 13 | #include 14 | 15 | namespace nark { 16 | class MfcFileStream 17 | : public RefCounter 18 | , public IInputStream 19 | , public IOutputStream 20 | , public ISeekable 21 | { 22 | CFile* m_fp; 23 | 24 | public: 25 | typedef boost::mpl::true_ is_seekable; 26 | 27 | MfcFileStream(CFile* fp) : m_fp(fp) {} 28 | 29 | size_t read(void* vbuf, size_t length); 30 | size_t write(const void* vbuf, size_t length); 31 | bool seek(stream_offset_t offset, int origin); 32 | void flush(); 33 | 34 | void ensureWrite(const void* vbuf, size_t length); 35 | void ensureRead(void* vbuf, size_t length); 36 | void writeByte(unsigned char b); 37 | int getByte(); 38 | unsigned char readByte(); 39 | }; 40 | 41 | class MfcArchiveStream 42 | : public IInputStream 43 | , public IOutputStream 44 | , public ISeekable 45 | { 46 | CArchive* m_fp; 47 | 48 | public: 49 | typedef boost::mpl::false_ is_seekable; 50 | 51 | MfcArchiveStream(CArchive* fp) : m_fp(fp) {} 52 | 53 | size_t read(void* vbuf, size_t length); 54 | size_t write(const void* vbuf, size_t length); 55 | bool seek(stream_offset_t offset, int origin); 56 | void flush(); 57 | 58 | void ensureWrite(const void* vbuf, size_t length); 59 | void ensureRead(void* vbuf, size_t length); 60 | void writeByte(unsigned char b); 61 | int getByte(); 62 | unsigned char readByte(); 63 | }; 64 | 65 | //! @{ 66 | //! serialize CString 67 | template 68 | void DataIO_loadObject(Input& input, CString& x) 69 | { 70 | var_size_t size; 71 | input >> size; 72 | LPTSTR buf = x.GetBufferSetLength(size.t); 73 | buf[size] = 0; 74 | uint32_t size2 = input.read(buf, size.t); 75 | 76 | if (size2 != size.t) 77 | { 78 | throw EndOfFileException("when load CString"); 79 | } 80 | x.ReleaseBuffer(size.t); 81 | } 82 | template 83 | void DataIO_saveObject(Output& output, const CString& x) 84 | { 85 | var_size_t size(x.GetLength()); 86 | output << size; 87 | uint32_t size2 = output.write(static_cast(x), size.t); 88 | 89 | if (size2 != size.t) 90 | { 91 | throw OutOfSpaceException("when save CString"); 92 | } 93 | } 94 | //! @} 95 | } 96 | 97 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 98 | # pragma warning(pop) 99 | #endif 100 | 101 | #endif // __MfcFileStream_h__ 102 | -------------------------------------------------------------------------------- /src/nark/io/win/WinFileStream.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #if defined(_MSC_VER) 3 | 4 | #if !defined(_WINDOWS_) && !defined(_INC_WINDOWS) 5 | # define WIN32_LEAN_AND_MEAN 6 | # include 7 | #endif 8 | 9 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 10 | # pragma once 11 | # pragma warning(push) 12 | # pragma warning(disable: 4267) 13 | #endif 14 | 15 | #include 16 | #include "WinFileStream.hpp" 17 | 18 | namespace nark { 19 | 20 | WinFileStream::~WinFileStream() 21 | { 22 | if (m_bAutoClose && INVALID_HANDLE_VALUE != m_hFile) 23 | CloseHandle(m_hFile); 24 | } 25 | 26 | WinFileStream::WinFileStream( 27 | HANDLE hFile, 28 | bool bAutoClose, 29 | const std::string& strFile 30 | ) : m_hFile(hFile), m_bAutoClose(false), m_strFile(strFile) 31 | {} 32 | 33 | WinFileStream::WinFileStream( 34 | LPCSTR szFile, 35 | DWORD dwDesiredAccess, 36 | DWORD dwShareMode, 37 | LPSECURITY_ATTRIBUTES lpSecurityAttributes) 38 | { 39 | if (!open(szFile, dwDesiredAccess, dwShareMode, lpSecurityAttributes)) 40 | { 41 | throw OpenFileException(szFile, ErrorText(GetLastError()).c_str()); 42 | } 43 | } 44 | 45 | WinFileStream::WinFileStream( 46 | LPCSTR szFile, 47 | DWORD dwDesiredAccess, 48 | DWORD dwShareMode, 49 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 50 | DWORD dwCreationDisposition, 51 | DWORD dwFlagsAndAttributes, 52 | HANDLE hTemplateFile) 53 | { 54 | if (!open(szFile, dwDesiredAccess, dwShareMode, lpSecurityAttributes, 55 | dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)) 56 | { 57 | throw OpenFileException(szFile, ErrorText(GetLastError()).c_str()); 58 | } 59 | } 60 | 61 | bool WinFileStream::open( 62 | LPCSTR szFile, 63 | DWORD dwDesiredAccess, 64 | DWORD dwShareMode, 65 | LPSECURITY_ATTRIBUTES lpSecurityAttributes) 66 | { 67 | return open(szFile, dwDesiredAccess, dwShareMode, lpSecurityAttributes, 68 | DefaultCreateDisposition(dwDesiredAccess), 0, NULL 69 | ); 70 | } 71 | 72 | bool WinFileStream::open( 73 | LPCSTR szFile, 74 | DWORD dwDesiredAccess, 75 | DWORD dwShareMode, 76 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 77 | DWORD dwCreationDisposition, 78 | DWORD dwFlagsAndAttributes, 79 | HANDLE hTemplateFile) 80 | { 81 | m_strFile = szFile; 82 | m_hFile = CreateFile(szFile, dwDesiredAccess, dwShareMode, 83 | lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 84 | m_bAutoClose = true; 85 | 86 | return INVALID_HANDLE_VALUE != m_hFile; 87 | } 88 | 89 | void WinFileStream::attach(HANDLE hFile, 90 | bool bAutoClose, 91 | const std::string& strFile) 92 | { 93 | assert(INVALID_HANDLE_VALUE == m_hFile); 94 | m_hFile = hFile; 95 | m_bAutoClose = bAutoClose; 96 | m_strFile = strFile; 97 | } 98 | HANDLE WinFileStream::detach() 99 | { 100 | assert(INVALID_HANDLE_VALUE != m_hFile); 101 | HANDLE hFile = m_hFile; 102 | m_hFile = INVALID_HANDLE_VALUE; 103 | return hFile; 104 | } 105 | 106 | size_t WinFileStream::read(void* vbuf, size_t length) 107 | { 108 | assert(INVALID_HANDLE_VALUE != m_hFile); 109 | DWORD nReaded; 110 | if (ReadFile(m_hFile, vbuf, length, &nReaded, 0)) 111 | { 112 | return nReaded; 113 | } 114 | throw IOException(ErrorText(GetLastError()).c_str()); 115 | } 116 | 117 | size_t WinFileStream::write(const void* vbuf, size_t length) 118 | { 119 | assert(INVALID_HANDLE_VALUE != m_hFile); 120 | DWORD nWritten; 121 | if (WriteFile(m_hFile, vbuf, length, &nWritten, 0)) 122 | { 123 | return nWritten; 124 | } 125 | throw IOException(ErrorText(GetLastError()).c_str()); 126 | } 127 | 128 | uint64_t WinFileStream::do_seek(int64_t offset, int origin) 129 | { 130 | assert(INVALID_HANDLE_VALUE != m_hFile); 131 | LONG hi32 = LONG(uint64_t(offset) >> 32); 132 | LONG lo32 = LONG(offset & 0xFFFFFFFF); 133 | lo32 = SetFilePointer(m_hFile, lo32, &hi32, origin); 134 | DWORD err; 135 | if (INVALID_SET_FILE_POINTER == lo32 && (err = GetLastError()) != NO_ERROR) 136 | { 137 | throw IOException(ErrorText(err).c_str()); 138 | } 139 | return uint64_t(hi32) << 32 | lo32; 140 | } 141 | 142 | void WinFileStream::seek(int64_t offset, int origin) 143 | { 144 | (void)do_seek(offset, origin); 145 | } 146 | 147 | uint64_t WinFileStream::tell() const 148 | { 149 | assert(INVALID_HANDLE_VALUE != m_hFile); 150 | LONG hi32 = 0; 151 | LONG lo32 = 0; 152 | lo32 = SetFilePointer(m_hFile, lo32, &hi32, FILE_CURRENT); 153 | DWORD err; 154 | if (INVALID_SET_FILE_POINTER == lo32 && (err = GetLastError()) != NO_ERROR) 155 | { 156 | throw IOException(ErrorText(err).c_str()); 157 | } 158 | return uint64_t(hi32) << 32 | lo32; 159 | } 160 | 161 | void WinFileStream::flush() 162 | { 163 | assert(INVALID_HANDLE_VALUE != m_hFile); 164 | if (!FlushFileBuffers(m_hFile)) 165 | throw IOException(ErrorText(GetLastError()).c_str()); 166 | } 167 | 168 | void WinFileStream::close() 169 | { 170 | assert(INVALID_HANDLE_VALUE != m_hFile); 171 | CloseHandle(m_hFile); 172 | } 173 | 174 | uint64_t WinFileStream::size() 175 | { 176 | assert(INVALID_HANDLE_VALUE != m_hFile); 177 | DWORD hi32; 178 | DWORD lo32 = GetFileSize(m_hFile, &hi32); 179 | DWORD err; 180 | if (INVALID_FILE_SIZE == lo32 && NO_ERROR != (err = GetLastError())) 181 | { 182 | throw IOException(ErrorText(err).c_str()); 183 | } 184 | return uint64_t(hi32) << 32 | lo32; 185 | } 186 | 187 | void WinFileStream::setEof(uint64_t newSize) 188 | { 189 | assert(INVALID_HANDLE_VALUE != m_hFile); 190 | uint64_t oldPos = do_seek(newSize, FILE_BEGIN); 191 | BOOL bRet = SetEndOfFile(m_hFile); 192 | seek(oldPos, FILE_BEGIN); 193 | if (!bRet) 194 | throw IOException(ErrorText(GetLastError()).c_str()); 195 | } 196 | 197 | DWORD WinFileStream::DefaultCreateDisposition(DWORD dwDesiredAccess) const 198 | { 199 | if (dwDesiredAccess & (GENERIC_READ|GENERIC_WRITE)) 200 | { 201 | return OPEN_ALWAYS; 202 | } 203 | else if (dwDesiredAccess & GENERIC_READ) 204 | { 205 | return OPEN_EXISTING; 206 | } 207 | else if (dwDesiredAccess & GENERIC_WRITE) 208 | { 209 | return CREATE_ALWAYS; 210 | } 211 | else 212 | { 213 | return OPEN_ALWAYS; 214 | } 215 | } 216 | 217 | std::string WinFileStream::ErrorText(DWORD errCode) const 218 | { 219 | HLOCAL hLocal = NULL; 220 | DWORD dwTextLength = FormatMessage( 221 | FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 222 | NULL, 223 | errCode, 224 | 0, //MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) 225 | (LPTSTR)&hLocal, 226 | 0, 227 | NULL 228 | ); 229 | std::string strText = "file: \"" + m_strFile + "\" error: " + (LPCSTR)LocalLock(hLocal); 230 | LocalFree(hLocal); 231 | 232 | return strText; 233 | } 234 | 235 | } 236 | 237 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 238 | # pragma warning(pop) 239 | #endif 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /src/nark/io/win/WinFileStream.hpp: -------------------------------------------------------------------------------- 1 | /* vim: set tabstop=4 : */ 2 | #ifndef __WinFileStream_h__ 3 | #define __WinFileStream_h__ 4 | 5 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 6 | # pragma once 7 | # pragma warning(push) 8 | # pragma warning(disable: 4267) 9 | #endif 10 | 11 | #include 12 | #include "IOException.hpp" 13 | #include "IStream.hpp" 14 | 15 | #if !defined(_WINDOWS_) && !defined(_INC_WINDOWS) 16 | # define WIN32_LEAN_AND_MEAN 17 | # include 18 | #endif 19 | 20 | namespace nark { 21 | 22 | class WinFileStream : public RefCounter, public ISeekableStream 23 | { 24 | public: 25 | typedef boost::mpl::true_ is_seekable; 26 | 27 | ~WinFileStream(); 28 | 29 | explicit WinFileStream( 30 | HANDLE hFile = INVALID_HANDLE_VALUE, 31 | bool bAutoClose = false, 32 | const std::string& strFile = "" 33 | ); 34 | explicit WinFileStream( 35 | LPCSTR szFile, 36 | DWORD dwDesiredAccess, 37 | DWORD dwShareMode = FILE_SHARE_READ, 38 | LPSECURITY_ATTRIBUTES lpSecurityAttributes = 0 // optional 39 | ); 40 | explicit WinFileStream( 41 | LPCSTR szFile, 42 | DWORD dwDesiredAccess, 43 | DWORD dwShareMode, 44 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, // optional 45 | DWORD dwCreationDisposition, 46 | DWORD dwFlagsAndAttributes = 0, 47 | HANDLE hTemplateFile = NULL 48 | ); 49 | bool open( 50 | LPCSTR szFile, 51 | DWORD dwDesiredAccess, 52 | DWORD dwShareMode = FILE_SHARE_READ, 53 | LPSECURITY_ATTRIBUTES lpSecurityAttributes = 0 // optional 54 | ); 55 | bool open( 56 | LPCSTR szFile, 57 | DWORD dwDesiredAccess, 58 | DWORD dwShareMode, 59 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, // optional 60 | DWORD dwCreationDisposition, 61 | DWORD dwFlagsAndAttributes = 0, 62 | HANDLE hTemplateFile = NULL 63 | ); 64 | void attach(HANDLE hFile, 65 | bool bAutoClose = false, 66 | const std::string& strFile = ""); 67 | 68 | HANDLE detach(); 69 | 70 | size_t read(void* vbuf, size_t length); 71 | 72 | size_t write(const void* vbuf, size_t length); 73 | 74 | void seek(int64_t offset, int origin); 75 | uint64_t tell() const; 76 | 77 | void flush(); 78 | 79 | void close(); 80 | 81 | uint64_t size(); 82 | 83 | void setEof(uint64_t newSize); 84 | 85 | protected: 86 | HANDLE m_hFile; 87 | bool m_bAutoClose; 88 | std::string m_strFile; 89 | 90 | uint64_t do_seek(int64_t offset, int origin); 91 | DWORD DefaultCreateDisposition(DWORD dwDesiredAccess) const; 92 | std::string ErrorText(DWORD errCode) const; 93 | }; 94 | } 95 | 96 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 97 | # pragma warning(pop) 98 | #endif 99 | 100 | #endif // __WinFileStream_h__ 101 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | 2 | NARK_SERIALIZATION = .. 3 | NARK_BONE = ../../nark-bone 4 | 5 | ifeq "$(origin CXX)" "default" 6 | ifeq "$(shell test -e /opt/bin/g++ && echo 1)" "1" 7 | CXX := /opt/bin/g++ 8 | else 9 | ifeq "$(shell test -e ${HOME}/opt/bin/g++ && echo 1)" "1" 10 | CXX := ${HOME}/opt/bin/g++ 11 | endif 12 | endif 13 | endif 14 | 15 | ifeq "$(origin LD)" "default" 16 | LD := ${CXX} 17 | endif 18 | 19 | override INCS := -I${NARK_SERIALIZATION}/src -I${NARK_BONE}/src ${INCS} 20 | #override CXXFLAGS += -pipe 21 | override CXXFLAGS += -std=gnu++1y 22 | override CXXFLAGS += -Wall -Wextra 23 | override CXXFLAGS += -Wno-unused-parameter 24 | #override CXXFLAGS += -Wno-unused-variable 25 | #CXXFLAGS += -Wconversion -Wno-sign-conversion 26 | 27 | override CXXFLAGS += -Wfatal-errors 28 | 29 | ifneq ($(shell uname), Darwin) 30 | override LIBS += -lrt 31 | endif 32 | ifeq ($(shell expr substr `uname` 1 6), CYGWIN) 33 | DLL_EXT = .dll.a 34 | else 35 | DLL_EXT = .so 36 | endif 37 | 38 | COMPILER := $(shell ${CXX} --version | head -1 | awk '{split($$3, Ver, "."); printf("%s-%d.%d", $$1, Ver[1], Ver[2]);}') 39 | UNAME_MachineSystem := $(shell uname -m -s | sed 's:[ /]:-:g') 40 | 41 | ifeq "$(shell expr substr ${COMPILER} 1 5)" "clang" 42 | override CXXFLAGS += -fcolor-diagnostics 43 | endif 44 | 45 | ifeq "$(shell expr substr ${COMPILER} 1 3)" "g++" 46 | override CXXFLAGS += -time 47 | override CXXFLAGS += -fmax-errors=5 48 | #override CXXFLAGS += -fmax-errors=2 49 | endif 50 | 51 | # icc or icpc 52 | ifeq "$(shell expr substr ${COMPILER} 1 2)" "ic" 53 | override CXXFLAGS += -xHost -fasm-blocks 54 | else 55 | override CXXFLAGS += -march=native 56 | endif 57 | 58 | BUILD_DIR := build/${COMPILER}-${UNAME_MachineSystem} 59 | 60 | DBG_DIR := ${BUILD_DIR}/dbg 61 | RLS_DIR := ${BUILD_DIR}/rls 62 | 63 | SRCS := $(shell find src -name '*.cpp' -not -name 'stdafx.cpp') 64 | 65 | ifeq ($(shell expr substr `uname` 1 6), CYGWIN) 66 | # Fatal error: can't write build/g++-4.8-CYGWIN_NT-6.1-x86_64/dbg/CompileSpeedBoost/CompileSpeedBoost.o: File too big 67 | SRCS := $(filter-out CompileSpeedBoost/CompileSpeedBoost.cpp, ${SRCS}) 68 | endif 69 | 70 | OBJS_R := $(addprefix ${RLS_DIR}/, $(addsuffix .o, $(basename ${SRCS}))) 71 | OBJS_D := $(addprefix ${DBG_DIR}/, $(addsuffix .o ,$(basename ${SRCS}))) 72 | BINS_D := $(addsuffix .exe ,$(basename ${OBJS_D})) 73 | BINS_R := $(addsuffix .exe ,$(basename ${OBJS_R})) 74 | 75 | ext_ldflags = $(strip $(shell sed -n 's,//Makefile\s*:\s*LDFLAGS\s*:\s*\(.*\),\1,p' $(subst .exe,.cpp,$(subst ${RLS_DIR}/,,$(subst ${DBG_DIR}/,,$@))))) 76 | ext_cxxflags = $(strip $(shell sed -n 's,//Makefile\s*:\s*CXXFLAGS\s*:\s*\(.*\),\1,p' $<)) 77 | 78 | .PHONY : all clean link 79 | 80 | all : ${BINS_D} ${BINS_R} ${OBJS_D} ${OBJS_R} link 81 | 82 | link : ${BINS_D} ${BINS_R} 83 | mkdir -p dbg; cd dbg; \ 84 | for f in `find ../${DBG_DIR} -name '*.exe'`; do \ 85 | ln -sf $$f .; \ 86 | done; cd .. 87 | mkdir -p rls; cd rls; \ 88 | for f in `find ../${RLS_DIR} -name '*.exe'`; do \ 89 | ln -sf $$f .; \ 90 | done; cd .. 91 | 92 | ifeq (${STATIC},1) 93 | ${BINS_D} : override LIBS := ${NARK_SERIALIZATION}/lib/libnark-serialization-d.a ${NARK_BONE}/lib/libnark-bone-d.a 94 | ${BINS_R} : override LIBS := ${NARK_SERIALIZATION}/lib/libnark-serialization-r.a ${NARK_BONE}/lib/libnark-bone-r.a 95 | else 96 | NARK_LIBS := -L${NARK_SERIALIZATION}/lib 97 | NARK_LIBS += -L${NARK_BONE}/lib 98 | ${BINS_D} : override LIBS := ${NARK_LIBS} -lnark-serialization-d -lnark-bone-d ${LIBS} 99 | ${BINS_R} : override LIBS := ${NARK_LIBS} -lnark-serialization-r -lnark-bone-d ${LIBS} 100 | endif 101 | 102 | clean : 103 | rm -rf ${BUILD_DIR} dbg rls 104 | 105 | ${DBG_DIR}/%.o : %.cpp 106 | @mkdir -p $(dir $@) 107 | ${CXX} -O0 -g3 -c ${INCS} ${CXXFLAGS} -o $@ $< $(ext_cxxflags) 108 | 109 | #${RLS_DIR}/%.o : CXXFLAGS += -funsafe-loop-optimizations -fgcse-sm -fgcse-las -fgcse-after-reload 110 | ${RLS_DIR}/%.o : %.cpp 111 | @mkdir -p $(dir $@) 112 | ${CXX} -Ofast -c ${INCS} ${CXXFLAGS} -o $@ $< $(ext_cxxflags) -DNDEBUG 113 | 114 | %.exe : %.o 115 | @echo Linking ... $@ 116 | ${LD} ${LDFLAGS} -o $@ $< ${LIBS} $(ext_ldflags) 117 | -------------------------------------------------------------------------------- /test/src/Bench/ReadMe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rockeet/nark-serialization/8ab089c02cf643a398489bdfb151588ccd62d48b/test/src/Bench/ReadMe.txt -------------------------------------------------------------------------------- /test/src/Bench/test_body.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////// 2 | // 使用这种方式的原因是,当把 ar 作为一个引用参数传递时, 3 | // 编译器会禁止一些优化,比如把 ar 本身放入寄存器, 4 | // 而这种优化导致的结果差异可能很巨大,已发现的是在 VC2008 中,达到 2 倍以上 5 | // 6 | // expanded as below, 'ar' will be put in register 7 | // 不手工展开 test_serialize, 编译器不能将 ar 放进寄存器,速度会慢一倍(d.d4 大一倍) 8 | // test_serialize(ar, d); 9 | //------------------------------------------------------------------------ 10 | int64_t c0, c1, c2, c3, c4, c5, c6, c7; 11 | 12 | c0 = pf.now(); 13 | ar & v0; 14 | c1 = pf.now(); 15 | ar & v1; 16 | c2 = pf.now(); 17 | ar & v2; 18 | c3 = pf.now(); 19 | ar & v3; 20 | c4 = pf.now(); 21 | 22 | for (int i=0, n=v0.size(); i < n; ++i) 23 | { 24 | MyData1 md1; 25 | ar & md1; 26 | } 27 | c5 = pf.now(); 28 | 29 | for (int i=0, n=v0.size(); i < n; ++i) 30 | { 31 | VarIntD vid; 32 | ar & vid; 33 | } 34 | c6 = pf.now(); 35 | 36 | ar & v4; 37 | c7 = pf.now(); 38 | 39 | d.d0 += c1 - c0; 40 | d.d1 += c2 - c1; 41 | d.d2 += c3 - c2; 42 | d.d3 += c4 - c3; 43 | d.d4 += c5 - c4; 44 | d.d5 += c6 - c5; 45 | d.d6 += c7 - c6; 46 | ////////////////////////////////////////////////////////////////////////// 47 | -------------------------------------------------------------------------------- /test/src/FastVarIntBench/FastVarIntBench.cpp: -------------------------------------------------------------------------------- 1 | #define NARK_DATA_IO_SLOW_VAR_INT 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace nark; 12 | 13 | template 14 | void fast_read_v32(int size, int loop, Stream s) 15 | { 16 | for (int j = 0; j < loop; ++j) { 17 | Stream input = s; 18 | for (int i = 0; i < size; ++i) { 19 | volatile uint32_t x = input.read_var_uint32(); 20 | } 21 | input = s; 22 | for (int i = 0; i < size; ++i) { 23 | volatile uint32_t x = input.read_var_uint32(); 24 | } 25 | } 26 | } 27 | 28 | template 29 | void slow_read_v32(int size, int loop, Stream s) 30 | { 31 | for (int j = 0; j < loop; ++j) { 32 | NativeDataInput input; 33 | input.set(s); 34 | // 重复两次以便 '>>' 不会被 inline 35 | for (int i = 0; i < size; ++i) { 36 | var_uint32_t x; 37 | input >> x; 38 | volatile var_uint32_t y = x; 39 | } 40 | input.set(s); 41 | for (int i = 0; i < size; ++i) { 42 | var_uint32_t x; 43 | input >> x; 44 | volatile var_uint32_t y = x; 45 | } 46 | } 47 | } 48 | 49 | template 50 | void read_v30(int size, int loop, Stream s, VarUint* x) 51 | { 52 | for (int j = 0; j < loop; ++j) { 53 | NativeDataInput input; 54 | input.set(s); 55 | for (int i = 0; i < size; ++i) { 56 | input >> *x; 57 | } 58 | input.set(s); 59 | for (int i = 0; i < size; ++i) { 60 | input >> *x; 61 | } 62 | } 63 | } 64 | 65 | template 66 | void test(int size, int loop, Uint*, VarUint*) 67 | { 68 | 69 | } 70 | 71 | int main(int argc, char* argv[]) 72 | { 73 | int size = 256; 74 | int loop = 256; 75 | if (argc > 1) 76 | size = atoi(argv[1]); 77 | if (argc > 2) 78 | loop = atoi(argv[2]); 79 | 80 | vector vec(size); 81 | for (int i = 0; i < size; ++i) 82 | vec[i] = rand() % (1<<30); 83 | 84 | NativeDataOutput fast; 85 | NativeDataOutput slow; 86 | NativeDataOutput uv30; 87 | fast.resize(size * 5); 88 | slow.resize(size * 5); 89 | uv30.resize(size * 5); 90 | 91 | profiling pf; 92 | long long t0 = pf.now(); // start fast write var_uint32 93 | for (int j = 0; j < loop; ++j) { 94 | fast.rewind(); 95 | for (int i = 0; i < size; ++i) { 96 | fast.write_var_uint32(vec[i]); 97 | } 98 | } 99 | long long t1 = pf.now(); // start slow write var_uint32 100 | for (int j = 0; j < loop; ++j) { 101 | slow.rewind(); 102 | for (int i = 0; i < size; ++i) { 103 | slow << var_uint32_t(vec[i]); 104 | } 105 | } 106 | long long t2 = pf.now(); // start fast read var_uint32 107 | 108 | fast_read_v32(size, loop, fast.head()); 109 | 110 | long long t3 = pf.now(); // start slow read 111 | 112 | slow_read_v32(size, loop, slow.head()); 113 | 114 | long long t4 = pf.now(); // start write var_uint30 115 | for (int j = 0; j < loop; ++j) { 116 | uv30.rewind(); 117 | for (int i = 0; i < size; ++i) { 118 | uv30.write_var_uint30(vec[i]); 119 | } 120 | } 121 | long long t5 = pf.now(); // start read var_uint30 122 | var_uint30_t xxxxx; 123 | read_v30(size, loop, uv30.head(), &xxxxx); 124 | long long t6 = pf.now(); 125 | 126 | if (fast.tell() != slow.tell() || memcmp(fast.begin(), slow.begin(), fast.tell()) != 0) { 127 | printf("error: fast != slow\n"); 128 | } 129 | 130 | // check correction 131 | var_uint32_t v1(12345678); 132 | slow.rewind(); slow << v1; 133 | slow.rewind(); 134 | uint32_t v2 = slow.read_var_uint32(); 135 | assert(v1.t == v2); 136 | 137 | slow.rewind(); 138 | slow.write_var_uint32(v2); 139 | { 140 | NativeDataInput input; 141 | input.set(slow.head()); 142 | input >> v1; 143 | } 144 | assert(v1.t == v2); 145 | 146 | printf("save[fast=%lld'us, slow=%lld'us, slow/fast=%f, avg=%f'ns, speed=%f'MB/S]\n" 147 | , pf.us(t0,t1), pf.us(t1,t2) 148 | , (double)(t2-t1)/(t1-t0) 149 | , (double)pf.ns(t0,t1)/(loop * size) 150 | , (double)(sizeof(uint32_t) * loop * size) * 1e3 / pf.ns(t0,t1) 151 | ); 152 | printf("load[fast=%lld'us, slow=%lld'us, slow/fast=%f, avg=%f'ns, speed=%f'MB/S]\n" 153 | , pf.us(t2,t3), pf.us(t3,t4) 154 | , (double)(t4-t3)/(t3-t2) 155 | , (double)pf.ns(t2,t3)/(loop * size * 2) 156 | , (double)(sizeof(uint32_t) * loop * size) * 1e3 / pf.ns(t2,t3) 157 | ); 158 | printf("save[vu30=%lld'us, fast=%lld'us, fast/vu30=%f, avg=%f'ns, speed=%f'MB/S]\n" 159 | , pf.us(t4,t5), pf.us(t0,t1) 160 | , (double)(t1-t0)/(t5-t4) 161 | , (double)pf.ns(t4,t5)/(loop * size) 162 | , (double)(sizeof(uint32_t) * loop * size) * 1e3 / pf.ns(t4,t5) 163 | ); 164 | printf("load[vu30=%lld'us, fast=%lld'us, fast/vu30=%f, avg=%f'ns, speed=%f'MB/S]\n" 165 | , pf.us(t5,t6), pf.us(t2,t3) 166 | , (double)(t3-t2)/(t6-t5) 167 | , (double)pf.ns(t5,t6)/(loop * size * 2) 168 | , (double)(sizeof(uint32_t) * loop * size) * 1e3 / pf.ns(t5,t6) 169 | ); 170 | 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /test/src/FastVarIntBench/FastVarIntBench.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 52 | 55 | 58 | 61 | 67 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 89 | 97 | 100 | 103 | 106 | 109 | 112 | 123 | 126 | 129 | 132 | 140 | 143 | 146 | 149 | 152 | 155 | 158 | 161 | 162 | 169 | 172 | 175 | 178 | 181 | 185 | 194 | 197 | 200 | 203 | 209 | 212 | 215 | 218 | 221 | 224 | 227 | 230 | 231 | 239 | 242 | 245 | 248 | 251 | 255 | 266 | 269 | 272 | 275 | 283 | 286 | 289 | 292 | 295 | 298 | 301 | 304 | 305 | 306 | 307 | 308 | 309 | 314 | 317 | 318 | 319 | 324 | 325 | 330 | 331 | 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /test/src/IsDump/IsDump.cpp: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | //#include 5 | 6 | #include 7 | 8 | //#include 9 | 10 | struct Dumpable 11 | { 12 | int x, y, z; 13 | }; 14 | DATA_IO_DUMP_RAW_MEM_E(Dumpable) 15 | 16 | struct Dumpable2 17 | { 18 | unsigned char a, b, c, d; 19 | DATA_IO_LOAD_SAVE(Dumpable2, &a &b &c &d) 20 | }; 21 | namespace nark { 22 | DataIO_IsDump_TypeTrue1(Dumpable2) 23 | } 24 | 25 | template 26 | nark::DataIO_is_dump 27 | DataIO_IsDump(Dio*, T*) 28 | { 29 | return nark::DataIO_is_dump(); 30 | } 31 | 32 | int main(int argc, char* argv[]) 33 | { 34 | using namespace nark; 35 | using namespace std; 36 | 37 | uint8_t u8; 38 | uint16_t u16; 39 | uint32_t u32; 40 | uint64_t u64; 41 | int8_t s8; 42 | int16_t s16; 43 | int32_t s32; 44 | int64_t s64; 45 | char c; 46 | 47 | NativeDataInput iNative; 48 | PortableDataInput iPortable; 49 | NativeDataOutput oNative; 50 | PortableDataOutput oPortable; 51 | // printf("DataIO_IsDump(NativeDataInput,uint32_t)=%d\n", DataIO_IsDump(&iNative, &u32).value); 52 | 53 | assert(DataIO_IsDump(&iNative, &c ).value); 54 | assert(DataIO_IsDump(&iNative, &u8 ).value); 55 | assert(DataIO_IsDump(&iNative, &u16).value); 56 | assert(DataIO_IsDump(&iNative, &u32).value); 57 | assert(DataIO_IsDump(&iNative, &u64).value); 58 | assert(DataIO_IsDump(&iNative, &u32).value); 59 | 60 | assert(DataIO_IsDump(&oNative, &c ).value); 61 | assert(DataIO_IsDump(&oNative, &u8 ).value); 62 | assert(DataIO_IsDump(&oNative, &u16).value); 63 | assert(DataIO_IsDump(&oNative, &u32).value); 64 | assert(DataIO_IsDump(&oNative, &u64).value); 65 | assert(DataIO_IsDump(&oNative, &u32).value); 66 | 67 | assert(DataIO_IsDump(&iPortable, &c ).value); 68 | assert(DataIO_IsDump(&iPortable, &u8 ).value); 69 | assert(DataIO_IsDump(&iPortable, &u16).value); 70 | assert(DataIO_IsDump(&iPortable, &u32).value); 71 | assert(DataIO_IsDump(&iPortable, &u64).value); 72 | assert(DataIO_IsDump(&iPortable, &u32).value); 73 | 74 | assert(DataIO_IsDump(&oPortable, &c ).value); 75 | assert(DataIO_IsDump(&oPortable, &u8 ).value); 76 | assert(DataIO_IsDump(&oPortable, &u16).value); 77 | assert(DataIO_IsDump(&oPortable, &u32).value); 78 | assert(DataIO_IsDump(&oPortable, &u64).value); 79 | assert(DataIO_IsDump(&oPortable, &u32).value); 80 | 81 | assert(DataIO_IsDump(&iNative, &s8 ).value); 82 | assert(DataIO_IsDump(&iNative, &s16).value); 83 | assert(DataIO_IsDump(&iNative, &s32).value); 84 | assert(DataIO_IsDump(&iNative, &s64).value); 85 | assert(DataIO_IsDump(&iNative, &s32).value); 86 | 87 | assert(DataIO_IsDump(&oNative, &s8 ).value); 88 | assert(DataIO_IsDump(&oNative, &s16).value); 89 | assert(DataIO_IsDump(&oNative, &s32).value); 90 | assert(DataIO_IsDump(&oNative, &s64).value); 91 | assert(DataIO_IsDump(&oNative, &s32).value); 92 | 93 | assert(DataIO_IsDump(&iPortable, &s8 ).value); 94 | assert(DataIO_IsDump(&iPortable, &s16).value); 95 | assert(DataIO_IsDump(&iPortable, &s32).value); 96 | assert(DataIO_IsDump(&iPortable, &s64).value); 97 | assert(DataIO_IsDump(&iPortable, &s32).value); 98 | 99 | assert(DataIO_IsDump(&oPortable, &s8 ).value); 100 | assert(DataIO_IsDump(&oPortable, &s16).value); 101 | assert(DataIO_IsDump(&oPortable, &s32).value); 102 | assert(DataIO_IsDump(&oPortable, &s64).value); 103 | assert(DataIO_IsDump(&oPortable, &s32).value); 104 | 105 | std::pair p16_16; 106 | std::pair p16_32; // has padding, so can not dump 107 | std::pair p32_32; 108 | std::pair p64_64; 109 | assert( DataIO_IsDump(&oNative, &p16_16).value); 110 | assert(!DataIO_IsDump(&oNative, &p16_32).value); 111 | assert( DataIO_IsDump(&oNative, &p32_32).value); 112 | assert( DataIO_IsDump(&oNative, &p64_64).value); 113 | 114 | Dumpable d; 115 | assert( DataIO_IsDump(&oNative, &d).value); 116 | 117 | Dumpable2 d2; 118 | assert( DataIO_IsDump(&oNative, &d2).value); 119 | 120 | vector v_u32; 121 | for (int i = 0; i < 100; ++i) 122 | v_u32.push_back(i+1); 123 | 124 | oNative << v_u32; 125 | 126 | printf("OK!\n"); 127 | 128 | return 0; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /test/src/IsDump/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : DataIO_IsDump Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this DataIO_IsDump application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your DataIO_IsDump application. 9 | 10 | 11 | DataIO_IsDump.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | DataIO_IsDump.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named DataIO_IsDump.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /test/src/TestCorrection/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : DataIO Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this DataIO application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your DataIO application. 9 | 10 | 11 | DataIO.vcproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | DataIO.cpp 18 | This is the main application source file. 19 | 20 | ///////////////////////////////////////////////////////////////////////////// 21 | Other standard files: 22 | 23 | StdAfx.h, StdAfx.cpp 24 | These files are used to build a precompiled header (PCH) file 25 | named DataIO.pch and a precompiled types file named StdAfx.obj. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other notes: 29 | 30 | AppWizard uses "TODO:" comments to indicate parts of the source code you 31 | should add to or customize. 32 | 33 | ///////////////////////////////////////////////////////////////////////////// 34 | -------------------------------------------------------------------------------- /test/src/TestCorrection/TestCorrection.cpp: -------------------------------------------------------------------------------- 1 | // DataIO.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #undef NDEBUG 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #undef NDEBUG 11 | 12 | using namespace nark; 13 | using namespace std; 14 | 15 | struct MyData1 16 | { 17 | uint32_t a, b, c, d; 18 | 19 | // DATA_IO_LOAD_SAVE(MyData1, &a&b&c&d) 20 | 21 | template void load(DataIO& dio) { dio &a&b&c&d; } 22 | template void save(DataIO& dio) const { dio &a&b&c&d; } 23 | DATA_IO_OPTIMIZE_ELEMEN_LOAD(MyData1, &a&b&c&d) 24 | DATA_IO_OPTIMIZE_ELEMEN_SAVE(MyData1, &a&b&c&d) 25 | DATA_IO_OPTIMIZE_VECTOR_LOAD(MyData1, &a&b&c&d) 26 | DATA_IO_OPTIMIZE_VECTOR_SAVE(MyData1, &a&b&c&d) 27 | DATA_IO_OPTIMIZE_ARRAY__LOAD(MyData1, &a&b&c&d) 28 | DATA_IO_OPTIMIZE_ARRAY__SAVE(MyData1, &a&b&c&d) 29 | DATA_IO_REG_LOAD(MyData1) 30 | DATA_IO_REG_SAVE(MyData1) 31 | DATA_IO_OPTIMIZE_ELEMEN_LOAD_REG(friend, DATA_IO_IDENTITY, MyData1) 32 | DATA_IO_OPTIMIZE_ELEMEN_SAVE_REG(friend, DATA_IO_IDENTITY, MyData1) 33 | DATA_IO_OPTIMIZE_VECTOR_LOAD_REG(friend, MyData1, MyData1) 34 | DATA_IO_OPTIMIZE_VECTOR_SAVE_REG(friend, MyData1, MyData1) 35 | DATA_IO_OPTIMIZE_ARRAY__LOAD_REG(friend, MyData1, MyData1) 36 | DATA_IO_OPTIMIZE_ARRAY__SAVE_REG(friend, MyData1, MyData1) 37 | }; 38 | namespace nark { 39 | DataIO_IsDump_TypeTrue1(MyData1) 40 | } 41 | 42 | struct MyData2 43 | { 44 | uint32_t a, b, c, d; 45 | }; 46 | // &a&c&b&d is not in true seq, raise assert 47 | //DATA_IO_LOAD_SAVE_E(MyData2, &a&c&b&d) 48 | DATA_IO_LOAD_SAVE_E(MyData2, &a&b&c&d) 49 | 50 | struct MyData3 51 | { 52 | uint32_t a, b, c, d; 53 | }; 54 | DATA_IO_LOAD_SAVE_EV(MyData3, 2, &a&b&c&d) 55 | 56 | template 57 | void gen_rand(Iter first, Iter last) 58 | { 59 | for (Iter i = first; i != last; ++i) 60 | { 61 | i->a = rand(); 62 | i->b = rand(); 63 | i->c = rand(); 64 | i->d = rand(); 65 | } 66 | } 67 | 68 | template 69 | void gen_rand_pair(Iter first, Iter last) 70 | { 71 | for (Iter i = first; i != last; ++i) 72 | { 73 | i->first = rand(); 74 | i->second = rand(); 75 | } 76 | } 77 | 78 | struct Less 79 | { 80 | template 81 | bool operator()(const T& x, const T& y) const 82 | { 83 | return memcmp(&x, &y, sizeof(T)) < 0; 84 | } 85 | }; 86 | 87 | struct Equal 88 | { 89 | template 90 | bool operator()(const T& x, const T& y) const 91 | { 92 | return memcmp(&x, &y, sizeof(T)) == 0; 93 | } 94 | }; 95 | 96 | int main(int argc, char* argv[]) 97 | { 98 | printf("sizeof(vector)=%d\n", (int)sizeof(vector)); 99 | int count = 1000; 100 | vector v1, w1; 101 | vector > v2, w2; 102 | vector v3, w3; 103 | vector v4, w4; 104 | vector v5, w5; 105 | vector > v6, w6; 106 | 107 | MyData1 arr[100], arr2[100]; 108 | gen_rand(arr, arr+100); 109 | v1.resize(count); 110 | v2.resize(count); 111 | v3.resize(count); 112 | v4.resize(count); 113 | v5.resize(count); 114 | v6.resize(count); 115 | 116 | for (int i = 0; i != count; ++i) v1[i] = rand(); 117 | 118 | gen_rand_pair(v2.begin(), v2.end()); 119 | gen_rand(v3.begin(), v3.end()); 120 | gen_rand(v4.begin(), v4.end()); 121 | gen_rand(v5.begin(), v5.end()); 122 | gen_rand_pair(v6.begin(), v6.end()); 123 | 124 | { 125 | NativeDataOutput oar; 126 | NativeDataInput iar; 127 | #include "body.h" 128 | } 129 | 130 | { 131 | PortableDataOutput oar; 132 | PortableDataInput iar; 133 | #include "body.h" 134 | } 135 | 136 | { 137 | NativeNoVarIntOutput oar; 138 | NativeNoVarIntInput iar; 139 | #include "body.h" 140 | } 141 | 142 | { 143 | PortableNoVarIntOutput oar; 144 | PortableNoVarIntInput iar; 145 | #include "body.h" 146 | } 147 | 148 | return 0; 149 | } 150 | 151 | -------------------------------------------------------------------------------- /test/src/TestCorrection/body.h: -------------------------------------------------------------------------------- 1 | 2 | int n0, n1, n2, n3, n4, n5, n6, n7; 3 | int m0, m1, m2, m3, m4, m5, m6, m7; 4 | n0 = oar.tell(); oar << v1; n1 = oar.tell() - n0; 5 | n0 = oar.tell(); oar << v2; n2 = oar.tell() - n0; 6 | n0 = oar.tell(); oar << v3; n3 = oar.tell() - n0; 7 | n0 = oar.tell(); oar << v4; n4 = oar.tell() - n0; 8 | n0 = oar.tell(); oar << v5; n5 = oar.tell() - n0; 9 | n0 = oar.tell(); oar << v6; n6 = oar.tell() - n0; 10 | n0 = oar.tell(); oar << arr; n7 = oar.tell() - n0; 11 | 12 | iar.set(oar.begin(), oar.current()); 13 | w1.clear(); 14 | w2.clear(); 15 | w3.clear(); 16 | w4.clear(); 17 | w5.clear(); 18 | w6.clear(); 19 | m0 = iar.diff(oar.begin()); iar >> w1; m1 = iar.diff(oar.begin()) - m0; 20 | m0 = iar.diff(oar.begin()); iar >> w2; m2 = iar.diff(oar.begin()) - m0; 21 | m0 = iar.diff(oar.begin()); iar >> w3; m3 = iar.diff(oar.begin()) - m0; 22 | m0 = iar.diff(oar.begin()); iar >> w4; m4 = iar.diff(oar.begin()) - m0; 23 | m0 = iar.diff(oar.begin()); iar >> w5; m5 = iar.diff(oar.begin()) - m0; 24 | m0 = iar.diff(oar.begin()); iar >> w6; m6 = iar.diff(oar.begin()) - m0; 25 | m0 = iar.diff(oar.begin()); iar >> arr2;m7 = iar.diff(oar.begin()) - m0; 26 | 27 | assert(iar.eof()); 28 | 29 | assert(m1 == n1); 30 | assert(m2 == n2); 31 | assert(m3 == n3); 32 | assert(m4 == n4); 33 | assert(m5 == n5); 34 | assert(m6 == n6); 35 | assert(m7 == n7); 36 | 37 | assert(v1.size() == w1.size()); 38 | assert(v2.size() == w2.size()); 39 | assert(v3.size() == w3.size()); 40 | assert(v4.size() == w4.size()); 41 | assert(v5.size() == w5.size()); 42 | assert(v6.size() == w6.size()); 43 | 44 | memcmp(&count, &count, 4); 45 | 46 | for (size_t i = 0, n = v1.size(); i < n; ++i) assert(Equal()(v1[i], w1[i])); 47 | for (size_t i = 0, n = v2.size(); i < n; ++i) assert(Equal()(v2[i], w2[i])); 48 | for (size_t i = 0, n = v3.size(); i < n; ++i) assert(Equal()(v3[i], w3[i])); 49 | for (size_t i = 0, n = v4.size(); i < n; ++i) assert(Equal()(v4[i], w4[i])); 50 | for (size_t i = 0, n = v5.size(); i < n; ++i) assert(Equal()(v5[i], w5[i])); 51 | for (size_t i = 0, n = v6.size(); i < n; ++i) assert(Equal()(v6[i], w6[i])); 52 | for (size_t i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i) assert(Equal()(arr[i], arr2[i])); 53 | --------------------------------------------------------------------------------