├── CMake └── cotire.cmake ├── CMakeLists.txt ├── LICENSE ├── README.md ├── WebContent ├── css │ ├── images │ │ ├── layers-2x.png │ │ ├── layers.png │ │ ├── marker-icon-2x.png │ │ ├── marker-icon.png │ │ ├── marker-shadow.png │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ └── ui-icons_cd0a0a_256x240.png │ ├── jquery-ui-timepicker-addon.min.css │ ├── jquery-ui.css │ ├── jquery-ui.min.css │ ├── jquery-ui.structure.css │ ├── jquery-ui.structure.min.css │ ├── jquery-ui.theme.css │ ├── jquery-ui.theme.min.css │ ├── leaflet.css │ ├── styles.css │ └── ui.jqgrid.css ├── images │ ├── android-icon.png │ ├── apple-icon.ico │ ├── chrome-icon.png │ ├── loading.gif │ ├── other-icon.png │ ├── twitter-icon.png │ └── windows-icon.ico ├── index.html └── js │ ├── d3.tip.js │ ├── d3 │ ├── LICENSE │ └── d3-3.5.5.min.js │ ├── global.js │ ├── histogram.js │ ├── i18n │ ├── grid.locale-ar.js │ ├── grid.locale-bg.js │ ├── grid.locale-ca.js │ ├── grid.locale-cn.js │ ├── grid.locale-cs.js │ ├── grid.locale-de.js │ ├── grid.locale-dk.js │ ├── grid.locale-el.js │ ├── grid.locale-en.js │ ├── grid.locale-es.js │ ├── grid.locale-fa.js │ ├── grid.locale-fi.js │ ├── grid.locale-fr.js │ ├── grid.locale-gl.js │ ├── grid.locale-he.js │ ├── grid.locale-hr.js │ ├── grid.locale-hu.js │ ├── grid.locale-id.js │ ├── grid.locale-is.js │ ├── grid.locale-it.js │ ├── grid.locale-ja.js │ ├── grid.locale-kr.js │ ├── grid.locale-lt.js │ ├── grid.locale-me.js │ ├── grid.locale-nl.js │ ├── grid.locale-no.js │ ├── grid.locale-pl.js │ ├── grid.locale-pt-br.js │ ├── grid.locale-pt.js │ ├── grid.locale-ro.js │ ├── grid.locale-ru.js │ ├── grid.locale-sk.js │ ├── grid.locale-sq.js │ ├── grid.locale-sr-latin.js │ ├── grid.locale-sr.js │ ├── grid.locale-sv.js │ ├── grid.locale-th.js │ ├── grid.locale-tr.js │ ├── grid.locale-tw.js │ ├── grid.locale-uk.js │ ├── grid.locale-vi.js │ ├── jquery-ui-timepicker-addon-i18n.js │ ├── jquery-ui-timepicker-addon-i18n.min.js │ ├── jquery-ui-timepicker-af.js │ ├── jquery-ui-timepicker-am.js │ ├── jquery-ui-timepicker-bg.js │ ├── jquery-ui-timepicker-ca.js │ ├── jquery-ui-timepicker-cs.js │ ├── jquery-ui-timepicker-da.js │ ├── jquery-ui-timepicker-de.js │ ├── jquery-ui-timepicker-el.js │ ├── jquery-ui-timepicker-es.js │ ├── jquery-ui-timepicker-et.js │ ├── jquery-ui-timepicker-eu.js │ ├── jquery-ui-timepicker-fa.js │ ├── jquery-ui-timepicker-fi.js │ ├── jquery-ui-timepicker-fr.js │ ├── jquery-ui-timepicker-gl.js │ ├── jquery-ui-timepicker-he.js │ ├── jquery-ui-timepicker-hr.js │ ├── jquery-ui-timepicker-hu.js │ ├── jquery-ui-timepicker-id.js │ ├── jquery-ui-timepicker-it.js │ ├── jquery-ui-timepicker-ja.js │ ├── jquery-ui-timepicker-ko.js │ ├── jquery-ui-timepicker-lt.js │ ├── jquery-ui-timepicker-lv.js │ ├── jquery-ui-timepicker-mk.js │ ├── jquery-ui-timepicker-nl.js │ ├── jquery-ui-timepicker-no.js │ ├── jquery-ui-timepicker-pl.js │ ├── jquery-ui-timepicker-pt-BR.js │ ├── jquery-ui-timepicker-pt.js │ ├── jquery-ui-timepicker-ro.js │ ├── jquery-ui-timepicker-ru.js │ ├── jquery-ui-timepicker-sk.js │ ├── jquery-ui-timepicker-sl.js │ ├── jquery-ui-timepicker-sr-RS.js │ ├── jquery-ui-timepicker-sr-YU.js │ ├── jquery-ui-timepicker-sv.js │ ├── jquery-ui-timepicker-th.js │ ├── jquery-ui-timepicker-tr.js │ ├── jquery-ui-timepicker-uk.js │ ├── jquery-ui-timepicker-vi.js │ ├── jquery-ui-timepicker-zh-CN.js │ └── jquery-ui-timepicker-zh-TW.js │ ├── images │ ├── layers-2x.png │ ├── layers.png │ ├── marker-icon-2x.png │ ├── marker-icon.png │ └── marker-shadow.png │ ├── jquery-2.1.4.min.js │ ├── jquery-dateFormat.min.js │ ├── jquery-ui-1.11.4.min.js │ ├── jquery-ui-sliderAccess.js │ ├── jquery-ui-timepicker-addon.min.js │ ├── jquery.jqGrid.min.js │ ├── leaflet-hashedcubes.js │ ├── leaflet-src.js │ ├── leaflet.js │ ├── linechart.js │ ├── loadmap.js │ ├── loadui.js │ ├── scatterchart.js │ ├── sql.js │ └── view_schemas.js ├── csv.7z ├── data.7z ├── include ├── SQLiteCpp │ ├── Assertion.h │ ├── Backup.cpp │ ├── Backup.h │ ├── Column.cpp │ ├── Column.h │ ├── Database.cpp │ ├── Database.h │ ├── Exception.h │ ├── SQLiteCpp.h │ ├── Statement.cpp │ ├── Statement.h │ ├── Transaction.cpp │ └── Transaction.h ├── boost │ └── serialization │ │ └── tuple.hpp ├── meerkat │ ├── LICENSE │ ├── meerkat.c │ └── meerkat.h ├── rapidjson │ ├── allocators.h │ ├── document.h │ ├── encodedstream.h │ ├── encodings.h │ ├── error │ │ ├── en.h │ │ └── error.h │ ├── filereadstream.h │ ├── filewritestream.h │ ├── internal │ │ ├── biginteger.h │ │ ├── diyfp.h │ │ ├── dtoa.h │ │ ├── ieee754.h │ │ ├── itoa.h │ │ ├── meta.h │ │ ├── pow10.h │ │ ├── stack.h │ │ ├── strfunc.h │ │ └── strtod.h │ ├── memorybuffer.h │ ├── memorystream.h │ ├── msinttypes │ │ ├── inttypes.h │ │ └── stdint.h │ ├── prettywriter.h │ ├── rapidjson.h │ ├── reader.h │ ├── stringbuffer.h │ └── writer.h └── sqlite │ ├── sqlite3.c │ └── sqlite3.h ├── src ├── CategoricalDimension.cpp ├── CategoricalDimension.h ├── CategoricalNode.cpp ├── CategoricalNode.h ├── CategoricalPivot.h ├── CategoricalSerializer.cpp ├── CategoricalSerializer.h ├── DMPLoader.cpp ├── DMPLoader.h ├── Data.cpp ├── Data.h ├── DataGenerator.h ├── DataLoader.cpp ├── DataLoader.h ├── Date.h ├── FlightsDelayLoader.cpp ├── FlightsDelayLoader.h ├── FlightsLoader.h ├── FlightsPerformanceLoader.cpp ├── FlightsPerformanceLoader.h ├── HashedCube.cpp ├── HashedCube.h ├── HashedCubeInstances.cpp ├── HashedCubeInstances.h ├── Hashing.h ├── InMemoryData.cpp ├── InMemoryData.h ├── InMemoryDataDescriptor.h ├── InMemoryDataGenerator.cpp ├── InMemoryDataGenerator.h ├── Mercator.h ├── MySQLSerializer.cpp ├── MySQLSerializer.h ├── Nanocubes.h ├── Pivot.h ├── Query.cpp ├── Query.h ├── ResidentSetSize.h ├── Response.h ├── SQLData.cpp ├── SQLData.h ├── ScatterSerializer.cpp ├── ScatterSerializer.h ├── Serializer.h ├── Server.cpp ├── Server.h ├── SnapLoader.cpp ├── SnapLoader.h ├── SpatialDimension.cpp ├── SpatialDimension.h ├── SpatialSerializer.cpp ├── SpatialSerializer.h ├── SplomLoader.cpp ├── SplomLoader.h ├── StringUtil.cpp ├── StringUtil.h ├── TemporalDimension.cpp ├── TemporalDimension.h ├── TemporalInterval.h ├── TemporalNode.cpp ├── TemporalNode.h ├── TemporalPivot.h ├── TemporalSerializer.cpp ├── TemporalSerializer.h ├── TileNode.cpp ├── TileNode.h ├── TilePivot.h ├── TripLoader.cpp ├── TripLoader.h ├── Trunc.h ├── TwitterSQL.h ├── Types.cpp ├── Types.h ├── main.cpp ├── stdafx.cpp └── stdafx.h └── xml ├── brightkite-immens.xml ├── brightkite-nanocubes.xml └── gowalla.xml /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (hashedcubes) 2 | cmake_minimum_required (VERSION 3.0) 3 | 4 | if(WIN32) 5 | if (MSVC) 6 | set(CMAKE_CXX_FLAGS "/EHsc") 7 | endif() 8 | 9 | set(BOOST_LIBRARYDIR "C:/Boost/lib/") 10 | set(BOOST_INCLUDEDIR "C:/Boost/include/boost-1_62/") 11 | endif() 12 | 13 | if(UNIX) 14 | set(CMAKE_CXX_FLAGS "-std=c++14") 15 | endif() 16 | 17 | set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake") 18 | 19 | include(cotire) 20 | 21 | aux_source_directory(. SRC_LIST) 22 | 23 | include_directories(AFTER ./) 24 | include_directories(AFTER src) 25 | include_directories(AFTER include) 26 | include_directories(AFTER include/sqlite) 27 | 28 | file(GLOB_RECURSE HEADERS "src/*.h") 29 | source_group("Header Files" FILES ${HEADERS}) 30 | 31 | add_executable (${PROJECT_NAME} ${SRC_LIST} ${HEADERS} 32 | include/sqlite/sqlite3.c 33 | include/meerkat/meerkat.c 34 | include/SQLiteCpp/Backup.cpp 35 | include/SQLiteCpp/Column.cpp 36 | include/SQLiteCpp/Database.cpp 37 | include/SQLiteCpp/Statement.cpp 38 | include/SQLiteCpp/Transaction.cpp 39 | src/CategoricalDimension.cpp 40 | src/CategoricalNode.cpp 41 | src/CategoricalSerializer.cpp 42 | src/Data.cpp 43 | src/DataLoader.cpp 44 | src/DMPLoader.cpp 45 | src/FlightsDelayLoader.cpp 46 | src/FlightsPerformanceLoader.cpp 47 | src/HashedCube.cpp 48 | src/HashedCubeInstances.cpp 49 | src/InMemoryData.cpp 50 | src/InMemoryDataGenerator.cpp 51 | src/main.cpp 52 | src/MySQLSerializer.cpp 53 | src/Query.cpp 54 | src/ScatterSerializer.cpp 55 | src/Server.cpp 56 | src/SnapLoader.cpp 57 | src/SpatialDimension.cpp 58 | src/SpatialSerializer.cpp 59 | src/SplomLoader.cpp 60 | src/SQLData.cpp 61 | src/StringUtil.cpp 62 | src/TemporalDimension.cpp 63 | src/TemporalNode.cpp 64 | src/TemporalSerializer.cpp 65 | src/TileNode.cpp 66 | src/TripLoader.cpp 67 | src/Types.cpp 68 | ) 69 | 70 | find_package(Threads REQUIRED) 71 | 72 | set(Boost_USE_MULTITHREAD ON) 73 | set(Boost_USE_STATIC_LIBS ON) 74 | 75 | find_package(Boost 1.62 COMPONENTS system filesystem serialization iostreams program_options REQUIRED) 76 | 77 | include_directories(${Boost_INCLUDE_DIR}) 78 | link_directories(${Boost_LIBRARY_DIR}) 79 | 80 | target_link_libraries (${PROJECT_NAME} LINK_PUBLIC ${CMAKE_DL_LIBS} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 81 | 82 | set_target_properties(${PROJECT_NAME} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "src/stdafx.h") 83 | 84 | cotire(${PROJECT_NAME}) 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Hashedcubes: Simple, Low Memory, Real-Time Visual Exploration of Big Data** 2 | 3 | Hashedcubes is formulated on the simple idea that a combination of progressive partitioning and sorting, along with a compact representation of data subsets, allows to create a data structure that efficiently stores and query spatiotemporal datasets. 4 | 5 | The underlying concept behind Hashedcubes makes it natural to create links between the data structure and original records, thus encouraging to complement the visual queries with additional information stored in an external database. 6 | 7 | **How To Build Hashedcubes** 8 | 9 | Hashedcubes depends on Boost 1.62 or later and CMake 3.0 or later, both on Windows and Linux. 10 | 11 | To build and run on Linux: 12 | 13 | 1- extract csv.7z and data.7z 14 | 15 | 2- cd build 16 | 17 | 3- cmake -DCMAKE_BUILD_TYPE=Release .. 18 | 19 | 4- make 20 | 21 | 5- cd .. && cp build/hashedcubes . 22 | 23 | 6- ./hashedcubes 24 | 25 | __Web interface: [http://localhost:8000]__ 26 | 27 | __To list all command line parameters: ./hashedcubes -h__ 28 | -------------------------------------------------------------------------------- /WebContent/css/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/layers-2x.png -------------------------------------------------------------------------------- /WebContent/css/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/layers.png -------------------------------------------------------------------------------- /WebContent/css/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/marker-icon-2x.png -------------------------------------------------------------------------------- /WebContent/css/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/marker-icon.png -------------------------------------------------------------------------------- /WebContent/css/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/marker-shadow.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /WebContent/css/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/css/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /WebContent/css/jquery-ui-timepicker-addon.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery Timepicker Addon - v1.6.1 - 2015-11-14 2 | * http://trentrichardson.com/examples/timepicker 3 | * Copyright (c) 2015 Trent Richardson; Licensed MIT */ 4 | 5 | .ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-tpicker-grid-label{background:0 0;border:0;margin:0;padding:0}.ui-timepicker-div .ui_tpicker_unit_hide{display:none}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input{background:0 0;color:inherit;border:0;outline:0;border-bottom:solid 1px #555;width:95%}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus{border-bottom-color:#aaa}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}.ui-timepicker-div.ui-timepicker-oneLine{padding-right:2px}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,.ui-timepicker-div.ui-timepicker-oneLine dt{display:none}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label{display:block;padding-top:2px}.ui-timepicker-div.ui-timepicker-oneLine dl{text-align:right}.ui-timepicker-div.ui-timepicker-oneLine dl dd,.ui-timepicker-div.ui-timepicker-oneLine dl dd>div{display:inline-block;margin:0}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before{content:':';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before{content:'.';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{display:none} -------------------------------------------------------------------------------- /WebContent/css/styles.css: -------------------------------------------------------------------------------- 1 | .axis { 2 | shape-rendering: crispEdges; 3 | } 4 | 5 | .x.axis path { 6 | stroke: #ddd; 7 | } 8 | 9 | .x.axis line { 10 | stroke: #ddd; 11 | stroke-opacity: .5; 12 | } 13 | 14 | .y.axis line { 15 | stroke: #ddd; 16 | } 17 | 18 | path.line { 19 | fill: none; 20 | stroke: #000; 21 | stroke-width: .5px; 22 | } 23 | 24 | rect.pane { 25 | cursor: move; 26 | fill: none; 27 | pointer-events: all; 28 | } 29 | 30 | .d3-tip { 31 | z-index: 901; 32 | line-height: 1; 33 | font-weight: bold; 34 | padding: 6px; 35 | background: rgba(0, 0, 0, 1); 36 | color: #fff; 37 | border-radius: 4px; 38 | 39 | font-family: sans-serif; 40 | font-size: 13px; 41 | } 42 | 43 | .d3-tip:after { 44 | z-index: 901; 45 | box-sizing: border-box; 46 | display: inline; 47 | font-size: 10px; 48 | width: 100%; 49 | line-height: 1; 50 | color: rgba(0, 0, 0, 1); 51 | content: "\25BC"; 52 | position: absolute; 53 | text-align: center; 54 | } 55 | 56 | .d3-tip.n:after { 57 | z-index: 901; 58 | margin: -1px 0 0 0; 59 | top: 100%; 60 | left: 0; 61 | } 62 | 63 | body, html { 64 | margin: 0; 65 | padding: 0; 66 | height: 100%; 67 | position: relative; 68 | background: rgba(0.3, 0.3, 0.3, 1); 69 | font-family: sans-serif; 70 | 71 | overflow-y:hidden; 72 | overflow-x:hidden; 73 | } 74 | 75 | #container { 76 | display: none; 77 | 78 | width: 100vw; 79 | height: 100vh; 80 | position: relative; 81 | } 82 | 83 | #right-section { 84 | 85 | width: 100vw; 86 | height: 100vh; 87 | position: relative; 88 | 89 | 90 | float: right; 91 | background: rgba(0, 0, 0, .75); 92 | } 93 | 94 | #loading { 95 | display: block; 96 | position: absolute; 97 | top: 0; 98 | left: 0; 99 | z-index: 100; 100 | width: 100vw; 101 | height: 100vh; 102 | background-color: white; 103 | background-image: url("/images/loading.gif"); 104 | background-repeat: no-repeat; 105 | background-position: center; 106 | } 107 | 108 | #map { 109 | width: 100%; 110 | height: 80%; 111 | position: absolute; 112 | top: 0; 113 | left: 0; 114 | } 115 | 116 | #progressbar { 117 | width: 400px; 118 | position: absolute; 119 | left: 42px; 120 | z-index: 900; 121 | font-size: 70%; 122 | margin-top: 10px; 123 | background: rgba(0, 0, 0, .5); 124 | text-align: center; 125 | } 126 | 127 | #slider { 128 | z-index: 900; 129 | position: absolute; 130 | left: 192px; 131 | margin-top: 45px; 132 | 133 | width: 238px; 134 | } 135 | 136 | #label-slider { 137 | z-index: 900; 138 | position: absolute; 139 | left: 42px; 140 | margin-top: 40px; 141 | 142 | 143 | font: 12px sans-serif; 144 | 145 | text-align: center; 146 | float: left; 147 | 148 | line-height: 200%; 149 | font-weight: bold; 150 | color: black; 151 | background-color : #d1d1d1; 152 | } 153 | 154 | #label { 155 | width: 400px; 156 | position: absolute; 157 | left: 32px; 158 | z-index: 900; 159 | font: 12px sans-serif; 160 | margin-top: 11px; 161 | 162 | text-align: center; 163 | float: left; 164 | 165 | line-height: 200%; 166 | font-weight: bold; 167 | color: white; 168 | } 169 | 170 | #tabs { 171 | width: 370px; 172 | position: absolute; 173 | right: 50px; 174 | z-index: 900; 175 | font-size: 70%; 176 | margin-top: 10px; 177 | background: rgba(0, 0, 0, .1); 178 | } 179 | 180 | #section { 181 | position: absolute; 182 | z-index: 900; 183 | margin-top: 80vh; 184 | width: 100vw; 185 | height: 20vh; 186 | float: bottom; 187 | background: rgba(0, 0, 0, .75); 188 | } 189 | 190 | #top-section { 191 | position: absolute; 192 | margin-top: 65vh; 193 | left: 0vw; 194 | width: 100vw; 195 | height: 15vh; 196 | float: bottom; 197 | z-index: 900; 198 | background: rgba(0, 0, 0, .35); 199 | } 200 | 201 | .main text { 202 | font: 10px sans-serif; 203 | } 204 | 205 | .axis path, 206 | .axis line { 207 | fill: none; 208 | stroke: #000; 209 | shape-rendering: crispEdges; 210 | } 211 | 212 | .line { 213 | fill: none; 214 | stroke: steelblue; 215 | stroke-width: 1.5px; 216 | } 217 | 218 | .leaflet-container { 219 | background: rgba(255, 255, 255, .72) !important; 220 | } -------------------------------------------------------------------------------- /WebContent/images/android-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/android-icon.png -------------------------------------------------------------------------------- /WebContent/images/apple-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/apple-icon.ico -------------------------------------------------------------------------------- /WebContent/images/chrome-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/chrome-icon.png -------------------------------------------------------------------------------- /WebContent/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/loading.gif -------------------------------------------------------------------------------- /WebContent/images/other-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/other-icon.png -------------------------------------------------------------------------------- /WebContent/images/twitter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/twitter-icon.png -------------------------------------------------------------------------------- /WebContent/images/windows-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/images/windows-icon.ico -------------------------------------------------------------------------------- /WebContent/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | 44 | 53 | 54 | 55 | 56 |
57 |
58 |
59 |
...
60 |
61 |
62 | 63 | 64 |
65 | 66 |
67 |
68 |
69 | 70 |
71 | 72 |
73 | 74 |
75 |
76 |
77 | 78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /WebContent/js/d3.tip.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"function"==typeof define&&define.amd?define(["d3"],e):"object"==typeof module&&module.exports?module.exports=function(t){return t.tip=e(t),t.tip}:t.d3.tip=e(t.d3)}(this,function(t){return function(){function e(t){T=d(t),b=T.createSVGPoint(),document.body.appendChild(w)}function n(){return"n"}function r(){return[0,0]}function o(){return" "}function u(){var t=g();return{top:t.n.y-w.offsetHeight,left:t.n.x-w.offsetWidth/2}}function f(){var t=g();return{top:t.s.y,left:t.s.x-w.offsetWidth/2}}function i(){var t=g();return{top:t.e.y-w.offsetHeight/2,left:t.e.x}}function l(){var t=g();return{top:t.w.y-w.offsetHeight/2,left:t.w.x-w.offsetWidth}}function s(){var t=g();return{top:t.nw.y-w.offsetHeight,left:t.nw.x-w.offsetWidth}}function a(){var t=g();return{top:t.ne.y-w.offsetHeight,left:t.ne.x}}function c(){var t=g();return{top:t.sw.y,left:t.sw.x-w.offsetWidth}}function p(){var t=g();return{top:t.se.y,left:t.e.x}}function y(){var e=t.select(document.createElement("div"));return e.style({position:"absolute",top:0,opacity:0,"pointer-events":"none","box-sizing":"border-box"}),e.node()}function d(t){return t=t.node(),"svg"===t.tagName.toLowerCase()?t:t.ownerSVGElement}function m(){return null===w&&(w=y(),document.body.appendChild(w)),t.select(w)}function g(){for(var e=C||t.event.target;"undefined"==typeof e.getScreenCTM&&"undefined"===e.parentNode;)e=e.parentNode;var n={},r=e.getScreenCTM(),o=e.getBBox(),u=o.width,f=o.height,i=o.x,l=o.y;return b.x=i,b.y=l,n.nw=b.matrixTransform(r),b.x+=u,n.ne=b.matrixTransform(r),b.y+=f,n.se=b.matrixTransform(r),b.x-=u,n.sw=b.matrixTransform(r),b.y-=f/2,n.w=b.matrixTransform(r),b.x+=u,n.e=b.matrixTransform(r),b.x-=u/2,b.y-=f/2,n.n=b.matrixTransform(r),b.y+=f,n.s=b.matrixTransform(r),n}var h=n,x=r,v=o,w=y(),T=null,b=null,C=null;e.show=function(){var t=Array.prototype.slice.call(arguments);t[t.length-1]instanceof SVGElement&&(C=t.pop());var n,r=v.apply(this,t),o=x.apply(this,t),u=h.apply(this,t),f=m(),i=H.length,l=document.documentElement.scrollTop||document.body.scrollTop,s=document.documentElement.scrollLeft||document.body.scrollLeft;for(f.html(r).style({opacity:1,"pointer-events":"all"});i--;)f.classed(H[i],!1);return n=E.get(u).apply(this),f.classed(u,!0).style({top:n.top+o[0]+l+"px",left:n.left+o[1]+s+"px"}),e},e.hide=function(){var t=m();return t.style({opacity:0,"pointer-events":"none"}),e},e.attr=function(n,r){if(arguments.length<2&&"string"==typeof n)return m().attr(n);var o=Array.prototype.slice.call(arguments);return t.selection.prototype.attr.apply(m(),o),e},e.style=function(n,r){if(arguments.length<2&&"string"==typeof n)return m().style(n);var o=Array.prototype.slice.call(arguments);return t.selection.prototype.style.apply(m(),o),e},e.direction=function(n){return arguments.length?(h=null==n?n:t.functor(n),e):h},e.offset=function(n){return arguments.length?(x=null==n?n:t.functor(n),e):x},e.html=function(n){return arguments.length?(v=null==n?n:t.functor(n),e):v},e.destroy=function(){return w&&(m().remove(),w=null),e};var E=t.map({n:u,s:f,e:i,w:l,nw:s,ne:a,sw:c,se:p}),H=E.keys();return e}}); -------------------------------------------------------------------------------- /WebContent/js/d3/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2015, Michael Bostock 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * The name Michael Bostock may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, 21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /WebContent/js/global.js: -------------------------------------------------------------------------------- 1 | var callbacks = null; 2 | 3 | var region = null, where = "", tseries = "", tile = null; 4 | var curr_region = null, curr_where = null, curr_tseries = null; 5 | 6 | var update = false; 7 | var update_tile = false; 8 | 9 | var curr_heatmap_resolution = 8, heatmap_resolution = 8; 10 | 11 | var total_count = 0, curr_count = 0; 12 | var lower_bound = null, upper_bound = null; 13 | var curr_lower_bound = null, curr_upper_bound = null; 14 | 15 | var currTile = 0; 16 | 17 | function roundtile(v, z) { 18 | v = Math.floor(v); 19 | while (v < 0) v += 1 << z; 20 | return v % (1 << z); 21 | } 22 | 23 | function tilex2lon(x, z) { 24 | return x / Math.pow(2.0, z) * 360.0 - 180; 25 | } 26 | 27 | function tiley2lat(y, z) { 28 | var n = Math.PI - 2.0 * Math.PI * y / Math.pow(2.0, z); 29 | return 180.0 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); 30 | } 31 | 32 | function lon2tilex(lon, z) { 33 | return ((lon + 180.0) / 360.0 * Math.pow(2.0, z)); 34 | } 35 | 36 | function lat2tiley(lat, z) { 37 | return ((1.0 - Math.log(Math.tan(lat * Math.PI / 180.0) + 1.0 / Math.cos(lat * Math.PI / 180.0)) / Math.PI) / 2.0 * Math.pow(2.0, z)); 38 | } -------------------------------------------------------------------------------- /WebContent/js/histogram.js: -------------------------------------------------------------------------------- 1 | function setHistogramData(data, entry) { 2 | 3 | var margin = { 4 | top : 10, 5 | right : 20, 6 | bottom : 33, 7 | left : 20 8 | }; 9 | 10 | var div = d3.select("#" + entry.field.name); 11 | 12 | var maxValue = -1; 13 | for (var index in data) { 14 | 15 | if (data[index][1] > maxValue) 16 | maxValue = data[index][1]; 17 | } 18 | 19 | var w = div.node().getBoundingClientRect().width - margin.left - margin.right; 20 | var h = div.node().getBoundingClientRect().height - margin.top - margin.bottom; 21 | 22 | var barPadding = 1; 23 | 24 | div.selectAll("*").remove(); 25 | 26 | var tip = d3.tip() 27 | .attr('class', 'd3-tip') 28 | .offset([-10, 0]) 29 | .html(function(d) { 30 | return "Value: " + d[1] + ""; 31 | }); 32 | 33 | 34 | div = div.append("svg").attr("width", w + margin.left + margin.right).attr("height", h + margin.top + margin.bottom).append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")").call(tip); 35 | 36 | 37 | var colors = ['#007399', 'Gray'] 38 | 39 | div.selectAll("rect").data(data).enter().append("rect") 40 | .attr("x", function(d, i) { 41 | return i * (w / data.length); 42 | }).attr("y", function(d) { 43 | return h - (d[1] / maxValue * h); 44 | }).attr("width", w / data.length - barPadding).attr("height", function(d) { 45 | return d[1] / maxValue * h; 46 | }).attr("fill", function(d) { 47 | return colors[0]; 48 | }) 49 | .on('mouseover', tip.show) 50 | .on('mouseout', tip.hide) 51 | .on('mouseup', function () { console.log("update"); }) 52 | .each(function () { 53 | var selection = d3.select(this); 54 | var state = true; 55 | selection.on('mousedown', function () { 56 | if (state) { 57 | selection.style('fill', colors[1]); 58 | } else { 59 | selection.style('fill', colors[0]); 60 | } 61 | state = !state; 62 | div.selectAll("rect").each(function (d) { console.log(d3.select(this).style("fill")) }); 63 | 64 | }); 65 | }); 66 | 67 | div.selectAll("text").data(data).enter().append("text") 68 | .text(function (d, i) { 69 | return entry.field.values[d[0]]; 70 | }).attr("cx", "0").attr("cy", "0") 71 | .attr("font-family", "sans-serif") 72 | .attr("font-size", "11px") 73 | .attr("fill", "white") 74 | .attr("text-anchor", "start") 75 | .attr("transform", function (d, i) { 76 | var x = Math.max(4, h - (d[1] / maxValue * h) - this.getComputedTextLength() - 4); 77 | var y = - (i * (w / data.length) + (w / data.length - barPadding) / 2) + 4; 78 | return 'rotate(90)translate(' + x + ',' + y + ')'; 79 | }); 80 | } -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-af.js: -------------------------------------------------------------------------------- 1 | /* Afrikaans translation for the jQuery Timepicker Addon */ 2 | /* Written by Deon Heyns */ 3 | (function($) { 4 | $.timepicker.regional['af'] = { 5 | timeOnlyTitle: 'Kies Tyd', 6 | timeText: 'Tyd ', 7 | hourText: 'Ure ', 8 | minuteText: 'Minute', 9 | secondText: 'Sekondes', 10 | millisecText: 'Millisekondes', 11 | microsecText: 'Mikrosekondes', 12 | timezoneText: 'Tydsone', 13 | currentText: 'Huidige Tyd', 14 | closeText: 'Klaar', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['af']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-am.js: -------------------------------------------------------------------------------- 1 | /* Armenian translation for the jQuery Timepicker Addon */ 2 | /* Written by Artavazd Avetisyan artavazda@hotmail.com */ 3 | (function($) { 4 | $.timepicker.regional['am'] = { 5 | timeOnlyTitle: 'Ընտրեք ժամանակը', 6 | timeText: 'Ժամանակը', 7 | hourText: 'Ժամ', 8 | minuteText: 'Րոպե', 9 | secondText: 'Վարկյան', 10 | millisecText: 'Միլիվարկյան', 11 | microsecText: 'Միկրովարկյան', 12 | timezoneText: 'Ժամային գոտին', 13 | currentText: 'Այժմ', 14 | closeText: 'Փակել', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['am']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-bg.js: -------------------------------------------------------------------------------- 1 | /* Bulgarian translation for the jQuery Timepicker Addon */ 2 | /* Written by Plamen Kovandjiev */ 3 | (function($) { 4 | $.timepicker.regional['bg'] = { 5 | timeOnlyTitle: 'Изберете време', 6 | timeText: 'Време', 7 | hourText: 'Час', 8 | minuteText: 'Минути', 9 | secondText: 'Секунди', 10 | millisecText: 'Милисекунди', 11 | microsecText: 'Микросекунди', 12 | timezoneText: 'Часови пояс', 13 | currentText: 'Сега', 14 | closeText: 'Затвори', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['bg']); 22 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-ca.js: -------------------------------------------------------------------------------- 1 | /* Catalan translation for the jQuery Timepicker Addon */ 2 | /* Written by Sergi Faber */ 3 | (function($) { 4 | $.timepicker.regional['ca'] = { 5 | timeOnlyTitle: 'Escollir una hora', 6 | timeText: 'Hora', 7 | hourText: 'Hores', 8 | minuteText: 'Minuts', 9 | secondText: 'Segons', 10 | millisecText: 'Milisegons', 11 | microsecText: 'Microsegons', 12 | timezoneText: 'Fus horari', 13 | currentText: 'Ara', 14 | closeText: 'Tancar', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['ca']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-cs.js: -------------------------------------------------------------------------------- 1 | /* Czech translation for the jQuery Timepicker Addon */ 2 | /* Written by Ondřej Vodáček */ 3 | (function($) { 4 | $.timepicker.regional['cs'] = { 5 | timeOnlyTitle: 'Vyberte čas', 6 | timeText: 'Čas', 7 | hourText: 'Hodiny', 8 | minuteText: 'Minuty', 9 | secondText: 'Vteřiny', 10 | millisecText: 'Milisekundy', 11 | microsecText: 'Mikrosekundy', 12 | timezoneText: 'Časové pásmo', 13 | currentText: 'Nyní', 14 | closeText: 'Zavřít', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['dop.', 'AM', 'A'], 18 | pmNames: ['odp.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['cs']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-da.js: -------------------------------------------------------------------------------- 1 | /* Danish translation for the jQuery Timepicker Addon */ 2 | /* Written by Lars H. Jensen (http://www.larshj.dk) */ 3 | (function ($) { 4 | $.timepicker.regional['da'] = { 5 | timeOnlyTitle: 'Vælg tid', 6 | timeText: 'Tid', 7 | hourText: 'Time', 8 | minuteText: 'Minut', 9 | secondText: 'Sekund', 10 | millisecText: 'Millisekund', 11 | microsecText: 'Mikrosekund', 12 | timezoneText: 'Tidszone', 13 | currentText: 'Nu', 14 | closeText: 'Luk', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['am', 'AM', 'A'], 18 | pmNames: ['pm', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['da']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-de.js: -------------------------------------------------------------------------------- 1 | /* German translation for the jQuery Timepicker Addon */ 2 | /* Written by Marvin */ 3 | (function($) { 4 | $.timepicker.regional['de'] = { 5 | timeOnlyTitle: 'Zeit wählen', 6 | timeText: 'Zeit', 7 | hourText: 'Stunde', 8 | minuteText: 'Minute', 9 | secondText: 'Sekunde', 10 | millisecText: 'Millisekunde', 11 | microsecText: 'Mikrosekunde', 12 | timezoneText: 'Zeitzone', 13 | currentText: 'Jetzt', 14 | closeText: 'Fertig', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['vorm.', 'AM', 'A'], 18 | pmNames: ['nachm.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['de']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-el.js: -------------------------------------------------------------------------------- 1 | /* Hellenic translation for the jQuery Timepicker Addon */ 2 | /* Written by Christos Pontikis */ 3 | (function($) { 4 | $.timepicker.regional['el'] = { 5 | timeOnlyTitle: 'Επιλογή ώρας', 6 | timeText: 'Ώρα', 7 | hourText: 'Ώρες', 8 | minuteText: 'Λεπτά', 9 | secondText: 'Δευτερόλεπτα', 10 | millisecText: 'μιλιδευτερόλεπτο', 11 | microsecText: 'Microseconds', 12 | timezoneText: 'Ζώνη ώρας', 13 | currentText: 'Τώρα', 14 | closeText: 'Κλείσιμο', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['π.μ.', 'AM', 'A'], 18 | pmNames: ['μ.μ.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['el']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-es.js: -------------------------------------------------------------------------------- 1 | /* Spanish translation for the jQuery Timepicker Addon */ 2 | /* Written by Ianaré Sévi */ 3 | /* Modified by Carlos Martínez */ 4 | (function($) { 5 | $.timepicker.regional['es'] = { 6 | timeOnlyTitle: 'Elegir una hora', 7 | timeText: 'Hora', 8 | hourText: 'Horas', 9 | minuteText: 'Minutos', 10 | secondText: 'Segundos', 11 | millisecText: 'Milisegundos', 12 | microsecText: 'Microsegundos', 13 | timezoneText: 'Uso horario', 14 | currentText: 'Hoy', 15 | closeText: 'Cerrar', 16 | timeFormat: 'HH:mm', 17 | timeSuffix: '', 18 | amNames: ['a.m.', 'AM', 'A'], 19 | pmNames: ['p.m.', 'PM', 'P'], 20 | isRTL: false 21 | }; 22 | $.timepicker.setDefaults($.timepicker.regional['es']); 23 | })(jQuery); 24 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-et.js: -------------------------------------------------------------------------------- 1 | /* Estonian translation for the jQuery Timepicker Addon */ 2 | /* Written by Karl Sutt (karl@sutt.ee) */ 3 | (function($) { 4 | $.timepicker.regional['et'] = { 5 | timeOnlyTitle: 'Vali aeg', 6 | timeText: 'Aeg', 7 | hourText: 'Tund', 8 | minuteText: 'Minut', 9 | secondText: 'Sekund', 10 | millisecText: 'Millisekundis', 11 | microsecText: 'Mikrosekundis', 12 | timezoneText: 'Ajavöönd', 13 | currentText: 'Praegu', 14 | closeText: 'Valmis', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['et']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-eu.js: -------------------------------------------------------------------------------- 1 | /* Basque trannslation for JQuery Timepicker Addon */ 2 | /* Translated by Xabi Fer */ 3 | /* Fixed by Asier Iturralde Sarasola - iametza interaktiboa */ 4 | (function($) { 5 | $.timepicker.regional['eu'] = { 6 | timeOnlyTitle: 'Aukeratu ordua', 7 | timeText: 'Ordua', 8 | hourText: 'Orduak', 9 | minuteText: 'Minutuak', 10 | secondText: 'Segundoak', 11 | millisecText: 'Milisegundoak', 12 | microsecText: 'Mikrosegundoak', 13 | timezoneText: 'Ordu-eremua', 14 | currentText: 'Orain', 15 | closeText: 'Itxi', 16 | timeFormat: 'HH:mm', 17 | timeSuffix: '', 18 | amNames: ['a.m.', 'AM', 'A'], 19 | pmNames: ['p.m.', 'PM', 'P'], 20 | isRTL: false 21 | }; 22 | $.timepicker.setDefaults($.timepicker.regional['eu']); 23 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-fa.js: -------------------------------------------------------------------------------- 1 | /* Persian translation for the jQuery Timepicker Addon */ 2 | /* Written by Meysam Pour Ganji */ 3 | (function($) { 4 | $.timepicker.regional['fa'] = { 5 | timeOnlyTitle: 'انتخاب زمان', 6 | timeText: 'زمان', 7 | hourText: 'ساعت', 8 | minuteText: 'دقیقه', 9 | secondText: 'ثانیه', 10 | millisecText: 'میلی ثانیه', 11 | microsecText: 'میکرو ثانیه', 12 | timezoneText: 'منطقه زمانی', 13 | currentText: 'الان', 14 | closeText: 'انتخاب', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['قبل ظهر', 'AM', 'A'], 18 | pmNames: ['بعد ظهر', 'PM', 'P'], 19 | isRTL: true 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['fa']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-fi.js: -------------------------------------------------------------------------------- 1 | /* Finnish translation for the jQuery Timepicker Addon */ 2 | /* Written by Juga Paazmaya (http://github.com/paazmaya) */ 3 | (function($) { 4 | $.timepicker.regional['fi'] = { 5 | timeOnlyTitle: 'Valitse aika', 6 | timeText: 'Aika', 7 | hourText: 'Tunti', 8 | minuteText: 'Minuutti', 9 | secondText: 'Sekunti', 10 | millisecText: 'Millisekunnin', 11 | microsecText: 'Mikrosekuntia', 12 | timezoneText: 'Aikavyöhyke', 13 | currentText: 'Nyt', 14 | closeText: 'Sulje', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['ap.', 'AM', 'A'], 18 | pmNames: ['ip.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['fi']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-fr.js: -------------------------------------------------------------------------------- 1 | /* French translation for the jQuery Timepicker Addon */ 2 | /* Written by Thomas Lété */ 3 | (function($) { 4 | $.timepicker.regional['fr'] = { 5 | timeOnlyTitle: 'Choisir une heure', 6 | timeText: 'Heure', 7 | hourText: 'Heures', 8 | minuteText: 'Minutes', 9 | secondText: 'Secondes', 10 | millisecText: 'Millisecondes', 11 | microsecText: 'Microsecondes', 12 | timezoneText: 'Fuseau horaire', 13 | currentText: 'Maintenant', 14 | closeText: 'Terminé', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['fr']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-gl.js: -------------------------------------------------------------------------------- 1 | /* Galician translation for the jQuery Timepicker Addon */ 2 | /* Written by David Barral */ 3 | (function($) { 4 | $.timepicker.regional['gl'] = { 5 | timeOnlyTitle: 'Elixir unha hora', 6 | timeText: 'Hora', 7 | hourText: 'Horas', 8 | minuteText: 'Minutos', 9 | secondText: 'Segundos', 10 | millisecText: 'Milisegundos', 11 | microsecText: 'Microssegundos', 12 | timezoneText: 'Fuso horario', 13 | currentText: 'Agora', 14 | closeText: 'Pechar', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['a.m.', 'AM', 'A'], 18 | pmNames: ['p.m.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['gl']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-he.js: -------------------------------------------------------------------------------- 1 | /* Hebrew translation for the jQuery Timepicker Addon */ 2 | /* Written by Lior Lapid */ 3 | (function($) { 4 | $.timepicker.regional["he"] = { 5 | timeOnlyTitle: "בחירת זמן", 6 | timeText: "שעה", 7 | hourText: "שעות", 8 | minuteText: "דקות", 9 | secondText: "שניות", 10 | millisecText: "אלפית השנייה", 11 | microsecText: "מיקרו", 12 | timezoneText: "אזור זמן", 13 | currentText: "עכשיו", 14 | closeText:"סגור", 15 | timeFormat: "HH:mm", 16 | timeSuffix: '', 17 | amNames: ['לפנה"צ', 'AM', 'A'], 18 | pmNames: ['אחה"צ', 'PM', 'P'], 19 | isRTL: true 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional["he"]); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-hr.js: -------------------------------------------------------------------------------- 1 | /* Croatian translation for the jQuery Timepicker Addon */ 2 | /* Written by Mladen */ 3 | (function($) { 4 | $.timepicker.regional['hr'] = { 5 | timeOnlyTitle: 'Odaberi vrijeme', 6 | timeText: 'Vrijeme', 7 | hourText: 'Sati', 8 | minuteText: 'Minute', 9 | secondText: 'Sekunde', 10 | millisecText: 'Milisekunde', 11 | microsecText: 'Mikrosekunde', 12 | timezoneText: 'Vremenska zona', 13 | currentText: 'Sada', 14 | closeText: 'Gotovo', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['a.m.', 'AM', 'A'], 18 | pmNames: ['p.m.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['hr']); 22 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-hu.js: -------------------------------------------------------------------------------- 1 | /* Hungarian translation for the jQuery Timepicker Addon */ 2 | /* Written by Vas Gábor */ 3 | (function($) { 4 | $.timepicker.regional['hu'] = { 5 | timeOnlyTitle: 'Válasszon időpontot', 6 | timeText: 'Idő', 7 | hourText: 'Óra', 8 | minuteText: 'Perc', 9 | secondText: 'Másodperc', 10 | millisecText: 'Milliszekundumos', 11 | microsecText: 'Ezredmásodperc', 12 | timezoneText: 'Időzóna', 13 | currentText: 'Most', 14 | closeText: 'Kész', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['de.', 'AM', 'A'], 18 | pmNames: ['du.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['hu']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-id.js: -------------------------------------------------------------------------------- 1 | /* Indonesian translation for the jQuery Timepicker Addon */ 2 | /* Written by Nia */ 3 | (function($) { 4 | $.timepicker.regional['id'] = { 5 | timeOnlyTitle: 'Pilih Waktu', 6 | timeText: 'Waktu', 7 | hourText: 'Pukul', 8 | minuteText: 'Menit', 9 | secondText: 'Detik', 10 | millisecText: 'Milidetik', 11 | microsecText: 'Mikrodetik', 12 | timezoneText: 'Zona Waktu', 13 | currentText: 'Sekarang', 14 | closeText: 'OK', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['id']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-it.js: -------------------------------------------------------------------------------- 1 | /* Italian translation for the jQuery Timepicker Addon */ 2 | /* Written by Marco "logicoder" Del Tongo */ 3 | (function($) { 4 | $.timepicker.regional['it'] = { 5 | timeOnlyTitle: 'Scegli orario', 6 | timeText: 'Orario', 7 | hourText: 'Ora', 8 | minuteText: 'Minuti', 9 | secondText: 'Secondi', 10 | millisecText: 'Millisecondi', 11 | microsecText: 'Microsecondi', 12 | timezoneText: 'Fuso orario', 13 | currentText: 'Adesso', 14 | closeText: 'Chiudi', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['m.', 'AM', 'A'], 18 | pmNames: ['p.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['it']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-ja.js: -------------------------------------------------------------------------------- 1 | /* Japanese translation for the jQuery Timepicker Addon */ 2 | /* Written by Jun Omae */ 3 | (function($) { 4 | $.timepicker.regional['ja'] = { 5 | timeOnlyTitle: '時間を選択', 6 | timeText: '時間', 7 | hourText: '時', 8 | minuteText: '分', 9 | secondText: '秒', 10 | millisecText: 'ミリ秒', 11 | microsecText: 'マイクロ秒', 12 | timezoneText: 'タイムゾーン', 13 | currentText: '現時刻', 14 | closeText: '閉じる', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['午前', 'AM', 'A'], 18 | pmNames: ['午後', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['ja']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-ko.js: -------------------------------------------------------------------------------- 1 | /* Korean translation for the jQuery Timepicker Addon */ 2 | /* Written by Genie */ 3 | (function($) { 4 | $.timepicker.regional['ko'] = { 5 | timeOnlyTitle: '시간 선택', 6 | timeText: '시간', 7 | hourText: '시', 8 | minuteText: '분', 9 | secondText: '초', 10 | millisecText: '밀리초', 11 | microsecText: '마이크로', 12 | timezoneText: '표준 시간대', 13 | currentText: '현재 시각', 14 | closeText: '닫기', 15 | timeFormat: 'tt h:mm', 16 | timeSuffix: '', 17 | amNames: ['오전', 'AM', 'A'], 18 | pmNames: ['오후', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['ko']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-lt.js: -------------------------------------------------------------------------------- 1 | /* Lithuanian translation for the jQuery Timepicker Addon */ 2 | /* Written by Irmantas Šiupšinskas */ 3 | (function($) { 4 | $.timepicker.regional['lt'] = { 5 | timeOnlyTitle: 'Pasirinkite laiką', 6 | timeText: 'Laikas', 7 | hourText: 'Valandos', 8 | minuteText: 'Minutės', 9 | secondText: 'Sekundės', 10 | millisecText: 'Milisekundės', 11 | microsecText: 'Mikrosekundės', 12 | timezoneText: 'Laiko zona', 13 | currentText: 'Dabar', 14 | closeText: 'Uždaryti', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['priešpiet', 'AM', 'A'], 18 | pmNames: ['popiet', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['lt']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-lv.js: -------------------------------------------------------------------------------- 1 | /* Latvian translation for the jQuery Timepicker Addon */ 2 | /* Written by Dmitry Bogatykh */ 3 | (function($) { 4 | $.timepicker.regional['lv'] = { 5 | timeOnlyTitle: 'Ievadiet laiku', 6 | timeText: 'Laiks', 7 | hourText: 'Stundas', 8 | minuteText: 'Minūtes', 9 | secondText: 'Sekundes', 10 | millisecText: 'Milisekundes', 11 | microsecText: 'Mikrosekundes', 12 | timezoneText: 'Laika josla', 13 | currentText: 'Tagad', 14 | closeText: 'Aizvērt', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'AM', 'A'], 18 | pmNames: ['PM', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['lv']); 22 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-mk.js: -------------------------------------------------------------------------------- 1 | /* Macedonian cyrilic translation for the jQuery Timepicker Addon */ 2 | /* Written by Vlatko Ristovski */ 3 | (function($) { 4 | $.timepicker.regional['mk'] = { 5 | timeOnlyTitle: 'Одберете време', 6 | timeText: 'Време', 7 | hourText: 'Час', 8 | minuteText: 'Минути', 9 | secondText: 'Секунди', 10 | millisecText: 'Милисекунди', 11 | microsecText: 'Микросекунди', 12 | timezoneText: 'Временска зона', 13 | currentText: 'Сега', 14 | closeText: 'Затвори', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['mk']); 22 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-nl.js: -------------------------------------------------------------------------------- 1 | /* Dutch translation for the jQuery Timepicker Addon */ 2 | /* Written by Martijn van der Lee */ 3 | (function($) { 4 | $.timepicker.regional['nl'] = { 5 | timeOnlyTitle: 'Tijdstip', 6 | timeText: 'Tijd', 7 | hourText: 'Uur', 8 | minuteText: 'Minuut', 9 | secondText: 'Seconde', 10 | millisecText: 'Milliseconde', 11 | microsecText: 'Microseconde', 12 | timezoneText: 'Tijdzone', 13 | currentText: 'Vandaag', 14 | closeText: 'Sluiten', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['nl']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-no.js: -------------------------------------------------------------------------------- 1 | /* Norwegian translation for the jQuery Timepicker Addon */ 2 | /* Written by Morten Hauan (http://hauan.me) */ 3 | (function($) { 4 | $.timepicker.regional['no'] = { 5 | timeOnlyTitle: 'Velg tid', 6 | timeText: 'Tid', 7 | hourText: 'Time', 8 | minuteText: 'Minutt', 9 | secondText: 'Sekund', 10 | millisecText: 'Millisekund', 11 | microsecText: 'mikrosekund', 12 | timezoneText: 'Tidssone', 13 | currentText: 'Nå', 14 | closeText: 'Lukk', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['am', 'AM', 'A'], 18 | pmNames: ['pm', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['no']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-pl.js: -------------------------------------------------------------------------------- 1 | /* Polish translation for the jQuery Timepicker Addon */ 2 | /* Written by Michał Pena */ 3 | (function($) { 4 | $.timepicker.regional['pl'] = { 5 | timeOnlyTitle: 'Wybierz godzinę', 6 | timeText: 'Czas', 7 | hourText: 'Godzina', 8 | minuteText: 'Minuta', 9 | secondText: 'Sekunda', 10 | millisecText: 'Milisekunda', 11 | microsecText: 'Mikrosekunda', 12 | timezoneText: 'Strefa czasowa', 13 | currentText: 'Teraz', 14 | closeText: 'Gotowe', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['pl']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-pt-BR.js: -------------------------------------------------------------------------------- 1 | /* Brazilian Portuguese translation for the jQuery Timepicker Addon */ 2 | /* Written by Diogo Damiani (diogodamiani@gmail.com) */ 3 | (function ($) { 4 | $.timepicker.regional['pt-BR'] = { 5 | timeOnlyTitle: 'Escolha o horário', 6 | timeText: 'Horário', 7 | hourText: 'Hora', 8 | minuteText: 'Minutos', 9 | secondText: 'Segundos', 10 | millisecText: 'Milissegundos', 11 | microsecText: 'Microssegundos', 12 | timezoneText: 'Fuso horário', 13 | currentText: 'Agora', 14 | closeText: 'Fechar', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['a.m.', 'AM', 'A'], 18 | pmNames: ['p.m.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['pt-BR']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-pt.js: -------------------------------------------------------------------------------- 1 | /* Portuguese translation for the jQuery Timepicker Addon */ 2 | /* Written by Luan Almeida */ 3 | (function($) { 4 | $.timepicker.regional['pt'] = { 5 | timeOnlyTitle: 'Escolha uma hora', 6 | timeText: 'Hora', 7 | hourText: 'Horas', 8 | minuteText: 'Minutos', 9 | secondText: 'Segundos', 10 | millisecText: 'Milissegundos', 11 | microsecText: 'Microssegundos', 12 | timezoneText: 'Fuso horário', 13 | currentText: 'Agora', 14 | closeText: 'Fechar', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['a.m.', 'AM', 'A'], 18 | pmNames: ['p.m.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['pt']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-ro.js: -------------------------------------------------------------------------------- 1 | /* Romanian translation for the jQuery Timepicker Addon */ 2 | /* Written by Romeo Adrian Cioaba */ 3 | (function($) { 4 | $.timepicker.regional['ro'] = { 5 | timeOnlyTitle: 'Alegeţi o oră', 6 | timeText: 'Timp', 7 | hourText: 'Ore', 8 | minuteText: 'Minute', 9 | secondText: 'Secunde', 10 | millisecText: 'Milisecunde', 11 | microsecText: 'Microsecunde', 12 | timezoneText: 'Fus orar', 13 | currentText: 'Acum', 14 | closeText: 'Închide', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['ro']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-ru.js: -------------------------------------------------------------------------------- 1 | /* Russian translation for the jQuery Timepicker Addon */ 2 | /* Written by Trent Richardson */ 3 | (function($) { 4 | $.timepicker.regional['ru'] = { 5 | timeOnlyTitle: 'Выберите время', 6 | timeText: 'Время', 7 | hourText: 'Часы', 8 | minuteText: 'Минуты', 9 | secondText: 'Секунды', 10 | millisecText: 'Миллисекунды', 11 | microsecText: 'Микросекунды', 12 | timezoneText: 'Часовой пояс', 13 | currentText: 'Сейчас', 14 | closeText: 'Закрыть', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['ru']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-sk.js: -------------------------------------------------------------------------------- 1 | /* Slovak translation for the jQuery Timepicker Addon */ 2 | /* Written by David Vallner */ 3 | (function($) { 4 | $.timepicker.regional['sk'] = { 5 | timeOnlyTitle: 'Zvoľte čas', 6 | timeText: 'Čas', 7 | hourText: 'Hodiny', 8 | minuteText: 'Minúty', 9 | secondText: 'Sekundy', 10 | millisecText: 'Milisekundy', 11 | microsecText: 'Mikrosekundy', 12 | timezoneText: 'Časové pásmo', 13 | currentText: 'Teraz', 14 | closeText: 'Zavrieť', 15 | timeFormat: 'H:m', 16 | timeSuffix: '', 17 | amNames: ['dop.', 'AM', 'A'], 18 | pmNames: ['pop.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['sk']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-sl.js: -------------------------------------------------------------------------------- 1 | /* Slovenian translation for the jQuery Timepicker Addon */ 2 | /* Written by Hadalin (https://github.com/hadalin) */ 3 | (function($) { 4 | $.timepicker.regional['sl'] = { 5 | timeOnlyTitle: 'Izberite čas', 6 | timeText: 'Čas', 7 | hourText: 'Ura', 8 | minuteText: 'Minute', 9 | secondText: 'Sekunde', 10 | millisecText: 'Milisekunde', 11 | microsecText: 'Mikrosekunde', 12 | timezoneText: 'Časovni pas', 13 | currentText: 'Sedaj', 14 | closeText: 'Zapri', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['dop.', 'AM', 'A'], 18 | pmNames: ['pop.', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['sl']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-sr-RS.js: -------------------------------------------------------------------------------- 1 | /* Serbian cyrilic translation for the jQuery Timepicker Addon */ 2 | /* Written by Vladimir Jelovac */ 3 | (function($) { 4 | $.timepicker.regional['sr-RS'] = { 5 | timeOnlyTitle: 'Одаберите време', 6 | timeText: 'Време', 7 | hourText: 'Сати', 8 | minuteText: 'Минути', 9 | secondText: 'Секунде', 10 | millisecText: 'Милисекунде', 11 | microsecText: 'Микросекунде', 12 | timezoneText: 'Временска зона', 13 | currentText: 'Сада', 14 | closeText: 'Затвори', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['sr-RS']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-sr-YU.js: -------------------------------------------------------------------------------- 1 | /* Serbian latin translation for the jQuery Timepicker Addon */ 2 | /* Written by Vladimir Jelovac */ 3 | (function($) { 4 | $.timepicker.regional['sr-YU'] = { 5 | timeOnlyTitle: 'Odaberite vreme', 6 | timeText: 'Vreme', 7 | hourText: 'Sati', 8 | minuteText: 'Minuti', 9 | secondText: 'Sekunde', 10 | millisecText: 'Milisekunde', 11 | microsecText: 'Mikrosekunde', 12 | timezoneText: 'Vremenska zona', 13 | currentText: 'Sada', 14 | closeText: 'Zatvori', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['sr-YU']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-sv.js: -------------------------------------------------------------------------------- 1 | /* Swedish translation for the jQuery Timepicker Addon */ 2 | /* Written by Nevon */ 3 | (function($) { 4 | $.timepicker.regional['sv'] = { 5 | timeOnlyTitle: 'Välj en tid', 6 | timeText: 'Tid', 7 | hourText: 'Timme', 8 | minuteText: 'Minut', 9 | secondText: 'Sekund', 10 | millisecText: 'Millisekund', 11 | microsecText: 'Mikrosekund', 12 | timezoneText: 'Tidszon', 13 | currentText: 'Nu', 14 | closeText: 'Stäng', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['sv']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-th.js: -------------------------------------------------------------------------------- 1 | /* Thai translation for the jQuery Timepicker Addon */ 2 | /* Written by Yote Wachirapornpongsa */ 3 | (function($) { 4 | $.timepicker.regional['th'] = { 5 | timeOnlyTitle: 'เลือกเวลา', 6 | timeText: 'เวลา ', 7 | hourText: 'ชั่วโมง ', 8 | minuteText: 'นาที', 9 | secondText: 'วินาที', 10 | millisecText: 'มิลลิวินาที', 11 | microsecText: 'ไมโคริวินาที', 12 | timezoneText: 'เขตเวลา', 13 | currentText: 'เวลาปัจจุบัน', 14 | closeText: 'ปิด', 15 | timeFormat: 'hh:mm tt', 16 | timeSuffix: '' 17 | }; 18 | $.timepicker.setDefaults($.timepicker.regional['th']); 19 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-tr.js: -------------------------------------------------------------------------------- 1 | /* Turkish translation for the jQuery Timepicker Addon */ 2 | /* Written by Fehmi Can Saglam, Edited by Goktug Ozturk */ 3 | (function($) { 4 | $.timepicker.regional['tr'] = { 5 | timeOnlyTitle: 'Zaman Seçiniz', 6 | timeText: 'Zaman', 7 | hourText: 'Saat', 8 | minuteText: 'Dakika', 9 | secondText: 'Saniye', 10 | millisecText: 'Milisaniye', 11 | microsecText: 'Mikrosaniye', 12 | timezoneText: 'Zaman Dilimi', 13 | currentText: 'Şu an', 14 | closeText: 'Tamam', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['ÖÖ', 'Ö'], 18 | pmNames: ['ÖS', 'S'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['tr']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-uk.js: -------------------------------------------------------------------------------- 1 | /* Ukrainian translation for the jQuery Timepicker Addon */ 2 | /* Written by Sergey Noskov */ 3 | (function($) { 4 | $.timepicker.regional['uk'] = { 5 | timeOnlyTitle: 'Виберіть час', 6 | timeText: 'Час', 7 | hourText: 'Години', 8 | minuteText: 'Хвилини', 9 | secondText: 'Секунди', 10 | millisecText: 'Мілісекунди', 11 | microsecText: 'Мікросекунди', 12 | timezoneText: 'Часовий пояс', 13 | currentText: 'Зараз', 14 | closeText: 'Закрити', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['uk']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-vi.js: -------------------------------------------------------------------------------- 1 | /* Vietnamese translation for the jQuery Timepicker Addon */ 2 | /* Written by Nguyen Dinh Trung */ 3 | (function($) { 4 | $.timepicker.regional['vi'] = { 5 | timeOnlyTitle: 'Chọn giờ', 6 | timeText: 'Thời gian', 7 | hourText: 'Giờ', 8 | minuteText: 'Phút', 9 | secondText: 'Giây', 10 | millisecText: 'Mili giây', 11 | microsecText: 'Micrô giây', 12 | timezoneText: 'Múi giờ', 13 | currentText: 'Hiện thời', 14 | closeText: 'Đóng', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['SA', 'S'], 18 | pmNames: ['CH', 'C'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['vi']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-zh-CN.js: -------------------------------------------------------------------------------- 1 | /* Simplified Chinese translation for the jQuery Timepicker Addon / 2 | / Written by Will Lu */ 3 | (function($) { 4 | $.timepicker.regional['zh-CN'] = { 5 | timeOnlyTitle: '选择时间', 6 | timeText: '时间', 7 | hourText: '小时', 8 | minuteText: '分钟', 9 | secondText: '秒钟', 10 | millisecText: '毫秒', 11 | microsecText: '微秒', 12 | timezoneText: '时区', 13 | currentText: '现在时间', 14 | closeText: '关闭', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['AM', 'A'], 18 | pmNames: ['PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['zh-CN']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/i18n/jquery-ui-timepicker-zh-TW.js: -------------------------------------------------------------------------------- 1 | /* Chinese translation for the jQuery Timepicker Addon */ 2 | /* Written by Alang.lin */ 3 | (function($) { 4 | $.timepicker.regional['zh-TW'] = { 5 | timeOnlyTitle: '選擇時分秒', 6 | timeText: '時間', 7 | hourText: '時', 8 | minuteText: '分', 9 | secondText: '秒', 10 | millisecText: '毫秒', 11 | microsecText: '微秒', 12 | timezoneText: '時區', 13 | currentText: '現在時間', 14 | closeText: '確定', 15 | timeFormat: 'HH:mm', 16 | timeSuffix: '', 17 | amNames: ['上午', 'AM', 'A'], 18 | pmNames: ['下午', 'PM', 'P'], 19 | isRTL: false 20 | }; 21 | $.timepicker.setDefaults($.timepicker.regional['zh-TW']); 22 | })(jQuery); 23 | -------------------------------------------------------------------------------- /WebContent/js/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/js/images/layers-2x.png -------------------------------------------------------------------------------- /WebContent/js/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/js/images/layers.png -------------------------------------------------------------------------------- /WebContent/js/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/js/images/marker-icon-2x.png -------------------------------------------------------------------------------- /WebContent/js/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/js/images/marker-icon.png -------------------------------------------------------------------------------- /WebContent/js/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/WebContent/js/images/marker-shadow.png -------------------------------------------------------------------------------- /WebContent/js/jquery-ui-sliderAccess.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Slider Access 3 | * By: Trent Richardson [http://trentrichardson.com] 4 | * Version 0.3 5 | * Last Modified: 10/20/2012 6 | * 7 | * Copyright 2011 Trent Richardson 8 | * Dual licensed under the MIT and GPL licenses. 9 | * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt 10 | * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt 11 | * 12 | */ 13 | (function($){ 14 | 15 | $.fn.extend({ 16 | sliderAccess: function(options){ 17 | options = options || {}; 18 | options.touchonly = options.touchonly !== undefined? options.touchonly : true; // by default only show it if touch device 19 | 20 | if(options.touchonly === true && !("ontouchend" in document)){ 21 | return $(this); 22 | } 23 | 24 | return $(this).each(function(i,obj){ 25 | var $t = $(this), 26 | o = $.extend({},{ 27 | where: 'after', 28 | step: $t.slider('option','step'), 29 | upIcon: 'ui-icon-plus', 30 | downIcon: 'ui-icon-minus', 31 | text: false, 32 | upText: '+', 33 | downText: '-', 34 | buttonset: true, 35 | buttonsetTag: 'span', 36 | isRTL: false 37 | }, options), 38 | $buttons = $('<'+ o.buttonsetTag +' class="ui-slider-access">'+ 39 | ''+ 40 | ''+ 41 | ''); 42 | 43 | $buttons.children('button').each(function(j, jobj){ 44 | var $jt = $(this); 45 | $jt.button({ 46 | text: o.text, 47 | icons: { primary: $jt.data('icon') } 48 | }) 49 | .click(function(e){ 50 | var step = $jt.data('step'), 51 | curr = $t.slider('value'), 52 | newval = curr += step*1, 53 | minval = $t.slider('option','min'), 54 | maxval = $t.slider('option','max'), 55 | slidee = $t.slider("option", "slide") || function(){}, 56 | stope = $t.slider("option", "stop") || function(){}; 57 | 58 | e.preventDefault(); 59 | 60 | if(newval < minval || newval > maxval){ 61 | return; 62 | } 63 | 64 | $t.slider('value', newval); 65 | 66 | slidee.call($t, null, { value: newval }); 67 | stope.call($t, null, { value: newval }); 68 | }); 69 | }); 70 | 71 | // before or after 72 | $t[o.where]($buttons); 73 | 74 | if(o.buttonset){ 75 | $buttons.removeClass('ui-corner-right').removeClass('ui-corner-left').buttonset(); 76 | $buttons.eq(0).addClass('ui-corner-left'); 77 | $buttons.eq(1).addClass('ui-corner-right'); 78 | } 79 | 80 | // adjust the width so we don't break the original layout 81 | var bOuterWidth = $buttons.css({ 82 | marginLeft: ((o.where === 'after' && !o.isRTL) || (o.where === 'before' && o.isRTL)? 10:0), 83 | marginRight: ((o.where === 'before' && !o.isRTL) || (o.where === 'after' && o.isRTL)? 10:0) 84 | }).outerWidth(true) + 5; 85 | var tOuterWidth = $t.outerWidth(true); 86 | $t.css('display','inline-block').width(tOuterWidth-bOuterWidth); 87 | }); 88 | } 89 | }); 90 | 91 | })(jQuery); -------------------------------------------------------------------------------- /WebContent/js/scatterchart.js: -------------------------------------------------------------------------------- 1 | function setSctterChart(data, entry) { 2 | 3 | var margin = { 4 | top : 0, 5 | right : 15, 6 | bottom : 23, 7 | left : 25 8 | }; 9 | 10 | var div = d3.select("#" + entry.field.name); 11 | 12 | var width = div.node().getBoundingClientRect().width; 13 | var height = div.node().getBoundingClientRect().height - 32; 14 | 15 | var scatter_width = width - margin.left -margin.right; 16 | var scatter_height = height - margin.top - margin.bottom; 17 | 18 | var max = d3.max(data, function(d) { return d[2]; }); 19 | 20 | var x = d3.scale.linear() 21 | .domain([0, 23]) 22 | .range([ 0, scatter_width - (scatter_width / 24)]); 23 | 24 | var y = d3.scale.linear() 25 | .domain([0, 6]) 26 | .range([ scatter_height - (scatter_height / 7), 0 ]); 27 | 28 | div.selectAll("*").remove(); 29 | 30 | var tip = d3.tip() 31 | .attr('class', 'd3-tip') 32 | .offset([-10, 0]) 33 | .html(function(d) { 34 | return "Day: " + d[1] + "" + 35 | "
Hour: " + d[0] + "" + 36 | "
Value: " + d[2] + ""; 37 | }); 38 | 39 | var main = div 40 | .append("svg") 41 | .attr("width", width) 42 | .attr('height', height) 43 | .attr("class", "chart"); 44 | 45 | var chart = main.append("g") 46 | .attr("transform", "translate(" + (margin.left)+ "," + (margin.top) + ")") 47 | .attr("width", scatter_width) 48 | .attr("height", scatter_height) 49 | .attr("class", "main") 50 | .call(tip); 51 | 52 | // draw the x axis 53 | var xAxis = d3.svg.axis() 54 | .scale(x) 55 | .ticks(24) 56 | .orient('bottom'); 57 | 58 | main.append('svg:g') 59 | .attr('transform', 'translate(' + (margin.left + (scatter_width / 48)) + ',' + (height - margin.bottom) + ')') 60 | .attr('class', 'main axis a') 61 | .call(xAxis).attr("font-family", "sans-serif").attr("font-size", "11px").attr("fill", "white").attr("text-anchor", "middle");; 62 | 63 | // draw the y axis 64 | var yAxis = d3.svg.axis() 65 | .scale(y) 66 | .ticks(7) 67 | .orient('left'); 68 | 69 | main.append('svg:g') 70 | .attr('transform', 'translate(' + (margin.left) + ',' + (margin.top + (scatter_height / 14)) + ')') 71 | .attr('class', 'main axis b') 72 | .call(yAxis).attr("font-family", "sans-serif").attr("font-size", "11px").attr("fill", "white").attr("text-anchor", "middle");; 73 | 74 | var color = d3.scale.linear() 75 | .domain([0.3, 1]) 76 | .range(["black", "steelblue"]); 77 | 78 | chart.selectAll("scatter-dots") 79 | .data(data) 80 | .enter().append("rect") 81 | .attr("x", function(d) { return d[0] * (scatter_width / 24); }) 82 | .attr("y", function(d) { return (6 - d[1]) * (scatter_height / 7); }) 83 | .attr("width", (scatter_width / 24) + .5) 84 | .attr("height", (scatter_height / 7) + .5) 85 | .attr("fill", function(d) { return color((d[2] / max)); }) 86 | .on('mouseover', tip.show) 87 | .on('mouseout', tip.hide); 88 | } -------------------------------------------------------------------------------- /WebContent/js/sql.js: -------------------------------------------------------------------------------- 1 | function loadMySQLPanel(data, entry) { 2 | 3 | var div = d3.select("#right-section"); 4 | div.selectAll("*").remove(); 5 | 6 | $("#right-section").append($('
')); 7 | $("#right-section").append($('
')); 8 | 9 | var names = []; 10 | var model = []; 11 | entry.field.values.forEach(function (value) { 12 | names.push(value.label); 13 | model.push({ align: value.align, width: value.width, /*label: value.label,*/ name: value.name, formatter: value.formatter }); 14 | }); 15 | 16 | $("#jqGrid").jqGrid({ 17 | datatype: "clientSide", 18 | data: data, 19 | colNames: names, 20 | colModel: model, 21 | caption: entry.title, 22 | pager: "#jqGridPager", 23 | rowNum: 100, 24 | viewrecords: true, 25 | loadonce: true, 26 | width: div.node().getBoundingClientRect().width, 27 | height: div.node().getBoundingClientRect().height - 84, 28 | }); 29 | 30 | 31 | 32 | $("#jqGrid").jqGrid('navGrid', '#jqGridPager', { 33 | add: false, 34 | del: false, 35 | edit: false, 36 | refresh: false, 37 | search: true, 38 | view: true, 39 | position: "left" 40 | }); 41 | } -------------------------------------------------------------------------------- /csv.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/csv.7z -------------------------------------------------------------------------------- /data.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cicerolp/hashedcubes/ff15e60f4449762c8282b66387dcb7bab836bf77/data.7z -------------------------------------------------------------------------------- /include/SQLiteCpp/Assertion.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Assertion.h 3 | * @ingroup SQLiteCpp 4 | * @brief Definition of the SQLITECPP_ASSERT() macro. 5 | * 6 | * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | 16 | /** 17 | * SQLITECPP_ASSERT SQLITECPP_ASSERT() is used in destructors, where exceptions shall not be thrown 18 | * 19 | * Define SQLITECPP_ENABLE_ASSERT_HANDLER at the project level 20 | * and define a SQLite::assertion_failed() assertion handler 21 | * to tell SQLiteC++ to use it instead of assert() when an assertion fail. 22 | */ 23 | #ifdef SQLITECPP_ENABLE_ASSERT_HANDLER 24 | 25 | // if an assert handler is provided by user code, use it instead of assert() 26 | namespace SQLite 27 | { 28 | // declaration of the assert handler to define in user code 29 | void assertion_failed(const char* apFile, const long apLine, const char* apFunc, 30 | const char* apExpr, const char* apMsg); 31 | 32 | #ifdef _MSC_VER 33 | #define __func__ __FUNCTION__ 34 | #endif 35 | // call the assert handler provided by user code 36 | #define SQLITECPP_ASSERT(expression, message) \ 37 | if (!(expression)) SQLite::assertion_failed(__FILE__, __LINE__, __func__, #expression, message) 38 | } // namespace SQLite 39 | 40 | #else 41 | 42 | // if no assert handler provided by user code, use standard assert() 43 | // (note: in release mode assert() does nothing) 44 | #define SQLITECPP_ASSERT(expression, message) assert(expression && message) 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/SQLiteCpp/Backup.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Backup.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Backup is used to backup a database file in a safe and online way. 5 | * 6 | * Copyright (c) 2015-2015 Shibao HONG (shibaohong@outlook.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | namespace SQLite 19 | { 20 | 21 | // Initialize resource for SQLite database backup 22 | Backup::Backup(Database& aDestDatabase, 23 | const char *apDestDatabaseName, 24 | Database& aSrcDatabase, 25 | const char *apSrcDatabaseName) : 26 | mpSQLiteBackup(NULL) 27 | { 28 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 29 | apDestDatabaseName, 30 | aSrcDatabase.getHandle(), 31 | apSrcDatabaseName); 32 | if (NULL == mpSQLiteBackup) 33 | { 34 | std::string strerr = sqlite3_errmsg(aDestDatabase.getHandle()); 35 | throw SQLite::Exception(strerr); 36 | } 37 | } 38 | 39 | // Initialize resource for SQLite database backup 40 | Backup::Backup(Database &aDestDatabase, 41 | const std::string &aDestDatabaseName, 42 | Database &aSrcDatabase, 43 | const std::string &aSrcDatabaseName) : 44 | mpSQLiteBackup(NULL) 45 | { 46 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 47 | aDestDatabaseName.c_str(), 48 | aSrcDatabase.getHandle(), 49 | aSrcDatabaseName.c_str()); 50 | if (NULL == mpSQLiteBackup) 51 | { 52 | std::string strerr = sqlite3_errmsg(aDestDatabase.getHandle()); 53 | throw SQLite::Exception(strerr); 54 | } 55 | } 56 | 57 | // Initialize resource for SQLite database backup 58 | Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) : 59 | mpSQLiteBackup(NULL) 60 | { 61 | mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(), 62 | "main", 63 | aSrcDatabase.getHandle(), 64 | "main"); 65 | if (NULL == mpSQLiteBackup) 66 | { 67 | std::string strerr = sqlite3_errmsg(aDestDatabase.getHandle()); 68 | throw SQLite::Exception(strerr); 69 | } 70 | } 71 | 72 | // Release resource for SQLite database backup 73 | Backup::~Backup() noexcept 74 | { 75 | if (NULL != mpSQLiteBackup) 76 | { 77 | sqlite3_backup_finish(mpSQLiteBackup); 78 | } 79 | } 80 | 81 | // Execute backup step with a given number of source pages to be copied 82 | int Backup::executeStep(const int aNumPage /* = -1 */) 83 | { 84 | const int res = sqlite3_backup_step(mpSQLiteBackup, aNumPage); 85 | if (SQLITE_OK != res && SQLITE_DONE != res && 86 | SQLITE_BUSY != res && SQLITE_LOCKED != res) 87 | { 88 | std::string strerr = sqlite3_errstr(res); 89 | throw SQLite::Exception(strerr); 90 | } 91 | return res; 92 | } 93 | 94 | // Get the number of remaining source pages to be copied in this backup process 95 | int Backup::remainingPageCount() 96 | { 97 | return sqlite3_backup_remaining(mpSQLiteBackup); 98 | } 99 | 100 | // Get the number of total source pages to be copied in this backup process 101 | int Backup::totalPageCount() 102 | { 103 | return sqlite3_backup_pagecount(mpSQLiteBackup); 104 | } 105 | 106 | } // namespace SQLite 107 | -------------------------------------------------------------------------------- /include/SQLiteCpp/Column.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Column.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement. 5 | * 6 | * Copyright (c) 2012-2016 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | 15 | 16 | namespace SQLite 17 | { 18 | 19 | 20 | // Encapsulation of a Column in a row of the result pointed by the prepared Statement. 21 | Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept : // nothrow 22 | mStmtPtr(aStmtPtr), 23 | mIndex(aIndex) 24 | { 25 | } 26 | 27 | // Finalize and unregister the SQL query from the SQLite Database Connection. 28 | Column::~Column() noexcept // nothrow 29 | { 30 | // the finalization will be done by the destructor of the last shared pointer 31 | } 32 | 33 | // Return the named assigned to this result column (potentially aliased) 34 | const char* Column::getName() const noexcept // nothrow 35 | { 36 | return sqlite3_column_name(mStmtPtr, mIndex); 37 | } 38 | 39 | #ifdef SQLITE_ENABLE_COLUMN_METADATA 40 | // Return the name of the table column that is the origin of this result column 41 | const char* Column::getOriginName() const noexcept // nothrow 42 | { 43 | return sqlite3_column_origin_name(mStmtPtr, mIndex); 44 | } 45 | #endif 46 | 47 | // Return the integer value of the column specified by its index starting at 0 48 | int Column::getInt() const noexcept // nothrow 49 | { 50 | return sqlite3_column_int(mStmtPtr, mIndex); 51 | } 52 | 53 | // Return the 64bits integer value of the column specified by its index starting at 0 54 | sqlite3_int64 Column::getInt64() const noexcept // nothrow 55 | { 56 | return sqlite3_column_int64(mStmtPtr, mIndex); 57 | } 58 | 59 | // Return the double value of the column specified by its index starting at 0 60 | double Column::getDouble() const noexcept // nothrow 61 | { 62 | return sqlite3_column_double(mStmtPtr, mIndex); 63 | } 64 | 65 | // Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0 66 | const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept // nothrow 67 | { 68 | const char* pText = reinterpret_cast(sqlite3_column_text(mStmtPtr, mIndex)); 69 | return (pText?pText:apDefaultValue); 70 | } 71 | 72 | // Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0 73 | const void* Column::getBlob() const noexcept // nothrow 74 | { 75 | return sqlite3_column_blob(mStmtPtr, mIndex); 76 | } 77 | 78 | // Return the type of the value of the column 79 | int Column::getType() const noexcept // nothrow 80 | { 81 | return sqlite3_column_type(mStmtPtr, mIndex); 82 | } 83 | 84 | // Return the number of bytes used by the text value of the column 85 | int Column::getBytes() const noexcept // nothrow 86 | { 87 | return sqlite3_column_bytes(mStmtPtr, mIndex); 88 | } 89 | 90 | // Standard std::ostream inserter 91 | std::ostream& operator<<(std::ostream& aStream, const Column& aColumn) 92 | { 93 | aStream << aColumn.getText(); 94 | return aStream; 95 | } 96 | 97 | 98 | } // namespace SQLite 99 | -------------------------------------------------------------------------------- /include/SQLiteCpp/Exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Exception.h 3 | * @ingroup SQLiteCpp 4 | * @brief Encapsulation of the error message from SQLite3 on a std::runtime_error. 5 | * 6 | * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | 17 | namespace SQLite 18 | { 19 | 20 | 21 | /** 22 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 23 | */ 24 | class Exception : public std::runtime_error 25 | { 26 | public: 27 | /** 28 | * @brief Encapsulation of the error message from SQLite3, based on std::runtime_error. 29 | * 30 | * @param[in] aErrorMessage The string message describing the SQLite error 31 | */ 32 | explicit Exception(const std::string& aErrorMessage) : 33 | std::runtime_error(aErrorMessage) 34 | { 35 | } 36 | }; 37 | 38 | 39 | } // namespace SQLite 40 | 41 | 42 | /// Compatibility with non-clang compilers. 43 | #ifndef __has_feature 44 | #define __has_feature(x) 0 45 | #endif 46 | 47 | // Detect whether the compiler supports C++11 noexcept exception specifications. 48 | #if ( defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)) \ 49 | && defined(__GXX_EXPERIMENTAL_CXX0X__)) 50 | // GCC 4.7 and following have noexcept 51 | #elif defined(__clang__) && __has_feature(cxx_noexcept) 52 | // Clang 3.0 and above have noexcept 53 | #elif defined(_MSC_VER) && _MSC_VER > 1800 54 | // Visual Studio 2015 and above have noexcept 55 | #else 56 | // Visual Studio 2013 does not support noexcept, and "throw()" is deprecated by C++11 57 | #define noexcept 58 | #endif 59 | -------------------------------------------------------------------------------- /include/SQLiteCpp/SQLiteCpp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file SQLiteCpp.h 3 | * @ingroup SQLiteCpp 4 | * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files. 5 | * 6 | * Include this main header file in your project to gain access to all functionality provided by the wrapper. 7 | * 8 | * Copyright (c) 2012-2016 Sebastien Rombauts (sebastien.rombauts@gmail.com) 9 | * 10 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 11 | * or copy at http://opensource.org/licenses/MIT) 12 | */ 13 | /** 14 | * @defgroup SQLiteCpp SQLiteC++ 15 | * @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files. 16 | */ 17 | #pragma once 18 | 19 | 20 | // Include useful headers of SQLiteC++ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | /** 30 | * @brief Version numbers for SQLiteC++ are provided in the same way as sqlite3.h 31 | * 32 | * The [SQLITECPP_VERSION] C preprocessor macro in the SQLiteC++.h header 33 | * evaluates to a string literal that is the SQLite version in the 34 | * format "X.Y.Z" where X is the major version number 35 | * and Y is the minor version number and Z is the release number. 36 | * 37 | * The [SQLITECPP_VERSION_NUMBER] C preprocessor macro resolves to an integer 38 | * with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same 39 | * numbers used in [SQLITECPP_VERSION]. 40 | */ 41 | #define SQLITECPP_VERSION "1.3.1" 42 | #define SQLITECPP_VERSION_NUMBER 1003001 43 | -------------------------------------------------------------------------------- /include/SQLiteCpp/Transaction.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Transaction.cpp 3 | * @ingroup SQLiteCpp 4 | * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation. 5 | * 6 | * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | namespace SQLite 18 | { 19 | 20 | 21 | // Begins the SQLite transaction 22 | Transaction::Transaction(Database& aDatabase) : 23 | mDatabase(aDatabase), 24 | mbCommited(false) 25 | { 26 | mDatabase.exec("BEGIN"); 27 | } 28 | 29 | // Safely rollback the transaction if it has not been committed. 30 | Transaction::~Transaction() noexcept // nothrow 31 | { 32 | if (false == mbCommited) 33 | { 34 | try 35 | { 36 | mDatabase.exec("ROLLBACK"); 37 | } 38 | catch (SQLite::Exception& e) 39 | { 40 | // Never throw an exception in a destructor 41 | (void)e; // warning proof 42 | SQLITECPP_ASSERT(false, e.what()); // See SQLITECPP_ENABLE_ASSERT_HANDLER 43 | } 44 | } 45 | } 46 | 47 | // Commit the transaction. 48 | void Transaction::commit() 49 | { 50 | if (false == mbCommited) 51 | { 52 | mDatabase.exec("COMMIT"); 53 | mbCommited = true; 54 | } 55 | else 56 | { 57 | throw SQLite::Exception("Transaction already commited."); 58 | } 59 | } 60 | 61 | 62 | } // namespace SQLite 63 | -------------------------------------------------------------------------------- /include/SQLiteCpp/Transaction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Transaction.h 3 | * @ingroup SQLiteCpp 4 | * @brief A Transaction is way to group multiple SQL statements into an atomic secured operation. 5 | * 6 | * Copyright (c) 2012-2013 Sebastien Rombauts (sebastien.rombauts@gmail.com) 7 | * 8 | * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt 9 | * or copy at http://opensource.org/licenses/MIT) 10 | */ 11 | #pragma once 12 | 13 | #include 14 | 15 | 16 | namespace SQLite 17 | { 18 | 19 | 20 | // Forward declaration 21 | class Database; 22 | 23 | /** 24 | * @brief RAII encapsulation of a SQLite Transaction. 25 | * 26 | * A Transaction is a way to group multiple SQL statements into an atomic secured operation; 27 | * either it succeeds, with all the changes committed to the database file, 28 | * or if it fails, all the changes are rolled back to the initial state. 29 | * 30 | * Resource Acquisition Is Initialization (RAII) means that the Transaction 31 | * begins in the constructor and is rollbacked in the destructor, so that there is 32 | * no need to worry about memory management or the validity of the underlying SQLite Connection. 33 | * 34 | * This method also offers big performances improvements compared to individually executed statements. 35 | * 36 | * Thread-safety: a Transaction object shall not be shared by multiple threads, because : 37 | * 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads 38 | * provided that no single database connection is used simultaneously in two or more threads." 39 | * 2) the SQLite "Serialized" mode is not supported by SQLiteC++, 40 | * because of the way it shares the underling SQLite precompiled statement 41 | * in a custom shared pointer (See the inner class "Statement::Ptr"). 42 | */ 43 | class Transaction 44 | { 45 | public: 46 | /** 47 | * @brief Begins the SQLite transaction 48 | * 49 | * @param[in] aDatabase the SQLite Database Connection 50 | * 51 | * Exception is thrown in case of error, then the Transaction is NOT initiated. 52 | */ 53 | explicit Transaction(Database& aDatabase); 54 | 55 | /** 56 | * @brief Safely rollback the transaction if it has not been committed. 57 | */ 58 | virtual ~Transaction() noexcept; // nothrow 59 | 60 | /** 61 | * @brief Commit the transaction. 62 | */ 63 | void commit(); 64 | 65 | private: 66 | // Transaction must be non-copyable 67 | Transaction(const Transaction&); 68 | Transaction& operator=(const Transaction&); 69 | /// @} 70 | 71 | private: 72 | Database& mDatabase; //!< Reference to the SQLite Database Connection 73 | bool mbCommited; //!< True when commit has been called 74 | }; 75 | 76 | 77 | } // namespace SQLite 78 | -------------------------------------------------------------------------------- /include/boost/serialization/tuple.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOOST_SERIALIZATION_TUPLE_HPP 2 | #define BOOST_SERIALIZATION_TUPLE_HPP 3 | 4 | // MS compatible compilers support #pragma once 5 | #if defined(_MSC_VER) 6 | # pragma once 7 | #endif 8 | 9 | /* 10 | Copyright 2011 Christopher Allen Ogden. All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without modification, are 13 | permitted provided that the following conditions are met: 14 | 15 | 1. Redistributions of source code must retain the above copyright notice, this list of 16 | conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 19 | of conditions and the following disclaimer in the documentation and/or other materials 20 | provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY CHRISTOPHER ALLEN OGDEN ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CHRISTOPHER ALLEN OGDEN OR 25 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 30 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | The views and conclusions contained in the software and documentation are those of the 33 | authors and should not be interpreted as representing official policies, either expressed 34 | or implied, of Christopher Allen Ogden. 35 | */ 36 | 37 | #include 38 | 39 | namespace boost { 40 | namespace serialization { 41 | 42 | template 43 | struct Serialize 44 | { 45 | template 46 | static void serialize(Archive & ar, std::tuple & t, const unsigned int version) 47 | { 48 | ar & std::get(t); 49 | Serialize::serialize(ar, t, version); 50 | } 51 | }; 52 | 53 | template<> 54 | struct Serialize<0> 55 | { 56 | template 57 | static void serialize(Archive & ar, std::tuple & t, const unsigned int version) 58 | { 59 | } 60 | }; 61 | 62 | template 63 | void serialize(Archive & ar, std::tuple & t, const unsigned int version) 64 | { 65 | Serialize::serialize(ar, t, version); 66 | } 67 | 68 | } // namespace serialization 69 | } // namespace boost 70 | 71 | #endif //BOOST_SERIALIZATION_TUPLE_HPP -------------------------------------------------------------------------------- /include/meerkat/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Cesanta Software Limited 2 | All rights reserved 3 | 4 | This code is dual-licensed: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License version 2 as 6 | published by the Free Software Foundation. For the terms of this 7 | license, see . 8 | 9 | You are free to use this code under the terms of the GNU General 10 | Public License, but WITHOUT ANY WARRANTY; without even the implied 11 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU General Public License for more details. 13 | 14 | Alternatively, you can license this code under a commercial 15 | license, as set out in . 16 | -------------------------------------------------------------------------------- /include/rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H__ 16 | #define RAPIDJSON_ERROR_EN_H__ 17 | 18 | #include "error.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Maps error code of parsing into error message. 23 | /*! 24 | \ingroup RAPIDJSON_ERRORS 25 | \param parseErrorCode Error code obtained in parsing. 26 | \return the error message. 27 | \note User can make a copy of this function for localization. 28 | Using switch-case is safer for future modification of error codes. 29 | */ 30 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 31 | switch (parseErrorCode) { 32 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 33 | 34 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 35 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); 36 | 37 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 38 | 39 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 40 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 41 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 42 | 43 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 44 | 45 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 46 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 47 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 48 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 49 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 50 | 51 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 52 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 53 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 54 | 55 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 56 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 57 | 58 | default: 59 | return RAPIDJSON_ERROR_STRING("Unknown error."); 60 | } 61 | } 62 | 63 | RAPIDJSON_NAMESPACE_END 64 | 65 | #endif // RAPIDJSON_ERROR_EN_H__ 66 | -------------------------------------------------------------------------------- /include/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! File byte stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileReadStream { 28 | public: 29 | typedef char Ch; //!< Character type (byte). 30 | 31 | //! Constructor. 32 | /*! 33 | \param fp File pointer opened for read. 34 | \param buffer user-supplied buffer. 35 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 36 | */ 37 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 38 | RAPIDJSON_ASSERT(fp_ != 0); 39 | RAPIDJSON_ASSERT(bufferSize >= 4); 40 | Read(); 41 | } 42 | 43 | Ch Peek() const { return *current_; } 44 | Ch Take() { Ch c = *current_; Read(); return c; } 45 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 46 | 47 | // Not implemented 48 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 49 | void Flush() { RAPIDJSON_ASSERT(false); } 50 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 51 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 52 | 53 | // For encoding detection only. 54 | const Ch* Peek4() const { 55 | return (current_ + 4 <= bufferLast_) ? current_ : 0; 56 | } 57 | 58 | private: 59 | void Read() { 60 | if (current_ < bufferLast_) 61 | ++current_; 62 | else if (!eof_) { 63 | count_ += readCount_; 64 | readCount_ = fread(buffer_, 1, bufferSize_, fp_); 65 | bufferLast_ = buffer_ + readCount_ - 1; 66 | current_ = buffer_; 67 | 68 | if (readCount_ < bufferSize_) { 69 | buffer_[readCount_] = '\0'; 70 | ++bufferLast_; 71 | eof_ = true; 72 | } 73 | } 74 | } 75 | 76 | std::FILE* fp_; 77 | Ch *buffer_; 78 | size_t bufferSize_; 79 | Ch *bufferLast_; 80 | Ch *current_; 81 | size_t readCount_; 82 | size_t count_; //!< Number of characters read 83 | bool eof_; 84 | }; 85 | 86 | RAPIDJSON_NAMESPACE_END 87 | 88 | #endif // RAPIDJSON_FILESTREAM_H_ 89 | -------------------------------------------------------------------------------- /include/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Wrapper of C file stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileWriteStream { 28 | public: 29 | typedef char Ch; //!< Character type. Only support char. 30 | 31 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 32 | RAPIDJSON_ASSERT(fp_ != 0); 33 | } 34 | 35 | void Put(char c) { 36 | if (current_ >= bufferEnd_) 37 | Flush(); 38 | 39 | *current_++ = c; 40 | } 41 | 42 | void PutN(char c, size_t n) { 43 | size_t avail = static_cast(bufferEnd_ - current_); 44 | while (n > avail) { 45 | std::memset(current_, c, avail); 46 | current_ += avail; 47 | Flush(); 48 | n -= avail; 49 | avail = static_cast(bufferEnd_ - current_); 50 | } 51 | 52 | if (n > 0) { 53 | std::memset(current_, c, n); 54 | current_ += n; 55 | } 56 | } 57 | 58 | void Flush() { 59 | if (current_ != buffer_) { 60 | fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 61 | current_ = buffer_; 62 | } 63 | } 64 | 65 | // Not implemented 66 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 67 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 68 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 69 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 70 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 71 | 72 | private: 73 | // Prohibit copy constructor & assignment operator. 74 | FileWriteStream(const FileWriteStream&); 75 | FileWriteStream& operator=(const FileWriteStream&); 76 | 77 | std::FILE* fp_; 78 | char *buffer_; 79 | char *bufferEnd_; 80 | char *current_; 81 | }; 82 | 83 | //! Implement specialized version of PutN() with memset() for better performance. 84 | template<> 85 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 86 | stream.PutN(c, n); 87 | } 88 | 89 | RAPIDJSON_NAMESPACE_END 90 | 91 | #endif // RAPIDJSON_FILESTREAM_H_ 92 | -------------------------------------------------------------------------------- /include/rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d_(d) {} 27 | Double(uint64_t u) : u_(u) {} 28 | 29 | double Value() const { return d_; } 30 | uint64_t Uint64Value() const { return u_; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u_ + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u_ & kSignMask) != 0; } 38 | uint64_t Significand() const { return u_ & kSignificandMask; } 39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } 40 | 41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } 44 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } 45 | 46 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 47 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 48 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } 49 | 50 | static unsigned EffectiveSignificandSize(int order) { 51 | if (order >= -1021) 52 | return 53; 53 | else if (order <= -1074) 54 | return 0; 55 | else 56 | return order + 1074; 57 | } 58 | 59 | private: 60 | static const int kSignificandSize = 52; 61 | static const int kExponentBias = 0x3FF; 62 | static const int kDenormalExponent = 1 - kExponentBias; 63 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 64 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 65 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 66 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 67 | 68 | union { 69 | double d_; 70 | uint64_t u_; 71 | }; 72 | }; 73 | 74 | } // namespace internal 75 | RAPIDJSON_NAMESPACE_END 76 | 77 | #endif // RAPIDJSON_IEEE754_ 78 | -------------------------------------------------------------------------------- /include/rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /include/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Custom strlen() which works on different character types. 24 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 25 | \param s Null-terminated input string. 26 | \return Number of characters in the string. 27 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 28 | */ 29 | template 30 | inline SizeType StrLen(const Ch* s) { 31 | const Ch* p = s; 32 | while (*p) ++p; 33 | return SizeType(p - s); 34 | } 35 | 36 | } // namespace internal 37 | RAPIDJSON_NAMESPACE_END 38 | 39 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 40 | -------------------------------------------------------------------------------- /include/rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /include/rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Represents an in-memory input byte stream. 23 | /*! 24 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 25 | 26 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 27 | 28 | Differences between MemoryStream and StringStream: 29 | 1. StringStream has encoding but MemoryStream is a byte stream. 30 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 31 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 32 | \note implements Stream concept 33 | */ 34 | struct MemoryStream { 35 | typedef char Ch; // byte 36 | 37 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 38 | 39 | Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } 40 | Ch Take() { return (src_ == end_) ? '\0' : *src_++; } 41 | size_t Tell() const { return static_cast(src_ - begin_); } 42 | 43 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 44 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 45 | void Flush() { RAPIDJSON_ASSERT(false); } 46 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 47 | 48 | // For encoding detection only. 49 | const Ch* Peek4() const { 50 | return Tell() + 4 <= size_ ? src_ : 0; 51 | } 52 | 53 | const Ch* src_; //!< Current read position. 54 | const Ch* begin_; //!< Original head of the string. 55 | const Ch* end_; //!< End of stream. 56 | size_t size_; //!< Size of the stream. 57 | }; 58 | 59 | RAPIDJSON_NAMESPACE_END 60 | 61 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 62 | -------------------------------------------------------------------------------- /include/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 21 | #include // std::move 22 | #endif 23 | 24 | #include "internal/stack.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory output stream. 29 | /*! 30 | \tparam Encoding Encoding of the stream. 31 | \tparam Allocator type for allocating memory buffer. 32 | \note implements Stream concept 33 | */ 34 | template 35 | class GenericStringBuffer { 36 | public: 37 | typedef typename Encoding::Ch Ch; 38 | 39 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 40 | 41 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 42 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 43 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 44 | if (&rhs != this) 45 | stack_ = std::move(rhs.stack_); 46 | return *this; 47 | } 48 | #endif 49 | 50 | void Put(Ch c) { *stack_.template Push() = c; } 51 | void Flush() {} 52 | 53 | void Clear() { stack_.Clear(); } 54 | void ShrinkToFit() { 55 | // Push and pop a null terminator. This is safe. 56 | *stack_.template Push() = '\0'; 57 | stack_.ShrinkToFit(); 58 | stack_.template Pop(1); 59 | } 60 | Ch* Push(size_t count) { return stack_.template Push(count); } 61 | void Pop(size_t count) { stack_.template Pop(count); } 62 | 63 | const Ch* GetString() const { 64 | // Push and pop a null terminator. This is safe. 65 | *stack_.template Push() = '\0'; 66 | stack_.template Pop(1); 67 | 68 | return stack_.template Bottom(); 69 | } 70 | 71 | size_t GetSize() const { return stack_.GetSize(); } 72 | 73 | static const size_t kDefaultCapacity = 256; 74 | mutable internal::Stack stack_; 75 | 76 | private: 77 | // Prohibit copy constructor & assignment operator. 78 | GenericStringBuffer(const GenericStringBuffer&); 79 | GenericStringBuffer& operator=(const GenericStringBuffer&); 80 | }; 81 | 82 | //! String buffer with UTF8 encoding 83 | typedef GenericStringBuffer > StringBuffer; 84 | 85 | //! Implement specialized version of PutN() with memset() for better performance. 86 | template<> 87 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 88 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 89 | } 90 | 91 | RAPIDJSON_NAMESPACE_END 92 | 93 | #endif // RAPIDJSON_STRINGBUFFER_H_ 94 | -------------------------------------------------------------------------------- /src/CategoricalDimension.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CategoricalDimension.h" 3 | 4 | CategoricalDimension::CategoricalDimension(const std::string& key, ulong numberOfValues) 5 | : Hashing(key), _numberOfValues(numberOfValues) { } 6 | 7 | bool CategoricalDimension::query(const Query& query, const Response& range, Response& response) const { 8 | 9 | if (query.evalWhere(_key)) { 10 | 11 | auto& values = query.getWhere(_key); 12 | 13 | auto note_it = _nodes.begin(); 14 | for (auto range_it = range.begin(); range_it != range.end(); ++range_it) { 15 | 16 | nextNode(*range_it, note_it); 17 | 18 | while ((**range_it).endAfter((*note_it)->front())) { 19 | 20 | (*note_it)->queryWhere(values, response); 21 | 22 | if (++note_it == _nodes.end()) return true; 23 | } 24 | } 25 | return true; 26 | 27 | } else if (query.evalGroup(_key)) { 28 | 29 | auto node_it = _nodes.begin(); 30 | for (auto range_it = range.begin(); range_it != range.end(); ++range_it) { 31 | 32 | nextNode(*range_it, node_it); 33 | 34 | while ((**range_it).endAfter((*node_it)->front())) { 35 | 36 | (*node_it)->queryGroup(response); 37 | 38 | if (++node_it == _nodes.end()) return true; 39 | } 40 | } 41 | return true; 42 | 43 | } else { 44 | return false; 45 | } 46 | } 47 | 48 | size_t CategoricalDimension::hash(const response_container& container, response_container& response, Data& data) { 49 | std::cout << "\tHashing Categorical Dimension: " + _key + "... "; 50 | 51 | data.prepareKey(_key); 52 | 53 | size_t pivots_count = 0; 54 | 55 | for (const auto& ptr : container) { 56 | if (ptr == nullptr || (*ptr).empty()) continue; 57 | 58 | _nodes.emplace_back(std::make_unique()); 59 | 60 | pivots_count += _nodes.back()->hash(this, response, data, *(Pivot*)ptr); 61 | } 62 | _nodes.shrink_to_fit(); 63 | 64 | std::cout << "Done." << std::endl; 65 | data.dispose(); 66 | 67 | return pivots_count; 68 | } 69 | 70 | ulong CategoricalDimension::numberOfValues() const { 71 | return _numberOfValues; 72 | } 73 | -------------------------------------------------------------------------------- /src/CategoricalDimension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Hashing.h" 4 | #include "CategoricalNode.h" 5 | 6 | class CategoricalDimension : public Hashing { 7 | public: 8 | CategoricalDimension(const std::string& key, ulong numberOfValues); 9 | CategoricalDimension(CategoricalDimension&&) = default; 10 | CategoricalDimension(const CategoricalDimension&) = delete; 11 | 12 | ~CategoricalDimension() = default; 13 | 14 | CategoricalDimension& operator=(CategoricalDimension&&) = default; 15 | CategoricalDimension& operator=(const CategoricalDimension&) = delete; 16 | 17 | bool query(const Query& query, const Response& range, Response& response) const override; 18 | size_t hash(const response_container& container, response_container& response, Data& data) override; 19 | 20 | ulong numberOfValues() const; 21 | 22 | protected: 23 | 24 | const ulong _numberOfValues{ 0 }; 25 | }; -------------------------------------------------------------------------------- /src/CategoricalNode.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CategoricalNode.h" 3 | 4 | #include "CategoricalDimension.h" 5 | 6 | void CategoricalNode::queryGroup(Response& response) const { 7 | response.insert(_container.begin(), _container.end()); 8 | } 9 | 10 | void CategoricalNode::queryWhere(const std::vector& values, Response& response) const { 11 | for (auto& ptr : _container) { 12 | if (values[ptr.value()]) response.addElement(&ptr); 13 | } 14 | } 15 | 16 | size_t CategoricalNode::hash(const CategoricalDimension* hashing, response_container& response, Data& data, const Pivot& pivot) { 17 | auto size = ((CategoricalDimension*)hashing)->numberOfValues(); 18 | 19 | std::vector used(size, 0); 20 | 21 | for (auto i = pivot.front(); i < pivot.back(); ++i) { 22 | int value = data.getIntProperty(i); 23 | 24 | data.setHash(i, value); 25 | used[value]++; 26 | } 27 | 28 | ulong accum = pivot.front(); 29 | for (ulong i = 0; i < size; ++i) { 30 | 31 | if (used[i] == 0) continue; 32 | 33 | int first = accum; 34 | accum += used[i]; 35 | int second = accum; 36 | 37 | _container.emplace_back(first, second, static_cast(i)); 38 | } 39 | _container.shrink_to_fit(); 40 | 41 | for (auto& ptr : _container) { 42 | response.emplace_back(&ptr); 43 | } 44 | 45 | data.sortHash(pivot.front(), pivot.back()); 46 | 47 | return _container.size(); 48 | } 49 | -------------------------------------------------------------------------------- /src/CategoricalNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CategoricalPivot.h" 4 | 5 | #include "Data.h" 6 | #include "Query.h" 7 | #include "Response.h" 8 | 9 | class CategoricalDimension; 10 | 11 | class CategoricalNode { 12 | public: 13 | CategoricalNode() = default; 14 | 15 | CategoricalNode(CategoricalNode&&) = default; 16 | CategoricalNode(const CategoricalNode&) = delete; 17 | 18 | ~CategoricalNode() = default; 19 | 20 | CategoricalNode& operator=(CategoricalNode&&) = delete; 21 | CategoricalNode& operator=(const CategoricalNode&) = delete; 22 | 23 | void queryGroup(Response& response) const; 24 | void queryWhere(const std::vector& values, Response& response) const; 25 | 26 | size_t hash(const CategoricalDimension* hashing, response_container& response, Data& data, const Pivot& pivot); 27 | 28 | inline const ulong front() const; 29 | inline const ulong back() const; 30 | 31 | protected: 32 | ulong value; 33 | std::vector _container; 34 | }; 35 | 36 | const ulong CategoricalNode::front() const { 37 | return _container.front().front(); 38 | } 39 | 40 | const ulong CategoricalNode::back() const { 41 | return _container.back().back(); 42 | } 43 | -------------------------------------------------------------------------------- /src/CategoricalPivot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Pivot.h" 4 | #include "Types.h" 5 | 6 | class CategoricalPivot : public Pivot { 7 | public: 8 | CategoricalPivot(ulong first, ulong second, const categorical_t& value) : Pivot(first, second), _value(value) { } 9 | CategoricalPivot(const Pivot& pivot, const categorical_t& value) : Pivot(pivot), _value(value) { } 10 | ~CategoricalPivot() = default; 11 | 12 | inline const categorical_t& value() const; 13 | 14 | protected: 15 | categorical_t _value; 16 | }; 17 | 18 | const categorical_t& CategoricalPivot::value() const { 19 | return _value; 20 | } 21 | -------------------------------------------------------------------------------- /src/CategoricalSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CategoricalSerializer.h" 3 | #include "CategoricalPivot.h" 4 | #include "CategoricalDimension.h" 5 | 6 | CategoricalSerializer& CategoricalSerializer::getInstance() { 7 | static CategoricalSerializer instance; 8 | return instance; 9 | } 10 | 11 | std::string CategoricalSerializer::serialize(const CategoricalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) { 12 | 13 | std::chrono::time_point start, end; 14 | start = std::chrono::high_resolution_clock::now(); 15 | 16 | std::vector aggregate((hashing)->numberOfValues(), 0); 17 | 18 | rapidjson::StringBuffer buffer; 19 | rapidjson::Writer writer(buffer); 20 | 21 | for (const auto& pivot : response.container()) { 22 | aggregate[((CategoricalPivot*)pivot)->value()] += pivot->size(); 23 | } 24 | 25 | end = std::chrono::high_resolution_clock::now(); 26 | duration = std::chrono::duration_cast(end - start); 27 | 28 | writer.StartArray(); 29 | for (ulong i = 0; i < aggregate.size(); ++i) { 30 | if (aggregate[i] == 0) continue; 31 | 32 | writer.StartArray(); 33 | writer.Uint(i); 34 | writer.Uint(aggregate[i]); 35 | writer.EndArray(); 36 | } 37 | writer.EndArray(); 38 | return buffer.GetString(); 39 | } 40 | 41 | std::string CategoricalSerializer::serialize(const CategoricalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) { 42 | 43 | std::chrono::time_point start, end; 44 | start = std::chrono::high_resolution_clock::now(); 45 | 46 | std::vector aggregate((hashing)->numberOfValues(), 0); 47 | 48 | rapidjson::StringBuffer buffer; 49 | rapidjson::Writer writer(buffer); 50 | 51 | auto it = tuple.second.begin(); 52 | for (const auto& pivot : tuple.first.container()) { 53 | int size = 0; 54 | 55 | while (it != tuple.second.end() && (*pivot) > (**it) ) { 56 | size += (**it).size(); 57 | it++; 58 | } 59 | 60 | aggregate[((CategoricalPivot*)pivot)->value()] += size; 61 | } 62 | 63 | end = std::chrono::high_resolution_clock::now(); 64 | duration = std::chrono::duration_cast(end - start); 65 | 66 | writer.StartArray(); 67 | for (ulong i = 0; i < aggregate.size(); ++i) { 68 | if (aggregate[i] == 0) continue; 69 | 70 | writer.StartArray(); 71 | writer.Uint(i); 72 | writer.Uint(aggregate[i]); 73 | writer.EndArray(); 74 | } 75 | writer.EndArray(); 76 | return buffer.GetString(); 77 | } 78 | -------------------------------------------------------------------------------- /src/CategoricalSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Serializer.h" 4 | #include "Response.h" 5 | 6 | class CategoricalDimension; 7 | 8 | class CategoricalSerializer : public Serializer { 9 | public: 10 | static CategoricalSerializer& getInstance(); 11 | 12 | virtual std::string serialize(const CategoricalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) override; 13 | virtual std::string serialize(const CategoricalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) override; 14 | 15 | protected: 16 | 17 | private: 18 | }; 19 | -------------------------------------------------------------------------------- /src/DMPLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "DMPLoader.h" 3 | 4 | DMPLoader& DMPLoader::getInstance() { 5 | static DMPLoader instance; 6 | return instance; 7 | } 8 | 9 | void DMPLoader::write(const std::string& path) { 10 | 11 | auto generator = getInMemoryGenerator(path); 12 | 13 | struct tweet { 14 | float latitude; 15 | float longitude; 16 | uint64_t time; 17 | uint8_t language; 18 | uint8_t device; 19 | uint8_t app; 20 | }; 21 | 22 | boost::filesystem::path boost_path(generator.path()); 23 | 24 | if (!exists(boost_path) || !is_directory(boost_path)) { 25 | std::cout << boost_path << " is a invalid path." << std::endl; 26 | return; 27 | } 28 | 29 | for (auto& x : boost::filesystem::directory_iterator(boost_path)) { 30 | 31 | if (is_directory(x)) continue; 32 | 33 | std::ifstream infile(x.path().string(), std::ios::binary); 34 | 35 | std::cout << x.path().string() << std::endl; 36 | 37 | infile.unsetf(std::ios_base::skipws); 38 | 39 | for (int i = 0; i < 32; ++i) { 40 | infile.ignore(std::numeric_limits::max(), '\n'); 41 | } 42 | 43 | while (!infile.eof()) { 44 | try { 45 | tweet record; 46 | infile.read((char*)&record, 19); 47 | 48 | time_t time(record.time); 49 | struct tm * ptm = std::gmtime(&time); 50 | 51 | generator.addFloat("lat0", record.latitude); 52 | generator.addFloat("lon0", record.longitude); 53 | 54 | generator.addInt("language", record.language); 55 | generator.addInt("device", record.device); 56 | generator.addInt("app", record.app); 57 | 58 | generator.addInt("tseries", util::mkgmtime(ptm)); 59 | 60 | generator.execute(); 61 | } catch (...) { 62 | break; 63 | } 64 | } 65 | 66 | infile.close(); 67 | } 68 | 69 | generator.commit(); 70 | } 71 | 72 | InMemoryDataGenerator DMPLoader::getInMemoryGenerator(const std::string& path) { 73 | std::vector tokens; 74 | 75 | tokens.emplace_back("lat0", "lat0", Spatial); 76 | tokens.emplace_back("lon0", "lon0", Spatial); 77 | 78 | tokens.emplace_back("language", "cat0", Categorical); 79 | tokens.emplace_back("device" , "cat1", Categorical); 80 | tokens.emplace_back("app" , "cat2", Categorical); 81 | 82 | tokens.emplace_back("tseries", "tseries", Temporal); 83 | 84 | return InMemoryDataGenerator(path, tokens); 85 | } 86 | -------------------------------------------------------------------------------- /src/DMPLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataLoader.h" 4 | #include "InMemoryDataGenerator.h" 5 | 6 | class DMPLoader : public DataLoader { 7 | public: 8 | static DMPLoader& getInstance(); 9 | virtual void write(const std::string& path) override; 10 | 11 | protected: 12 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 13 | 14 | private: 15 | DMPLoader() = default; 16 | ~DMPLoader() = default; 17 | }; 18 | -------------------------------------------------------------------------------- /src/Data.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Data.h" 3 | 4 | void Data::initialize(ulong size) { 5 | _hash = data_container::result(size); 6 | _index = data_container::result(size); 7 | 8 | for (ulong i = 0; i < _index.size(); i++) { 9 | _hash[i] = 0; 10 | _index[i] = i; 11 | } 12 | } 13 | 14 | void Data::sortHash(ulong fromIndex, ulong toIndex) { 15 | const auto functor = std::bind(&Data::comparator, this, std::placeholders::_1, std::placeholders::_2); 16 | std::sort(_index.begin() + fromIndex, _index.begin() + toIndex, functor); 17 | } 18 | 19 | void Data::setHash(ulong id, unsigned short value) { 20 | _hash[_index[id]] = value; 21 | } 22 | 23 | unsigned long Data::getHash(ulong index) const { 24 | return _hash[index]; 25 | } 26 | 27 | 28 | /* Local Variables: */ 29 | /* mode: c */ 30 | /* indent-tabs-mode: t */ 31 | /* c-basic-offset: 8 */ 32 | /* tab-width: 8 */ 33 | /* End: */ 34 | -------------------------------------------------------------------------------- /src/Data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Data { 4 | public: 5 | Data() = default; 6 | virtual ~Data() = default; 7 | 8 | void initialize(ulong size); 9 | 10 | void sortHash(ulong fromIndex, ulong toIndex); 11 | 12 | virtual void dispose() = 0; 13 | 14 | virtual void prepareKey(const std::string& key) = 0; 15 | virtual void prepareKey(const std::string& str, const std::vector& key) = 0; 16 | 17 | inline int getIntProperty(ulong id) { return getIntProperty(id, 0); }; 18 | inline float getFloatProperty(ulong id) { return getFloatProperty(id, 0); }; 19 | 20 | virtual int getIntProperty(ulong id, ulong key) = 0; 21 | virtual float getFloatProperty(ulong id, ulong key) = 0; 22 | 23 | void setHash(ulong id, unsigned short value); 24 | 25 | inline bool comparator(ulong bit0, ulong bit1) const { 26 | return _hash[bit0] < _hash[bit1]; 27 | } 28 | 29 | virtual ulong size() const = 0; 30 | 31 | protected: 32 | unsigned long getHash(ulong index) const; 33 | 34 | data_container::result _index; 35 | data_container::result _hash; 36 | 37 | private: 38 | }; 39 | 40 | /* Local Variables: */ 41 | /* mode: c */ 42 | /* indent-tabs-mode: t */ 43 | /* c-basic-offset: 8 */ 44 | /* tab-width: 8 */ 45 | /* End: */ 46 | -------------------------------------------------------------------------------- /src/DataGenerator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class DataGenerator { 4 | public: 5 | DataGenerator(const std::string& path, const std::vector tokens) : _path(path), _tokens(tokens) { } 6 | virtual ~DataGenerator() = default; 7 | 8 | inline const std::string& path() const; 9 | 10 | virtual void addInt(const std::string& key, ulong value) = 0; 11 | virtual void addFloat(const std::string& key, float value) = 0; 12 | 13 | virtual void execute() = 0; 14 | virtual void commit() = 0; 15 | 16 | protected: 17 | std::string _path; 18 | const std::vector _tokens; 19 | 20 | private: 21 | }; 22 | 23 | const std::string& DataGenerator::path() const { 24 | return _path; 25 | } 26 | -------------------------------------------------------------------------------- /src/DataLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "DataLoader.h" 3 | 4 | std::tuple, long long, size_t> DataLoader::build(const Schema& schema) { 5 | 6 | size_t pivots_count = 0; 7 | 8 | std::chrono::time_point start, end; 9 | 10 | std::unique_ptr data = nullptr; 11 | 12 | if (schema.loader == "sql") { 13 | data = getSQLData(schema); 14 | } else { 15 | data = getInMemoryData(schema); 16 | } 17 | 18 | std::cout << "\nBuildind HashedCube: " << std::endl; 19 | std::cout << "\tName: " << schema.name << std::endl; 20 | std::cout << "\tSize: " << data->size() << std::endl; 21 | std::cout << "\tLeaf Threshold: " << schema.leaf << "\n" << std::endl; 22 | 23 | std::shared_ptrcube = std::make_shared(data->size()); 24 | 25 | response_container current, response; 26 | current = cube->root(); 27 | 28 | start = std::chrono::high_resolution_clock::now(); 29 | 30 | // spatial 31 | pivots_count += cube->setSpatial(schema.spatial, schema.leaf)->hash(current, response, *data.get()); 32 | current.swap(response); 33 | response.clear(); 34 | std::cout << "\t\tNumber of Pivots: " << current.size() << std::endl; 35 | 36 | // categorical 37 | for (auto& pair : schema.categorical) { 38 | pivots_count += cube->addCategorical(pair.first, pair.second)->hash(current, response, *data.get()); 39 | current.swap(response); 40 | response.clear(); 41 | std::cout << "\t\tNumber of Pivots: " << current.size() << std::endl; 42 | } 43 | 44 | // temporal 45 | for (auto& pair : schema.temporal) { 46 | pivots_count += cube->addTemporal(pair.first, pair.second)->hash(current, response, *data.get()); 47 | current.swap(response); 48 | response.clear(); 49 | std::cout << "\t\tNumber of Pivots: " << current.size() << std::endl; 50 | } 51 | 52 | end = std::chrono::high_resolution_clock::now(); 53 | long long duration = std::chrono::duration_cast(end - start).count(); 54 | 55 | std::cout << "\n\tDuration: "+ std::to_string(duration) + "s\n" << std::endl; 56 | 57 | data->dispose(); 58 | 59 | if (schema.loader == "sql") { 60 | cube->setSQLData(data); 61 | } 62 | return std::make_tuple(cube , duration, pivots_count); 63 | } 64 | 65 | std::unique_ptr DataLoader::getInMemoryData(const Schema& schema) { 66 | return std::make_unique(InMemoryDataDescriptor(schema)); 67 | } 68 | 69 | std::unique_ptr DataLoader::getSQLData(const Schema& schema) { 70 | return std::make_unique(schema, InMemoryDataDescriptor(schema)); 71 | } 72 | -------------------------------------------------------------------------------- /src/DataLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HashedCube.h" 4 | 5 | #include "Data.h" 6 | #include "DataGenerator.h" 7 | 8 | #include "SQLData.h" 9 | 10 | #include "InMemoryData.h" 11 | #include "InMemoryDataGenerator.h" 12 | 13 | class DataLoader { 14 | public: 15 | static std::tuple, long long, size_t> build(const Schema& schema); 16 | virtual void write(const std::string& path) = 0; 17 | 18 | protected: 19 | static std::unique_ptr getInMemoryData(const Schema& schema); 20 | static std::unique_ptr getSQLData(const Schema& schema); 21 | 22 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) = 0; 23 | }; 24 | -------------------------------------------------------------------------------- /src/FlightsDelayLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataLoader.h" 4 | #include "InMemoryDataGenerator.h" 5 | 6 | #include "FlightsLoader.h" 7 | 8 | class FlightsDelayLoader : public DataLoader, public FlightsLoader { 9 | public: 10 | static FlightsDelayLoader& getInstance(); 11 | virtual void write(const std::string& path) override; 12 | 13 | protected: 14 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 15 | 16 | private: 17 | FlightsDelayLoader() = default; 18 | ~FlightsDelayLoader() = default; 19 | }; 20 | -------------------------------------------------------------------------------- /src/FlightsLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class FlightsLoader { 4 | public: 5 | FlightsLoader() = default; 6 | ~FlightsLoader() = default; 7 | 8 | protected: 9 | inline void loadMap(const std::string& path); 10 | std::unordered_map> map; 11 | }; 12 | 13 | void FlightsLoader::loadMap(const std::string & pathStr) { 14 | boost::filesystem::path path(pathStr + "csv/"); 15 | 16 | if (!exists(path) || !is_directory(path)) { 17 | std::cout << path << " is a invalid path." << std::endl; 18 | return; 19 | } 20 | 21 | for (auto& x : boost::filesystem::directory_iterator(path)) { 22 | 23 | if (is_directory(x)) continue; 24 | 25 | std::ifstream infile(x.path().string()); 26 | 27 | std::string line; 28 | while (std::getline(infile, line)) { 29 | if (line == "") continue; 30 | 31 | auto record = util::split(line, ","); 32 | 33 | try { 34 | if (record[4] == "\"\"") continue; 35 | map[record[4].substr(1, record[4].size() - 2)] = { std::stof(record[6]), std::stof(record[7]) }; 36 | } 37 | catch (std::invalid_argument) { 38 | continue; 39 | } 40 | } 41 | 42 | infile.close(); 43 | } 44 | } -------------------------------------------------------------------------------- /src/FlightsPerformanceLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataLoader.h" 4 | #include "InMemoryDataGenerator.h" 5 | 6 | #include "FlightsLoader.h" 7 | 8 | class FlightsPerformanceLoader : public DataLoader, public FlightsLoader { 9 | public: 10 | static FlightsPerformanceLoader& getInstance(); 11 | virtual void write(const std::string& path) override; 12 | 13 | protected: 14 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 15 | 16 | private: 17 | FlightsPerformanceLoader() = default; 18 | ~FlightsPerformanceLoader() = default; 19 | }; 20 | -------------------------------------------------------------------------------- /src/HashedCube.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "HashedCube.h" 3 | 4 | HashedCube::HashedCube(ulong size){ 5 | _root = std::make_unique(Pivot(size)); 6 | _root_container.emplace_back(_root.get()); 7 | } 8 | 9 | std::shared_ptr HashedCube::setSpatial(const std::vector& key, ulong leaf) { 10 | _spatial = std::make_shared(key, leaf); 11 | return _spatial; 12 | } 13 | 14 | std::shared_ptr HashedCube::addCategorical(const std::string& key, ulong numberOfValues) { 15 | _categorical.emplace_back(std::make_shared(key, numberOfValues)); 16 | return _categorical.back(); 17 | } 18 | 19 | std::shared_ptr HashedCube::addTemporal(const std::string& key, ulong bucketSize) { 20 | _temporal.emplace_back(std::make_shared(key, bucketSize)); 21 | return _temporal.back(); 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/HashedCube.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SQLData.h" 4 | #include "SpatialDimension.h" 5 | #include "TemporalDimension.h" 6 | #include "CategoricalDimension.h" 7 | 8 | class HashedCube { 9 | public: 10 | HashedCube(ulong size); 11 | 12 | HashedCube(HashedCube&&) = default; 13 | HashedCube(const HashedCube&) = delete; 14 | 15 | ~HashedCube() = default; 16 | 17 | HashedCube& operator=(HashedCube&&) = default; 18 | HashedCube& operator=(const HashedCube&) = delete; 19 | 20 | std::shared_ptr setSpatial(const std::vector& key, ulong leaf); 21 | std::shared_ptr addCategorical(const std::string& key, ulong numberOfValues); 22 | std::shared_ptr addTemporal(const std::string& key, ulong bucketSize); 23 | 24 | inline std::shared_ptr& spatial(); 25 | inline std::vector>& categorical(); 26 | inline std::vector>& temporal(); 27 | 28 | inline void setSQLData(std::unique_ptr& data); 29 | inline SQLData* getSQLData(void) const; 30 | 31 | inline const response_container& root() const; 32 | inline ulong size() const; 33 | 34 | inline ulong getCategoricalValues(const std::string& key) const; 35 | 36 | protected: 37 | std::unique_ptr _root; 38 | response_container _root_container; 39 | 40 | std::unique_ptr _data{ nullptr }; 41 | 42 | std::shared_ptr _spatial { nullptr }; 43 | std::vector> _categorical; 44 | std::vector> _temporal; 45 | }; 46 | 47 | ulong HashedCube::getCategoricalValues(const std::string& key) const { 48 | for (const auto& hashing : _categorical) { 49 | if (hashing->key() == key) { 50 | return hashing->numberOfValues(); 51 | } 52 | } 53 | return 0; 54 | } 55 | 56 | void HashedCube::setSQLData(std::unique_ptr& data) { 57 | _data = std::move(data); 58 | } 59 | 60 | SQLData* HashedCube::getSQLData(void) const { 61 | return (_data != nullptr)? (SQLData*)_data.get() : nullptr; 62 | } 63 | 64 | const response_container& HashedCube::root() const { 65 | return _root_container; 66 | } 67 | 68 | ulong HashedCube::size() const { 69 | return _root->size(); 70 | } 71 | 72 | std::shared_ptr& HashedCube::spatial() { 73 | return _spatial; 74 | } 75 | 76 | std::vector>& HashedCube::categorical() { 77 | return _categorical; 78 | } 79 | 80 | std::vector>& HashedCube::temporal() { 81 | return _temporal; 82 | } -------------------------------------------------------------------------------- /src/HashedCubeInstances.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "HashedCube.h" 4 | #include "Query.h" 5 | 6 | class HashedCubeInstances { 7 | public: 8 | 9 | static HashedCubeInstances& getInstance(); 10 | 11 | static void run(const std::vector& args); 12 | static void write(const std::vector& args); 13 | 14 | ~HashedCubeInstances(); 15 | 16 | inline bool ready() const { return _ready; }; 17 | inline void setReady() { _ready = true; }; 18 | 19 | inline std::shared_ptr get(std::string instance) const { 20 | auto it = _container.find(instance); 21 | if (it != _container.end()) { 22 | return (*it).second; 23 | } else { 24 | return nullptr; 25 | } 26 | } 27 | 28 | std::string query(const Query& query); 29 | std::string schema(const std::string& instance); 30 | 31 | inline void enableTelemetry(const std::string& file) { 32 | _telemetry = true; 33 | 34 | auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); 35 | std::stringstream stream; 36 | stream << std::put_time(std::localtime(&time), "-%Y-%m-%d-%H-%M-%S.csv"); 37 | 38 | _telemetry_file = std::make_shared(file + stream.str(), std::ofstream::out); 39 | } 40 | inline bool telemetry() { return _telemetry; } 41 | 42 | std::unordered_map> _container; 43 | 44 | protected: 45 | bool _ready{ false }; 46 | 47 | bool _telemetry{ false }; 48 | std::shared_ptr _telemetry_file; 49 | }; 50 | -------------------------------------------------------------------------------- /src/Hashing.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Data.h" 4 | #include "Query.h" 5 | #include "Response.h" 6 | 7 | template using node_container = std::vector>; 8 | template using node_iterator = typename std::vector>::const_iterator; 9 | 10 | template 11 | class Hashing { 12 | public: 13 | Hashing(const KeyType& key) : _key(key) { } 14 | 15 | Hashing(Hashing&&) = default; 16 | Hashing(const Hashing&) = delete; 17 | 18 | virtual ~Hashing() = default; 19 | 20 | Hashing& operator=(Hashing&&) = default; 21 | Hashing& operator=(const Hashing&) = delete; 22 | 23 | const KeyType& key() const { return _key; } 24 | 25 | virtual bool query(const Query& query, const Response& range, Response& response) const = 0; 26 | virtual size_t hash(const response_container& container, response_container& response, Data& data) = 0; 27 | 28 | inline void nextNode(const Pivot* range, node_iterator& node) const { 29 | if (range->front() <= (*node)->front() && range->back() >= (*node)->front()) return; 30 | node = std::lower_bound(node, _nodes.end(), range->front(), 31 | [](const std::unique_ptr& o1, const size_t& o2) { return o1->front() < o2; }); 32 | } 33 | 34 | protected: 35 | 36 | KeyType _key; 37 | node_container _nodes; 38 | }; 39 | -------------------------------------------------------------------------------- /src/InMemoryData.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "InMemoryData.h" 3 | 4 | InMemoryData::InMemoryData(const InMemoryDataDescriptor& descriptor) : _descriptor(descriptor) { 5 | initialize(_descriptor.size()); 6 | } 7 | 8 | void InMemoryData::dispose() { 9 | _data.clear(); 10 | } 11 | 12 | void InMemoryData::prepareKey(const std::string& key) { 13 | auto tuple = _descriptor.get(key); 14 | 15 | std::ifstream is(_descriptor.schema().path + "hcf/" + std::get<0>(tuple), std::ios::in | std::ifstream::binary); 16 | 17 | if (is.is_open()) { 18 | try { 19 | switch (std::get<1>(tuple)) { 20 | case Spatial: 21 | _data.emplace_back(size() * sizeof(float)); 22 | is.read(&_data.back()[0], size() * sizeof(float)); 23 | break; 24 | case Categorical: 25 | case Temporal: 26 | default: 27 | _data.emplace_back(size() * sizeof(int)); 28 | is.read(&_data.back()[0], size() * sizeof(int)); 29 | break; 30 | } 31 | 32 | is.close(); 33 | } catch (const std::exception& e) { 34 | std::cout << e.what() << std::endl; 35 | exit(0); 36 | } 37 | } else { 38 | std::cout << "!error opening file" << std::endl; 39 | exit(0); 40 | } 41 | } 42 | 43 | void InMemoryData::prepareKey(const std::string& str, const std::vector& key) { 44 | for (auto& k : key) { 45 | prepareKey(str + std::to_string(k)); 46 | } 47 | } 48 | 49 | int InMemoryData::getIntProperty(ulong id, ulong key) { 50 | return *((int*)&_data[key][_index[id] * sizeof(int)]); 51 | } 52 | 53 | float InMemoryData::getFloatProperty(ulong id, ulong key) { 54 | return *((float*)&_data[key][_index[id] * sizeof(float)]); 55 | } 56 | 57 | ulong InMemoryData::size() const { 58 | return _descriptor.size(); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/InMemoryData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Data.h" 4 | #include "InMemoryDataDescriptor.h" 5 | 6 | class InMemoryData : public Data { 7 | public: 8 | InMemoryData(const InMemoryDataDescriptor& descriptor); 9 | virtual ~InMemoryData() = default; 10 | 11 | virtual void dispose() override; 12 | 13 | virtual void prepareKey(const std::string& key) override; 14 | virtual void prepareKey(const std::string& str, const std::vector& key) override; 15 | 16 | virtual int getIntProperty(ulong id, ulong key) override; 17 | virtual float getFloatProperty(ulong id, ulong key) override; 18 | 19 | virtual ulong size() const override; 20 | 21 | protected: 22 | std::vector> _data; 23 | InMemoryDataDescriptor _descriptor; 24 | }; 25 | -------------------------------------------------------------------------------- /src/InMemoryDataDescriptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class InMemoryDataDescriptor { 4 | public: 5 | InMemoryDataDescriptor(ulong size) : _size(size) { } 6 | InMemoryDataDescriptor(const Schema& schema) : _schema(schema) { 7 | std::ifstream is(schema.path + "hcf/descriptor.hcf"); 8 | boost::archive::text_iarchive archive(is); 9 | 10 | archive & (*this); 11 | } 12 | 13 | virtual ~InMemoryDataDescriptor() = default; 14 | 15 | inline const Schema& schema() const; 16 | 17 | inline token_t get(const std::string& key) const; 18 | inline void set(const tuple_t& tuple); 19 | 20 | void save(const std::string& fileName) const { 21 | std::ofstream os(fileName); 22 | boost::archive::text_oarchive archive(os); 23 | 24 | archive & (*this); 25 | } 26 | 27 | inline unsigned int size() const; 28 | 29 | template 30 | void serialize(Archive & ar, const unsigned int version); 31 | 32 | 33 | protected: 34 | unsigned int _size{ 0 }; 35 | unsigned int _bitsPerHash{ 0 }; // legacy 36 | std::unordered_map _tokens; 37 | 38 | Schema _schema; 39 | 40 | private: 41 | friend class boost::serialization::access; 42 | }; 43 | 44 | template 45 | void InMemoryDataDescriptor::serialize(Archive & ar, const unsigned int version) { 46 | ar & _size; 47 | ar & _bitsPerHash; 48 | ar & _tokens; 49 | } 50 | 51 | const Schema& InMemoryDataDescriptor::schema() const { 52 | return _schema; 53 | } 54 | 55 | token_t InMemoryDataDescriptor::get(const std::string& key) const { 56 | return _tokens.at(key); 57 | } 58 | 59 | void InMemoryDataDescriptor::set(const tuple_t& tuple) { 60 | _tokens.emplace(std::get<0>(tuple), token_t(std::get<1>(tuple), std::get<2>(tuple))); 61 | } 62 | 63 | unsigned int InMemoryDataDescriptor::size() const { 64 | return _size * _schema.fraction; 65 | } -------------------------------------------------------------------------------- /src/InMemoryDataGenerator.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "InMemoryDataGenerator.h" 3 | #include "InMemoryDataDescriptor.h" 4 | 5 | InMemoryDataGenerator::InMemoryDataGenerator(const std::string& path, const std::vector tokens) 6 | : DataGenerator(path, tokens) { 7 | 8 | for (auto token : _tokens) { 9 | std::ofstream *s = new std::ofstream(_path + "hcf/" + std::get<1>(token), std::ios::out | std::ios::binary); 10 | _output.push_back(std::shared_ptr(s)); 11 | } 12 | } 13 | 14 | void InMemoryDataGenerator::addInt(const std::string& key, ulong value) { 15 | _output[find_if(key)]->write(reinterpret_cast(&value), sizeof(ulong)); 16 | } 17 | 18 | void InMemoryDataGenerator::addFloat(const std::string& key, float value) { 19 | _output[find_if(key)]->write(reinterpret_cast(&value), sizeof(float)); 20 | } 21 | 22 | void InMemoryDataGenerator::execute() { 23 | _size++; 24 | } 25 | 26 | void InMemoryDataGenerator::commit() { 27 | for (auto& output : _output) { 28 | output->close(); 29 | } 30 | 31 | InMemoryDataDescriptor descriptor(_size); 32 | 33 | for (auto token : _tokens) { 34 | descriptor.set(token); 35 | } 36 | 37 | descriptor.save(_path + "hcf/descriptor.hcf"); 38 | } 39 | -------------------------------------------------------------------------------- /src/InMemoryDataGenerator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataGenerator.h" 4 | #include 5 | 6 | class InMemoryDataGenerator : public DataGenerator { 7 | public: 8 | InMemoryDataGenerator(const std::string& path, const std::vector tokens); 9 | virtual ~InMemoryDataGenerator() = default; 10 | 11 | virtual void addInt(const std::string& key, ulong value) override; 12 | 13 | virtual void addFloat(const std::string& key, float value) override; 14 | 15 | virtual void execute() override; 16 | 17 | virtual void commit() override; 18 | 19 | protected: 20 | 21 | ulong _size{ 0 }; 22 | std::vector> _output; 23 | 24 | private: 25 | inline size_t find_if(const std::string& key) { 26 | auto it = std::find_if(_tokens.begin(), _tokens.end(), [key](tuple_t tuple) { return (key == std::get<0>(tuple)); }); 27 | 28 | return it - _tokens.begin(); 29 | } 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /src/Mercator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Types.h" 3 | 4 | namespace util { 5 | 6 | inline ulong lon2tilex(double lon, int z) { 7 | //lon = std::max(std::min(lon, 179.8), -179.8); 8 | int x = std::floor((lon + 180.0) / 360.0 * pow(2.0, z)); 9 | return x & ((1 << z) - 1); 10 | } 11 | 12 | inline ulong lat2tiley(double lat, int z) { 13 | //lat = std::max(std::min(lat, 89.8), -89.8); 14 | int y = std::floor((1.0 - log(tan(lat * M_PI / 180.0) + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0 * pow(2.0, z)); 15 | return y & ((1 << z) - 1); 16 | } 17 | 18 | 19 | inline double tilex2lon(double x, int z) { 20 | return x / pow(2.0, z) * 360.0 - 180; 21 | } 22 | 23 | inline double tiley2lat(double y, int z) { 24 | double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); 25 | return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); 26 | } 27 | 28 | inline bool intersectsTile(const tile_t& tile, const TileBounds& bounds) { 29 | return (bounds.lat1 <= tiley2lat(tile.y, tile.z)) && (bounds.lon1 >= tilex2lon(tile.x, tile.z)) 30 | && (bounds.lat0 >= tiley2lat(tile.y + 1, tile.z)) && (bounds.lon0 <= tilex2lon(tile.x + 1, tile.z)); 31 | } 32 | 33 | inline bool intersects(const tile_t& tile0, const Tile& tile1) { 34 | const float lat = tiley2lat(tile0.y, tile0.z); 35 | const float lon = tilex2lon(tile0.x, tile0.z); 36 | return (lon >= tile1.lon0 && lon <= tile1.lon1) && (lat <= tile1.lat0 && lat >= tile1.lat1); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/MySQLSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "MySQLSerializer.h" 3 | 4 | MySQLSerializer& MySQLSerializer::getInstance() { 5 | static MySQLSerializer instance; 6 | return instance; 7 | } 8 | 9 | std::string MySQLSerializer::serialize(const Response& response, std::chrono::milliseconds& duration) { 10 | return "[]"; 11 | } 12 | 13 | std::string MySQLSerializer::serialize(SQLData* data, Response& response, std::chrono::milliseconds& duration) { 14 | static const ulong max_count = 300; 15 | ulong count = 0; 16 | 17 | rapidjson::StringBuffer buffer; 18 | rapidjson::Writer writer(buffer); 19 | 20 | SQLite::Statement statement(*data->getDb(), "SELECT * FROM data WHERE ROWID==?"); 21 | 22 | writer.StartArray(); 23 | 24 | for (auto it = response.container().begin(); count < max_count && it != response.container().end(); ++it) { 25 | for (ulong id = (*it)->front(); count < max_count && id != (*it)->back(); ++id, ++count) { 26 | try { 27 | statement.reset(); 28 | statement.bind(1, (int)data->getSQLIndex(id)); 29 | if (statement.executeStep()) { 30 | writer.StartObject(); 31 | for (int i = 0; i < statement.getColumnCount(); ++i) { 32 | writer.String(statement.getColumnName(i)); 33 | switch (statement.getColumn(i).getType()) { 34 | case SQLITE_INTEGER: 35 | writer.Int(statement.getColumn(i).getInt()); 36 | break; 37 | case SQLITE_FLOAT: 38 | writer.Double(statement.getColumn(i).getDouble()); 39 | break; 40 | case SQLITE_TEXT: 41 | writer.String(statement.getColumn(i).getText()); 42 | break; 43 | case SQLITE_BLOB: 44 | writer.String((char*)statement.getColumn(i).getBlob()); 45 | break; 46 | case SQLITE_NULL: 47 | writer.String("null"); 48 | break; 49 | } 50 | } 51 | writer.EndObject(); 52 | } 53 | } 54 | catch (std::exception& e) { 55 | std::cout << "SQLite exception: " << e.what() << std::endl; 56 | return "[]"; 57 | } 58 | } 59 | } 60 | 61 | writer.EndArray(); 62 | return buffer.GetString(); 63 | } -------------------------------------------------------------------------------- /src/MySQLSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Serializer.h" 4 | #include "Response.h" 5 | 6 | #include "SQLData.h" 7 | 8 | class MySQLSerializer { 9 | public: 10 | static MySQLSerializer& getInstance(); 11 | std::string serialize(const Response& response, std::chrono::milliseconds& duration); 12 | std::string serialize(SQLData* data, Response& response, std::chrono::milliseconds& duration); 13 | protected: 14 | 15 | private: 16 | }; -------------------------------------------------------------------------------- /src/Pivot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Pivot { 4 | public: 5 | Pivot() = default; 6 | 7 | Pivot(ulong size) : Pivot(0, size) { }; 8 | Pivot(ulong first, ulong second) : _pivot({first, second}) { }; 9 | 10 | Pivot(const Pivot&) = default; 11 | 12 | virtual ~Pivot() = default; 13 | 14 | inline bool empty() const; 15 | inline ulong size() const; 16 | 17 | inline ulong front() const; 18 | inline ulong back() const; 19 | 20 | inline bool operator< (const Pivot& other) const; 21 | inline bool operator> (const Pivot& other) const; 22 | 23 | // implicit conversion 24 | inline operator const Pivot*() const; 25 | 26 | inline bool endAfter(const Pivot& other) const; 27 | inline bool endAfter(const ulong other) const; 28 | inline bool endBefore(const Pivot& other) const; 29 | 30 | protected: 31 | std::array _pivot; 32 | }; 33 | 34 | using pivot_container = std::vector; 35 | using pivot_iterator = pivot_container::const_iterator; 36 | 37 | using response_container = std::vector; 38 | using response_iterator = response_container::const_iterator; 39 | 40 | 41 | bool Pivot::empty() const { 42 | return (back() - front()) == 0; 43 | } 44 | 45 | ulong Pivot::size() const { 46 | return back() - front(); 47 | } 48 | 49 | ulong Pivot::front() const { 50 | return _pivot[0]; 51 | } 52 | 53 | ulong Pivot::back() const { 54 | return _pivot[1]; 55 | } 56 | 57 | bool Pivot::operator<(const Pivot& other) const { 58 | return back() < other.front(); 59 | } 60 | 61 | bool Pivot::operator>(const Pivot& other) const { 62 | return back() > other.front(); 63 | } 64 | 65 | Pivot::operator const Pivot*() const { 66 | return this; 67 | } 68 | 69 | bool Pivot::endAfter(const ulong other) const { 70 | return back() > other; 71 | } 72 | 73 | bool Pivot::endAfter(const Pivot& other) const { 74 | return back() > other.front(); 75 | } 76 | 77 | bool Pivot::endBefore(const Pivot& other) const { 78 | return back() <= other.front(); 79 | } -------------------------------------------------------------------------------- /src/Query.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TemporalInterval.h" 3 | 4 | class HashedCube; 5 | 6 | class Query { 7 | public: 8 | enum QueryType { TILE, GROUP, TSERIES, SCATTER, MYSQL, REGION }; 9 | 10 | QueryType type; 11 | std::string instance{ "brightkite" }; 12 | std::shared_ptr cube; 13 | 14 | ulong zoom; 15 | ulong resolution; 16 | 17 | std::unordered_map tseries; 18 | std::unordered_set group; 19 | 20 | Query(const std::string& url); 21 | Query(const std::vector& tokens); 22 | Query(const std::string& instance, const std::string& type); 23 | 24 | friend std::ostream& operator<< (std::ostream& stream, const Query& query); 25 | 26 | inline const TemporalInterval& getTseries(const std::string& key) const { 27 | return tseries.at(key); 28 | } 29 | inline const std::vector& getWhere(const std::string& key) const { 30 | return _where.at(key); 31 | } 32 | 33 | 34 | inline bool evalTseries(const std::string& key) const { 35 | return tseries.find(key) != tseries.end(); 36 | } 37 | inline bool evalGroup(const std::string& key) const { 38 | return group.find(key) != group.end(); 39 | } 40 | 41 | 42 | // tile 43 | inline void emplaceTile(ulong key, const Tile& tile) { 44 | if (key < _tile.size()) { 45 | _tile[key] = tile; 46 | } 47 | } 48 | inline bool evalTile(ulong key) const { 49 | if (key < _tile.size()) { 50 | return _tile[key].isValid(); 51 | } else return false; 52 | } 53 | inline bool evalAnyTile(const std::vector& key) const { 54 | for (auto& k : key) { 55 | if (evalTile(k)) return true; 56 | } 57 | return false; 58 | } 59 | inline const Tile& getTile(ulong key) const { 60 | return _tile[key]; 61 | } 62 | 63 | // region 64 | inline ulong getLastValidRegion(void) const { 65 | return _last_valid_region; 66 | } 67 | inline void emplaceRegion(ulong key, const TileBounds& region) { 68 | if (key < _region.size()) { 69 | _region[key] = region; 70 | _last_valid_region = key; 71 | } 72 | } 73 | inline bool evalRegion(ulong key) const { 74 | if (key < _region.size()) { 75 | return _region[key].isValid(); 76 | } 77 | else return false; 78 | } 79 | inline bool evalAnyRegion(const std::vector& key) const { 80 | for (auto& k : key) { 81 | if (evalRegion(k)) return true; 82 | } 83 | return false; 84 | } 85 | inline const TileBounds& getRegion(ulong key) const { 86 | return _region.at(key); 87 | } 88 | 89 | //where 90 | void emplaceWhere(const std::string& key, const std::vector& values); 91 | 92 | inline bool evalWhere(const std::string& key) const { 93 | return _where.find(key) != _where.end(); 94 | } 95 | 96 | protected: 97 | // tile 98 | std::vector _tile; 99 | 100 | // region 101 | ulong _last_valid_region = 0; 102 | std::vector _region; 103 | 104 | // where 105 | std::unordered_map> _where; 106 | 107 | inline std::string nextToken(std::vector::const_iterator& it) { return *(++it); } 108 | }; -------------------------------------------------------------------------------- /src/ResidentSetSize.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: David Robert Nadeau 3 | * Site: http://NadeauSoftware.com/ 4 | * License: Creative Commons Attribution 3.0 Unported License 5 | * http://creativecommons.org/licenses/by/3.0/deed.en_US 6 | */ 7 | 8 | #if defined(_WIN32) 9 | #include 10 | #include 11 | 12 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) 13 | #include 14 | #include 15 | 16 | #if defined(__APPLE__) && defined(__MACH__) 17 | #include 18 | 19 | #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) 20 | #include 21 | #include 22 | 23 | #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) 24 | #include 25 | 26 | #endif 27 | 28 | #else 29 | #error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS." 30 | #endif 31 | 32 | 33 | 34 | 35 | 36 | /** 37 | * Returns the peak (maximum so far) resident set size (physical 38 | * memory use) measured in bytes, or zero if the value cannot be 39 | * determined on this OS. 40 | */ 41 | inline size_t getPeakRSS() 42 | { 43 | #if defined(_WIN32) 44 | /* Windows -------------------------------------------------- */ 45 | PROCESS_MEMORY_COUNTERS info; 46 | GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 47 | return (size_t)info.PeakWorkingSetSize; 48 | 49 | #elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) 50 | /* AIX and Solaris ------------------------------------------ */ 51 | struct psinfo psinfo; 52 | int fd = -1; 53 | if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1) 54 | return (size_t)0L; /* Can't open? */ 55 | if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) 56 | { 57 | close(fd); 58 | return (size_t)0L; /* Can't read? */ 59 | } 60 | close(fd); 61 | return (size_t)(psinfo.pr_rssize * 1024L); 62 | 63 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) 64 | /* BSD, Linux, and OSX -------------------------------------- */ 65 | struct rusage rusage; 66 | getrusage(RUSAGE_SELF, &rusage); 67 | #if defined(__APPLE__) && defined(__MACH__) 68 | return (size_t)rusage.ru_maxrss; 69 | #else 70 | return (size_t)(rusage.ru_maxrss * 1024L); 71 | #endif 72 | 73 | #else 74 | /* Unknown OS ----------------------------------------------- */ 75 | return (size_t)0L; /* Unsupported. */ 76 | #endif 77 | } 78 | 79 | 80 | 81 | 82 | 83 | /** 84 | * Returns the current resident set size (physical memory use) measured 85 | * in bytes, or zero if the value cannot be determined on this OS. 86 | */ 87 | inline size_t getCurrentRSS() 88 | { 89 | #if defined(_WIN32) 90 | /* Windows -------------------------------------------------- */ 91 | PROCESS_MEMORY_COUNTERS info; 92 | GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)); 93 | return (size_t)info.WorkingSetSize; 94 | 95 | #elif defined(__APPLE__) && defined(__MACH__) 96 | /* OSX ------------------------------------------------------ */ 97 | struct mach_task_basic_info info; 98 | mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; 99 | if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, 100 | (task_info_t)&info, &infoCount) != KERN_SUCCESS) 101 | return (size_t)0L; /* Can't access? */ 102 | return (size_t)info.resident_size; 103 | 104 | #elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) 105 | /* Linux ---------------------------------------------------- */ 106 | long rss = 0L; 107 | FILE* fp = NULL; 108 | if ((fp = fopen("/proc/self/statm", "r")) == NULL) 109 | return (size_t)0L; /* Can't open? */ 110 | if (fscanf(fp, "%*s%ld", &rss) != 1) 111 | { 112 | fclose(fp); 113 | return (size_t)0L; /* Can't read? */ 114 | } 115 | fclose(fp); 116 | return (size_t)rss * (size_t)sysconf(_SC_PAGESIZE); 117 | 118 | #else 119 | /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ 120 | return (size_t)0L; /* Unsupported. */ 121 | #endif 122 | } -------------------------------------------------------------------------------- /src/Response.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdafx.h" 4 | #include "Pivot.h" 5 | 6 | class Response { 7 | public: 8 | Response() = default; 9 | Response(const response_container& container) : _container(container) {}; 10 | 11 | ~Response() = default; 12 | 13 | inline const response_container& container() const; 14 | 15 | inline void addElement(const Pivot* const pivot); 16 | 17 | template 18 | inline void insert(_Iter begin, _Iter last); 19 | 20 | inline size_t size() const; 21 | 22 | inline response_iterator begin() const; 23 | inline response_iterator end() const; 24 | 25 | inline void swap(Response& right); 26 | 27 | protected: 28 | response_container _container; 29 | }; 30 | 31 | response_iterator Response::begin() const { 32 | return _container.begin(); 33 | } 34 | 35 | response_iterator Response::end() const { 36 | return _container.end(); 37 | } 38 | 39 | void Response::swap(Response& right) { 40 | _container.swap(right._container); 41 | right._container.clear(); 42 | } 43 | 44 | const response_container& Response::container() const { 45 | return _container; 46 | } 47 | 48 | void Response::addElement(const Pivot* const pivot) { 49 | _container.emplace_back(pivot); 50 | } 51 | 52 | template 53 | void Response::insert(_Iter begin, _Iter last) { 54 | _container.insert(_container.end(), begin, last); 55 | } 56 | 57 | size_t Response::size() const { 58 | return _container.size(); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/SQLData.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SQLData.h" 3 | 4 | SQLData::SQLData(const Schema& schema, const InMemoryDataDescriptor& descriptor) : InMemoryData(descriptor) { 5 | try { 6 | _db = std::make_unique(schema.path + "db3/log.db3", SQLITE_OPEN_READONLY); 7 | std::cout << "SQLite database file '" << _db->getFilename().c_str() << "' opened successfully\n"; 8 | } catch (std::exception& e) { 9 | std::cout << "SQLite exception: " << e.what() << std::endl; 10 | return; 11 | } 12 | } 13 | 14 | void SQLData::dispose() { 15 | InMemoryData::dispose(); 16 | Data::_hash.clear(); 17 | } 18 | -------------------------------------------------------------------------------- /src/SQLData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Data.h" 4 | #include"Types.h" 5 | 6 | #include "InMemoryData.h" 7 | 8 | class SQLData : public InMemoryData { 9 | public: 10 | SQLData(const Schema& schema, const InMemoryDataDescriptor& descriptor); 11 | virtual ~SQLData() = default; 12 | 13 | virtual void dispose() override; 14 | 15 | SQLData(const SQLData&) = default; 16 | SQLData& operator=(const SQLData&) = default; 17 | 18 | inline SQLite::Database* getDb() const; 19 | inline ulong getSQLIndex(ulong id) const; 20 | 21 | protected: 22 | std::unique_ptr _db; 23 | }; 24 | 25 | SQLite::Database* SQLData::getDb() const { 26 | return _db.get(); 27 | } 28 | 29 | ulong SQLData::getSQLIndex(ulong id) const { 30 | return _index[id]; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/ScatterSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ScatterSerializer.h" 3 | 4 | #include "CategoricalDimension.h" 5 | 6 | ScatterSerializer& ScatterSerializer::getInstance() { 7 | static ScatterSerializer instance; 8 | return instance; 9 | } 10 | 11 | std::string ScatterSerializer::serialize(const CategoricalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) { return "[]"; } 12 | 13 | std::string ScatterSerializer::serialize(const CategoricalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) { return "[]"; } 14 | 15 | std::string ScatterSerializer::serialize(const std::vector>& tuples, std::chrono::milliseconds& duration) { 16 | if (tuples.size() != 2) return "[]"; 17 | 18 | std::chrono::time_point start, end; 19 | start = std::chrono::high_resolution_clock::now(); 20 | 21 | size_t size = (tuples[0].first)->numberOfValues() * (tuples[1].first)->numberOfValues(); 22 | 23 | std::vector aggregate(size, 0); 24 | 25 | rapidjson::StringBuffer buffer; 26 | rapidjson::Writer writer(buffer); 27 | 28 | auto it = tuples[1].second.begin(); 29 | for (const auto& pivot : tuples[0].second.container()) { 30 | int size = 0; 31 | 32 | while (it != tuples[1].second.end() && (*pivot) > (**it)) { 33 | aggregate[((CategoricalPivot*)pivot)->value() * (tuples[1].first)->numberOfValues() + ((CategoricalPivot*)*it)->value()] += ((CategoricalPivot*)*it)->size(); 34 | it++; 35 | } 36 | } 37 | 38 | end = std::chrono::high_resolution_clock::now(); 39 | duration = std::chrono::duration_cast(end - start); 40 | 41 | writer.StartArray(); 42 | for (ulong i = 0; i < aggregate.size(); ++i) { 43 | if (aggregate[i] == 0) continue; 44 | 45 | writer.StartArray(); 46 | writer.Uint(i - ((i / ((tuples[1].first)->numberOfValues()) * ((tuples[1].first)->numberOfValues())))); 47 | writer.Uint(i / (tuples[1].first)->numberOfValues()); 48 | writer.Uint(aggregate[i]); 49 | writer.EndArray(); 50 | } 51 | writer.EndArray(); 52 | return buffer.GetString(); 53 | } 54 | -------------------------------------------------------------------------------- /src/ScatterSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Serializer.h" 4 | #include "Response.h" 5 | 6 | class CategoricalDimension; 7 | 8 | class ScatterSerializer : public Serializer { 9 | public: 10 | 11 | static ScatterSerializer& getInstance(); 12 | 13 | std::string serialize(const CategoricalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) override; 14 | std::string serialize(const CategoricalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) override; 15 | 16 | std::string serialize(const std::vector>& tuples, std::chrono::milliseconds& duration); 17 | }; -------------------------------------------------------------------------------- /src/Serializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Response.h" 4 | 5 | template 6 | class Serializer { 7 | public: 8 | virtual std::string serialize(const T* hashing, const Response& response, std::chrono::milliseconds& duration) = 0; 9 | virtual std::string serialize(const T* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) = 0; 10 | protected: 11 | private: 12 | }; 13 | -------------------------------------------------------------------------------- /src/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Server.h" 3 | #include "Query.h" 4 | 5 | #include "HashedCubeInstances.h" 6 | 7 | 8 | Server& Server::getInstance() { 9 | // c++11 static local variable initilization is thread-safe 10 | static Server instance; 11 | return instance; 12 | } 13 | 14 | void Server::run(bool disable_multithreading, ulong port) { 15 | mg_mgr_init(&Server::getInstance().mgr, NULL); 16 | Server::getInstance().nc = mg_bind(&Server::getInstance().mgr, std::to_string(port).c_str(), handler); 17 | 18 | mg_set_protocol_http_websocket(Server::getInstance().nc); 19 | 20 | Server::getInstance().http_server_opts.document_root = "WebContent"; 21 | 22 | if (!disable_multithreading) { 23 | mg_enable_multithreading(Server::getInstance().nc); 24 | } 25 | 26 | std::cout << "\nServer running..." << std::endl; 27 | 28 | while (Server::getInstance().running) { 29 | mg_mgr_poll(&Server::getInstance().mgr, 1); 30 | } 31 | mg_mgr_free(&Server::getInstance().mgr); 32 | } 33 | 34 | void Server::stop() { 35 | running = false; 36 | } 37 | 38 | void Server::handler(struct mg_connection* conn, int ev, void *p) { 39 | if (ev != MG_EV_HTTP_REQUEST) return; 40 | 41 | struct http_message *hm = (struct http_message *) p; 42 | std::string uri(hm->uri.p, hm->uri.len); 43 | 44 | try { 45 | std::vector tokens = util::split(uri, "[/]+"); 46 | 47 | if (tokens.size() <= 1) { 48 | mg_serve_http(conn, hm, Server::getInstance().http_server_opts); 49 | 50 | } 51 | else if (tokens[1] == "rest") { 52 | if (!HashedCubeInstances::getInstance().ready()) { 53 | printJson(conn, "[]", 200); 54 | 55 | } 56 | else if (tokens.size() >= 4) { 57 | if (tokens[2] == "schema") { 58 | printJson(conn, HashedCubeInstances::getInstance().schema(tokens[3]), 200); 59 | } 60 | else if (tokens.size() >= 5 && tokens[2] == "query") { 61 | printJson(conn, HashedCubeInstances::getInstance().query(Query(tokens)), 200); 62 | return; 63 | } 64 | else { 65 | printJson(conn, "[]", 200); 66 | } 67 | } 68 | } 69 | else { 70 | mg_serve_http(conn, hm, Server::getInstance().http_server_opts); 71 | } 72 | } catch (...) { 73 | std::cout << uri << std::endl; 74 | printJson(conn, "[]", 200); 75 | } 76 | } 77 | 78 | void Server::printText(struct mg_connection* conn, const std::string& content, int code) { 79 | const std::string sep = "\r\n"; 80 | 81 | std::stringstream ss; 82 | ss << "HTTP/1.1 " << code << " OK" << sep 83 | << "Content-Type: text/plain" << sep 84 | << "Access-Control-Allow-Origin: " << "*" << sep 85 | << "Connection: keep-alive" << sep 86 | << "Cache-Control: public, max-age=" << "86400" << sep 87 | << "Content-Length: %d" << sep << sep 88 | << "%s"; 89 | 90 | mg_printf(conn, ss.str().c_str(), (int)content.size(), content.c_str()); 91 | } 92 | 93 | void Server::printJson(struct mg_connection* conn, const std::string& content, int code) { 94 | const std::string sep = "\r\n"; 95 | 96 | bool cache = true; 97 | if (content == "[null]") cache = false; 98 | 99 | std::stringstream ss; 100 | ss << "HTTP/1.1 " << code << " OK" << sep 101 | << "Content-Type: application/json" << sep 102 | << "Access-Control-Allow-Origin: " << "*" << sep 103 | << "Connection: keep-alive" << sep; 104 | if (cache) ss << "Cache-Control: public, max-age=" << "86400" << sep; 105 | ss << "Content-Length: %d" << sep << sep 106 | << "%s"; 107 | 108 | mg_printf(conn, ss.str().c_str(), (int)content.size(), content.c_str()); 109 | } 110 | -------------------------------------------------------------------------------- /src/Server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Server { 4 | public: 5 | static Server& getInstance(); 6 | 7 | 8 | static void run(bool disable_multithreading, ulong port); 9 | 10 | void stop(); 11 | 12 | static void handler(struct mg_connection* conn, int ev, void *p); 13 | 14 | static void printText(struct mg_connection* conn, const std::string& content, int code); 15 | static void printJson(struct mg_connection* conn, const std::string& content, int code); 16 | 17 | struct mg_mgr mgr; 18 | struct mg_connection *nc; 19 | 20 | bool running{ true }; 21 | 22 | protected: 23 | struct mg_serve_http_opts http_server_opts; 24 | 25 | private: 26 | Server() = default; 27 | ~Server() = default; 28 | }; 29 | -------------------------------------------------------------------------------- /src/SnapLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SnapLoader.h" 3 | 4 | SnapLoader& SnapLoader::getInstance() { 5 | static SnapLoader instance; 6 | return instance; 7 | } 8 | 9 | void SnapLoader::write(const std::string& path) { 10 | 11 | auto generator = getInMemoryGenerator(path); 12 | 13 | boost::filesystem::path boost_path(generator.path()); 14 | 15 | if (!exists(boost_path) || !is_directory(boost_path)) { 16 | std::cout << boost_path << " is a invalid path." << std::endl; 17 | return; 18 | } 19 | 20 | for (auto& x : boost::filesystem::directory_iterator(boost_path)) { 21 | 22 | if (is_directory(x)) continue; 23 | 24 | std::ifstream infile(x.path().string()); 25 | 26 | infile.unsetf(std::ios_base::skipws); 27 | 28 | size_t line_count = std::count(std::istreambuf_iterator(infile), std::istreambuf_iterator(), '\n') + 1; 29 | infile.seekg(0, infile.beg); 30 | 31 | #pragma omp parallel for 32 | for (int l = 0; l < (int)line_count; ++l) { 33 | std::string line; 34 | 35 | #pragma omp critical (read_snap) 36 | { 37 | std::getline(infile, line); 38 | } 39 | 40 | if (line == "") continue; 41 | 42 | auto record = util::split(line, "[\t]+"); 43 | 44 | if (record.size() != 5) continue; 45 | 46 | float lat = std::stof(record[2]); 47 | float lon = std::stof(record[3]); 48 | 49 | if (lat < -90.f || lat > 90.f) continue; 50 | if (lon < -180.f || lat > 180.f) continue; 51 | 52 | if (lat == 0.f && lon == 0.f) continue; 53 | 54 | auto datetime = util::split(record[1], "T"); 55 | 56 | if (datetime.size() != 2) continue; 57 | 58 | auto date = util::split(datetime[0], "-"); 59 | auto hour = util::split(datetime[1], ":"); 60 | 61 | if (date.size() != 3) continue; 62 | 63 | int days = util::days_from_civil(std::stoi(date[0]), std::stoi(date[1]), std::stoi(date[2])); 64 | 65 | std::tm time = { 0 }; 66 | time.tm_sec = std::stoi(hour[2]); 67 | time.tm_min = std::stoi(hour[1]); 68 | time.tm_hour = std::stoi(hour[0]); 69 | 70 | time.tm_mday = std::stoi(date[2]); 71 | time.tm_mon = std::stoi(date[1]) - 1; 72 | time.tm_year = std::stoi(date[0]) - 1900; 73 | 74 | #pragma omp critical (write_snap) 75 | { 76 | generator.addFloat("lat0", lat); 77 | generator.addFloat("lon0", lon); 78 | 79 | generator.addInt("hour_of_day", std::stoi(hour[0])); 80 | generator.addInt("day_of_week", (util::weekday_from_days(days) + 6) % 7); 81 | generator.addInt("month_of_year", std::stoi(date[1]) - 1); 82 | generator.addInt("day_of_month", std::stoi(date[2]) - 1); 83 | 84 | generator.addInt("tseries", util::mkgmtime(&time)); 85 | 86 | generator.execute(); 87 | } 88 | } 89 | 90 | infile.close(); 91 | } 92 | 93 | generator.commit(); 94 | } 95 | 96 | InMemoryDataGenerator SnapLoader::getInMemoryGenerator(const std::string& path) { 97 | std::vector tokens; 98 | 99 | tokens.emplace_back("lat0", "lat0", Spatial); 100 | tokens.emplace_back("lon0", "lon0", Spatial); 101 | 102 | 103 | tokens.emplace_back("hour_of_day", "cat0", Categorical); 104 | tokens.emplace_back("day_of_week", "cat1", Categorical); 105 | 106 | tokens.emplace_back("month_of_year", "cat2", Categorical); 107 | tokens.emplace_back("day_of_month", "cat3", Categorical); 108 | 109 | tokens.emplace_back("tseries", "tseries", Temporal); 110 | 111 | return InMemoryDataGenerator(path, tokens); 112 | } 113 | -------------------------------------------------------------------------------- /src/SnapLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataLoader.h" 4 | #include "InMemoryDataGenerator.h" 5 | 6 | class SnapLoader : public DataLoader { 7 | public: 8 | static SnapLoader& getInstance(); 9 | virtual void write(const std::string& path) override; 10 | 11 | protected: 12 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 13 | 14 | private: 15 | SnapLoader() = default; 16 | ~SnapLoader() = default; 17 | }; 18 | -------------------------------------------------------------------------------- /src/SpatialDimension.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SpatialDimension.h" 3 | 4 | #include "TileNode.h" 5 | 6 | SpatialDimension::SpatialDimension(const std::vector& key, ulong leaf) : Hashing(key) { 7 | _max_zoom = 20 * (ulong)key.size(); 8 | _min_per_node = leaf; 9 | } 10 | 11 | bool SpatialDimension::query(const Query& query, const Response& range, Response& response) const { 12 | if (!query.evalAnyRegion(_key) && !query.evalAnyTile(_key)) return false; 13 | 14 | auto node_it = _nodes.begin(); 15 | for (auto range_it = range.begin(); range_it != range.end(); ++range_it) { 16 | 17 | nextNode(*range_it, node_it); 18 | 19 | while ((**range_it).endAfter((*node_it)->front())) { 20 | 21 | if (query.type == Query::TILE) { 22 | (*node_it)->queryTile(this, query, response, 0); 23 | } else { 24 | (*node_it)->queryRegion(this, query, response, 0); 25 | } 26 | 27 | if (++node_it == _nodes.end()) return true; 28 | } 29 | } 30 | 31 | return true; 32 | } 33 | 34 | size_t SpatialDimension::hash(const response_container& container, response_container& response, Data& data) { 35 | std::cout << "\tHashing " + std::to_string(key().size()) + " SpatialDimension(s)..."; 36 | 37 | data.prepareKey("lat", key()); 38 | data.prepareKey("lon", key()); 39 | 40 | size_t pivots_count = 0; 41 | 42 | for (const auto& ptr : container) { 43 | if (ptr == nullptr || (*ptr).empty()) continue; 44 | 45 | _nodes.emplace_back(std::make_unique(*ptr, tile_t())); 46 | 47 | pivots_count += _nodes.back()->hash(this, response, data); 48 | } 49 | _nodes.shrink_to_fit(); 50 | 51 | std::cout << "Done." << std::endl; 52 | data.dispose(); 53 | 54 | return pivots_count; 55 | } 56 | 57 | ulong SpatialDimension::maxZoom() const { 58 | return _max_zoom; 59 | } 60 | 61 | 62 | ulong SpatialDimension::min_per_node() const { 63 | return _min_per_node; 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/SpatialDimension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Hashing.h" 4 | #include "TileNode.h" 5 | 6 | class SpatialDimension : public Hashing> { 7 | public: 8 | SpatialDimension(const std::vector& key, ulong leaf); 9 | SpatialDimension(SpatialDimension&&) = default; 10 | SpatialDimension(const SpatialDimension&) = delete; 11 | 12 | ~SpatialDimension() = default; 13 | 14 | SpatialDimension& operator=(SpatialDimension&&) = default; 15 | SpatialDimension& operator=(const SpatialDimension&) = delete; 16 | 17 | bool query(const Query& query, const Response& range, Response& response) const override; 18 | size_t hash(const response_container& container, response_container& response, Data& data) override; 19 | 20 | ulong maxZoom() const; 21 | ulong min_per_node() const; 22 | 23 | protected: 24 | 25 | ulong _max_zoom; 26 | ulong _min_per_node; 27 | }; 28 | -------------------------------------------------------------------------------- /src/SpatialSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SpatialSerializer.h" 3 | 4 | #include "TilePivot.h" 5 | 6 | SpatialSerializer& SpatialSerializer::getInstance() { 7 | static SpatialSerializer instance; 8 | return instance; 9 | } 10 | 11 | std::string SpatialSerializer::serialize(const SpatialDimension* hashing, const Response& response, std::chrono::milliseconds& duration) { 12 | 13 | std::chrono::time_point start, end; 14 | start = std::chrono::high_resolution_clock::now(); 15 | 16 | std::unordered_map aggregate; 17 | 18 | for (const auto& pivot : response.container()) { 19 | aggregate[((TilePivot*)pivot)->value()] += pivot->size(); 20 | } 21 | 22 | end = std::chrono::high_resolution_clock::now(); 23 | duration = std::chrono::duration_cast(end - start); 24 | 25 | rapidjson::StringBuffer buffer; 26 | rapidjson::Writer writer(buffer); 27 | 28 | writer.StartArray(); 29 | for (const auto& pair : aggregate) { 30 | writer.StartArray(); 31 | writer.Uint(pair.first.x); 32 | writer.Uint(pair.first.y); 33 | writer.Uint(pair.first.z); 34 | writer.Uint(pair.second); 35 | writer.EndArray(); 36 | } 37 | writer.EndArray(); 38 | return buffer.GetString(); 39 | } 40 | 41 | std::string SpatialSerializer::serialize(const SpatialDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) { 42 | 43 | std::chrono::time_point start, end; 44 | start = std::chrono::high_resolution_clock::now(); 45 | 46 | std::unordered_map aggregate; 47 | 48 | auto it = tuple.second.begin(); 49 | for (const auto& pivot : tuple.first.container()) { 50 | ulong size = 0; 51 | 52 | while (it != tuple.second.end() && (*pivot) > (**it)) { 53 | size += (**it).size(); 54 | it++; 55 | } 56 | 57 | aggregate[((TilePivot*)pivot)->value()] += size; 58 | } 59 | 60 | end = std::chrono::high_resolution_clock::now(); 61 | duration = std::chrono::duration_cast(end - start); 62 | 63 | rapidjson::StringBuffer buffer; 64 | rapidjson::Writer writer(buffer); 65 | 66 | writer.StartArray(); 67 | for (const auto& pair : aggregate) { 68 | if (pair.second == 0) continue; 69 | writer.StartArray(); 70 | writer.Uint(pair.first.x); 71 | writer.Uint(pair.first.y); 72 | writer.Uint(pair.first.z); 73 | writer.Uint(pair.second); 74 | writer.EndArray(); 75 | } 76 | writer.EndArray(); 77 | return buffer.GetString(); 78 | } 79 | -------------------------------------------------------------------------------- /src/SpatialSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Serializer.h" 4 | #include "Response.h" 5 | 6 | class SpatialDimension; 7 | 8 | class SpatialSerializer : public Serializer { 9 | public: 10 | 11 | static SpatialSerializer& getInstance(); 12 | 13 | std::string serialize(const SpatialDimension* hashing, const Response& response, std::chrono::milliseconds& duration) override; 14 | std::string serialize(const SpatialDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) override; 15 | 16 | protected: 17 | 18 | private: 19 | }; 20 | -------------------------------------------------------------------------------- /src/SplomLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SplomLoader.h" 3 | 4 | SplomLoader& SplomLoader::getInstance() { 5 | static SplomLoader instance; 6 | return instance; 7 | } 8 | 9 | void SplomLoader::write(const std::string& path) { 10 | 11 | auto generator = getInMemoryGenerator(path); 12 | 13 | for (int l = 0; l < 1000000000; ++l) { 14 | 15 | float d0, d1, d2, d3, d4; 16 | 17 | d0 = randNormal(10, 10); 18 | d1 = randNormal(10, 10); 19 | d2 = randNormal(d0, 10); 20 | d3 = (log(fabs(d0) + 1) + randUniform(3, 1)); 21 | d4 = randNormal(10, 10); 22 | 23 | generator.addInt("dim0_10", util::linearScale(-40.f, 60.f, 0, 10, d0)); 24 | generator.addInt("dim1_10", util::linearScale(-40.f, 60.f, 0, 10, d1)); 25 | generator.addInt("dim2_10", util::linearScale(-70.f, 80.f, 0, 10, d2)); 26 | generator.addInt("dim3_10", util::linearScale(1.f, 7.f, 0, 10, d3)); 27 | generator.addInt("dim4_10", util::linearScale(-40.f, 60.f, 0, 10, d4)); 28 | 29 | generator.addInt("dim0_20", util::linearScale(-40.f, 60.f, 0, 20, d0)); 30 | generator.addInt("dim1_20", util::linearScale(-40.f, 60.f, 0, 20, d1)); 31 | generator.addInt("dim2_20", util::linearScale(-70.f, 80.f, 0, 20, d2)); 32 | generator.addInt("dim3_20", util::linearScale(1.f, 7.f, 0, 20, d3)); 33 | generator.addInt("dim4_20", util::linearScale(-40.f, 60.f, 0, 20, d4)); 34 | 35 | generator.addInt("dim0_30", util::linearScale(-40.f, 60.f, 0, 30, d0)); 36 | generator.addInt("dim1_30", util::linearScale(-40.f, 60.f, 0, 30, d1)); 37 | generator.addInt("dim2_30", util::linearScale(-70.f, 80.f, 0, 30, d2)); 38 | generator.addInt("dim3_30", util::linearScale(1.f, 7.f, 0, 30, d3)); 39 | generator.addInt("dim4_30", util::linearScale(-40.f, 60.f, 0, 30, d4)); 40 | 41 | generator.addInt("dim0_40", util::linearScale(-40.f, 60.f, 0, 40, d0)); 42 | generator.addInt("dim1_40", util::linearScale(-40.f, 60.f, 0, 40, d1)); 43 | generator.addInt("dim2_40", util::linearScale(-70.f, 80.f, 0, 40, d2)); 44 | generator.addInt("dim3_40", util::linearScale(1.f, 7.f, 0, 40, d3)); 45 | generator.addInt("dim4_40", util::linearScale(-40.f, 60.f, 0, 40, d4)); 46 | 47 | generator.addInt("dim0_50", util::linearScale(-40.f, 60.f, 0, 50, d0)); 48 | generator.addInt("dim1_50", util::linearScale(-40.f, 60.f, 0, 50, d1)); 49 | generator.addInt("dim2_50", util::linearScale(-70.f, 80.f, 0, 50, d2)); 50 | generator.addInt("dim3_50", util::linearScale(1.f, 7.f, 0, 50, d3)); 51 | generator.addInt("dim4_50", util::linearScale(-40.f, 60.f, 0, 50, d4)); 52 | 53 | generator.execute(); 54 | } 55 | 56 | generator.commit(); 57 | } 58 | 59 | InMemoryDataGenerator SplomLoader::getInMemoryGenerator(const std::string& path) { 60 | std::vector tokens; 61 | 62 | tokens.emplace_back("dim0_10", "dim0_10", Categorical); 63 | tokens.emplace_back("dim1_10", "dim1_10", Categorical); 64 | tokens.emplace_back("dim2_10", "dim2_10", Categorical); 65 | tokens.emplace_back("dim3_10", "dim3_10", Categorical); 66 | tokens.emplace_back("dim4_10", "dim4_10", Categorical); 67 | 68 | tokens.emplace_back("dim0_20", "dim0_20", Categorical); 69 | tokens.emplace_back("dim1_20", "dim1_20", Categorical); 70 | tokens.emplace_back("dim2_20", "dim2_20", Categorical); 71 | tokens.emplace_back("dim3_20", "dim3_20", Categorical); 72 | tokens.emplace_back("dim4_20", "dim4_20", Categorical); 73 | 74 | tokens.emplace_back("dim0_30", "dim0_30", Categorical); 75 | tokens.emplace_back("dim1_30", "dim1_30", Categorical); 76 | tokens.emplace_back("dim2_30", "dim2_30", Categorical); 77 | tokens.emplace_back("dim3_30", "dim3_30", Categorical); 78 | tokens.emplace_back("dim4_30", "dim4_30", Categorical); 79 | 80 | tokens.emplace_back("dim0_40", "dim0_40", Categorical); 81 | tokens.emplace_back("dim1_40", "dim1_40", Categorical); 82 | tokens.emplace_back("dim2_40", "dim2_40", Categorical); 83 | tokens.emplace_back("dim3_40", "dim3_40", Categorical); 84 | tokens.emplace_back("dim4_40", "dim4_40", Categorical); 85 | 86 | tokens.emplace_back("dim0_50", "dim0_50", Categorical); 87 | tokens.emplace_back("dim1_50", "dim1_50", Categorical); 88 | tokens.emplace_back("dim2_50", "dim2_50", Categorical); 89 | tokens.emplace_back("dim3_50", "dim3_50", Categorical); 90 | tokens.emplace_back("dim4_50", "dim4_50", Categorical); 91 | 92 | return InMemoryDataGenerator(path, tokens); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/SplomLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Trunc.h" 4 | #include "DataLoader.h" 5 | #include "InMemoryDataGenerator.h" 6 | 7 | class SplomLoader : public DataLoader { 8 | public: 9 | static SplomLoader& getInstance(); 10 | virtual void write(const std::string& path) override; 11 | 12 | protected: 13 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 14 | 15 | private: 16 | inline float randUniform(int min, int max); 17 | inline float randNormal(float mean, float stdev); 18 | 19 | SplomLoader() = default; 20 | ~SplomLoader() = default; 21 | 22 | std::default_random_engine _random_engine; 23 | std::uniform_real_distribution _uniform_dist {0.0, 1.0}; 24 | }; 25 | 26 | float SplomLoader::randUniform(int min, int max) { 27 | float delta = max - min; 28 | return (float)(min + delta * _uniform_dist(_random_engine)); 29 | } 30 | 31 | float SplomLoader::randNormal(float mean, float stdev) { 32 | float x = 0, y = 0, rds, c; 33 | do { 34 | x = (float)(_uniform_dist(_random_engine) * 2 - 1); 35 | y = (float)(_uniform_dist(_random_engine) * 2 - 1); 36 | rds = x * x + y * y; 37 | } while (rds == 0 || rds > 1); 38 | c = (float)sqrt(-2 * log(rds) / rds); 39 | return mean + x * c * stdev; 40 | } 41 | -------------------------------------------------------------------------------- /src/StringUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "StringUtil.h" 3 | 4 | std::vector util::split(const std::string& input, const std::regex& regex) { 5 | static const std::sregex_token_iterator last; 6 | return std::vector{ std::sregex_token_iterator{ input.begin(), input.end(), regex, -1 }, last }; 7 | } 8 | 9 | std::vector util::split(const std::string& input, const std::string& str_regex) { 10 | static const std::sregex_token_iterator last; 11 | std::regex regex(str_regex); 12 | return std::vector{ std::sregex_token_iterator{ input.begin(), input.end(), regex, -1 }, last }; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/StringUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace util { 4 | std::vector split(const std::string& input, const std::regex& regex); 5 | std::vector split(const std::string& input, const std::string& str_regex); 6 | } 7 | -------------------------------------------------------------------------------- /src/TemporalDimension.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TemporalDimension.h" 3 | #include "TemporalNode.h" 4 | #include "TemporalPivot.h" 5 | 6 | TemporalDimension::TemporalDimension(const std::string& key, size_t bucketSize) 7 | : Hashing(key), _bucketSize(static_cast(bucketSize)) { } 8 | 9 | bool TemporalDimension::query(const Query& query, const Response& range, Response& response) const { 10 | 11 | if (query.evalTseries(_key)) { 12 | if (query.type == Query::TSERIES) { 13 | 14 | auto& interval = query.getTseries(_key); 15 | 16 | auto node_it = _nodes.begin(); 17 | for (auto range_it = range.begin(); range_it != range.end(); ++range_it) { 18 | 19 | nextNode(*range_it, node_it); 20 | 21 | while ((**range_it).endAfter((*node_it)->front())) { 22 | 23 | (*node_it)->queryTseries(interval, response); 24 | 25 | if (++node_it == _nodes.end()) return true; 26 | } 27 | } 28 | 29 | } else if (!query.getTseries(_key).contains(_interval.lower(), _interval.upper())) { 30 | 31 | auto& interval = query.getTseries(_key); 32 | 33 | auto node_it = _nodes.begin(); 34 | for (auto range_it = range.begin(); range_it != range.end(); ++range_it) { 35 | 36 | nextNode(*range_it, node_it); 37 | 38 | while ((**range_it).endAfter((*node_it)->front())) { 39 | 40 | (*node_it)->query(interval, response); 41 | 42 | if (++node_it == _nodes.end()) return true; 43 | } 44 | } 45 | } else { 46 | return false; 47 | } 48 | return true; 49 | 50 | } else { 51 | return false; 52 | } 53 | } 54 | 55 | size_t TemporalDimension::hash(const response_container& container, response_container& response, Data& data) { 56 | std::cout << "\tHashing Temporal Dimension: " + _key + "... "; 57 | 58 | data.prepareKey(_key); 59 | 60 | size_t pivots_count = 0; 61 | 62 | for (const auto& ptr : container) { 63 | 64 | if (ptr == nullptr || (*ptr).empty()) continue; 65 | 66 | _nodes.emplace_back(std::make_unique(*ptr)); 67 | 68 | pivots_count += _nodes.back()->hash(this, response, data, *ptr); 69 | } 70 | _nodes.shrink_to_fit(); 71 | 72 | std::cout << "Done." << std::endl; 73 | data.dispose(); 74 | 75 | return pivots_count; 76 | } 77 | 78 | float TemporalDimension::bucketSize() const { 79 | return _bucketSize; 80 | } 81 | 82 | TemporalInterval& TemporalDimension::interval() { 83 | return _interval; 84 | } 85 | 86 | const TemporalInterval& TemporalDimension::interval() const { 87 | return _interval; 88 | } 89 | 90 | unsigned int TemporalDimension::intervalSize() const { 91 | return _interval.days(); 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TemporalDimension.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Hashing.h" 4 | #include "TemporalNode.h" 5 | 6 | class TemporalDimension : public Hashing { 7 | public: 8 | TemporalDimension(const std::string& key, size_t bucketSize); 9 | TemporalDimension(TemporalDimension&&) = default; 10 | TemporalDimension(const TemporalDimension&) = delete; 11 | 12 | ~TemporalDimension() = default; 13 | 14 | TemporalDimension& operator=(TemporalDimension&&) = default; 15 | TemporalDimension& operator=(const TemporalDimension&) = delete; 16 | 17 | bool query(const Query& query, const Response& range, Response& response) const override; 18 | size_t hash(const response_container& container, response_container& response, Data& data) override; 19 | 20 | float bucketSize() const; 21 | TemporalInterval& interval(); 22 | const TemporalInterval& interval() const; 23 | 24 | unsigned int intervalSize() const; 25 | 26 | protected: 27 | 28 | const float _bucketSize; 29 | TemporalInterval _interval; 30 | private: 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /src/TemporalInterval.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class TemporalInterval { 4 | public: 5 | TemporalInterval() : TemporalInterval(std::numeric_limits::max(), std::numeric_limits::min()) {}; 6 | TemporalInterval(temporal_t lower, temporal_t upper) : _bound{lower, upper} {}; 7 | virtual ~TemporalInterval() = default; 8 | 9 | inline temporal_t lower() const { 10 | return _bound[0]; 11 | } 12 | inline temporal_t upper() const { 13 | return _bound[1]; 14 | } 15 | 16 | inline void setLower(temporal_t value) { 17 | _bound[0] = value; 18 | } 19 | inline void setUpper(temporal_t value) { 20 | _bound[1] = value; 21 | } 22 | 23 | inline temporal_t days() const { 24 | return _bound[1] - _bound[0] + 1; 25 | } 26 | 27 | inline bool intersects(size_t lower, size_t upper) const { 28 | return (_bound[0] <= upper) && (_bound[1] >= lower); 29 | } 30 | 31 | inline bool contains(size_t lower, size_t upper) const { 32 | return (_bound[0] <= lower) && (_bound[1] >= upper); 33 | } 34 | 35 | friend std::ostream& operator<< (std::ostream& stream, const TemporalInterval& interval) { 36 | stream << interval.lower() << "/" << interval.upper(); 37 | return stream; 38 | } 39 | 40 | protected: 41 | std::array_bound{}; 42 | }; 43 | -------------------------------------------------------------------------------- /src/TemporalNode.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TemporalNode.h" 3 | 4 | #include "TemporalDimension.h" 5 | 6 | TemporalNode::TemporalNode(const Pivot& pivot) : _pivot(pivot) { } 7 | 8 | void TemporalNode::query(const TemporalInterval& interval, Response& response) const { 9 | if (interval.contains(lower(), upper())) { 10 | response.addElement(&_pivot); 11 | } else { 12 | queryInterval(interval, response); 13 | } 14 | } 15 | 16 | void TemporalNode::queryTseries(const TemporalInterval& interval, Response& response) const { 17 | if (interval.contains(lower(), upper())) { 18 | response.insert(_container.begin(), _container.end()); 19 | } else { 20 | queryInterval(interval, response); 21 | } 22 | } 23 | 24 | void TemporalNode::queryInterval(const TemporalInterval& interval, Response& response) const { 25 | if (!interval.intersects(lower(), upper())) return; 26 | 27 | auto lower = std::lower_bound(_container.begin(), _container.end(), interval.lower(), 28 | [](const TemporalPivot& o1, const temporal_t& o2) { return o2 > o1.value(); } 29 | ); 30 | 31 | auto upper = std::lower_bound(lower, _container.end(), interval.upper(), 32 | [](const TemporalPivot& o1, const temporal_t& o2) { return o2 > o1.value(); } 33 | ); 34 | 35 | response.insert(lower, upper); 36 | } 37 | 38 | size_t TemporalNode::hash(const TemporalDimension* hashing, response_container& response, Data& data, const Pivot& pivot) { 39 | 40 | std::map map{}; 41 | 42 | const float bucketSize = ((TemporalDimension*)hashing)->bucketSize(); 43 | 44 | for (auto i = pivot.front(); i < pivot.back(); ++i) { 45 | 46 | ulong value = std::floor(data.getIntProperty(i) / bucketSize) * bucketSize; 47 | 48 | // update TemporalInterval 49 | auto& interval = ((TemporalDimension*)hashing)->interval(); 50 | if (value > interval.upper()) interval.setUpper(value); 51 | if (value < interval.lower()) interval.setLower(value); 52 | 53 | map[value]++; 54 | 55 | data.setHash(i, value); 56 | } 57 | 58 | int accum = pivot.front(); 59 | for (auto entry : map) { 60 | 61 | int first = accum; 62 | accum += entry.second; 63 | int second = accum; 64 | 65 | _container.emplace_back(first, second, entry.first); 66 | } 67 | _container.shrink_to_fit(); 68 | 69 | for (auto& ptr : _container) { 70 | response.emplace_back(&ptr); 71 | } 72 | 73 | data.sortHash(pivot.front(), pivot.back()); 74 | 75 | return _container.size(); 76 | } 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/TemporalNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TemporalPivot.h" 4 | 5 | #include "Data.h" 6 | #include "Query.h" 7 | #include "Response.h" 8 | 9 | class TemporalDimension; 10 | 11 | class TemporalNode { 12 | public: 13 | TemporalNode(const Pivot& pivot); 14 | TemporalNode(TemporalNode&&) = default; 15 | TemporalNode(const TemporalNode&) = delete; 16 | 17 | ~TemporalNode() = default; 18 | 19 | TemporalNode& operator=(TemporalNode&&) = default; 20 | TemporalNode& operator=(const TemporalNode&) = delete; 21 | 22 | void query(const TemporalInterval& interval, Response& response) const; 23 | void queryTseries(const TemporalInterval& interval, Response& response) const; 24 | 25 | size_t hash(const TemporalDimension* hashing, response_container& response, Data& data, const Pivot& pivot); 26 | 27 | inline ulong lower() const; 28 | inline ulong upper() const; 29 | 30 | inline const ulong front() const; 31 | inline const ulong back() const; 32 | 33 | protected: 34 | void queryInterval(const TemporalInterval& interval, Response& response) const; 35 | 36 | Pivot _pivot; 37 | std::vector _container; 38 | }; 39 | 40 | const ulong TemporalNode::front() const { 41 | return _pivot.front(); 42 | } 43 | 44 | const ulong TemporalNode::back() const { 45 | return _pivot.back(); 46 | } 47 | 48 | ulong TemporalNode::lower() const { 49 | return _container.front().value(); 50 | } 51 | 52 | ulong TemporalNode::upper() const { 53 | return _container.back().value(); 54 | } 55 | -------------------------------------------------------------------------------- /src/TemporalPivot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Pivot.h" 4 | #include "TemporalInterval.h" 5 | 6 | class TemporalPivot : public Pivot { 7 | public: 8 | TemporalPivot(ulong first, ulong second, const temporal_t& value) : Pivot(first, second), _value(value) { } 9 | TemporalPivot(const Pivot& pivot, const temporal_t& value) : Pivot(pivot), _value(value) { } 10 | ~TemporalPivot() = default; 11 | 12 | inline const temporal_t& value() const; 13 | 14 | protected: 15 | temporal_t _value; 16 | }; 17 | 18 | const temporal_t& TemporalPivot::value() const { 19 | return _value; 20 | } 21 | -------------------------------------------------------------------------------- /src/TemporalSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "TemporalSerializer.h" 3 | #include "TemporalPivot.h" 4 | #include "TemporalDimension.h" 5 | 6 | TemporalSerializer& TemporalSerializer::getInstance() { 7 | static TemporalSerializer instance; 8 | return instance; 9 | } 10 | 11 | std::string TemporalSerializer::serialize(const TemporalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) { 12 | 13 | std::chrono::time_point start, end; 14 | start = std::chrono::high_resolution_clock::now(); 15 | 16 | std::vector aggregate(bins, 0); 17 | 18 | rapidjson::StringBuffer buffer; 19 | rapidjson::Writer writer(buffer); 20 | 21 | for (const auto& pivot : response.container()) { 22 | size_t index = util::linearScale(hashing->interval().lower(), hashing->interval().upper(), 0, bins - 1, ((TemporalPivot*)pivot)->value()); 23 | aggregate[index] += pivot->size(); 24 | } 25 | 26 | end = std::chrono::high_resolution_clock::now(); 27 | duration = std::chrono::duration_cast(end - start); 28 | 29 | writer.StartArray(); 30 | for (ulong i = 0; i < aggregate.size(); ++i) { 31 | if (aggregate[i] == 0) continue; 32 | writer.StartArray(); 33 | writer.Uint((i * (hashing->interval().days() / bins)) + hashing->interval().lower()); 34 | writer.Uint(aggregate[i]); 35 | writer.EndArray(); 36 | } 37 | writer.EndArray(); 38 | return buffer.GetString(); 39 | } 40 | 41 | std::string TemporalSerializer::serialize(const TemporalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) { 42 | 43 | std::chrono::time_point start, end; 44 | start = std::chrono::high_resolution_clock::now(); 45 | 46 | std::vector aggregate(bins, 0); 47 | 48 | rapidjson::StringBuffer buffer; 49 | rapidjson::Writer writer(buffer); 50 | 51 | auto it = tuple.second.begin(); 52 | for (const auto& pivot : tuple.first.container()) { 53 | int size = 0; 54 | 55 | while (it != tuple.second.end() && (*pivot) > (**it)) { 56 | size += (**it).size(); 57 | it++; 58 | } 59 | 60 | size_t index = util::linearScale(hashing->interval().lower(), hashing->interval().upper(), 0, bins - 1, ((TemporalPivot*)pivot)->value()); 61 | aggregate[index] += size; 62 | } 63 | 64 | end = std::chrono::high_resolution_clock::now(); 65 | duration = std::chrono::duration_cast(end - start); 66 | 67 | writer.StartArray(); 68 | for (ulong i = 0; i < aggregate.size(); ++i) { 69 | if (aggregate[i] == 0) continue; 70 | writer.StartArray(); 71 | writer.Uint((i * (hashing->interval().days() / bins)) + hashing->interval().lower()); 72 | writer.Uint(aggregate[i]); 73 | writer.EndArray(); 74 | } 75 | writer.EndArray(); 76 | return buffer.GetString(); 77 | } 78 | -------------------------------------------------------------------------------- /src/TemporalSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Serializer.h" 4 | #include "Response.h" 5 | 6 | class TemporalDimension; 7 | 8 | class TemporalSerializer : public Serializer { 9 | public: 10 | 11 | static TemporalSerializer& getInstance(); 12 | 13 | std::string serialize(const TemporalDimension* hashing, const Response& response, std::chrono::milliseconds& duration) override; 14 | std::string serialize(const TemporalDimension* hashing, const std::pair& tuple, std::chrono::milliseconds& duration) override; 15 | 16 | static const ulong bins { 256 }; 17 | }; 18 | -------------------------------------------------------------------------------- /src/TileNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Types.h" 4 | #include "TilePivot.h" 5 | 6 | #include "Data.h" 7 | #include "Query.h" 8 | #include "Response.h" 9 | 10 | class SpatialDimension; 11 | 12 | class TileNode { 13 | public: 14 | TileNode(const TilePivot& pivot); 15 | TileNode(const Pivot& pivot, const tile_t& value); 16 | 17 | TileNode(TileNode&&) = default; 18 | TileNode(const TileNode&) = delete; 19 | 20 | ~TileNode() = default; 21 | 22 | TileNode& operator=(TileNode&&) = default; 23 | TileNode& operator=(const TileNode&) = delete; 24 | 25 | void queryTile(const SpatialDimension* hashing, const Query& query, Response& response, ulong level) const; 26 | void queryRegion(const SpatialDimension* hashing, const Query& query, Response& response, ulong level) const; 27 | 28 | size_t hash(const SpatialDimension* hashing, response_container& response, Data& data); 29 | 30 | inline const ulong front() const; 31 | inline const ulong back() const; 32 | 33 | private: 34 | struct zoom_level { 35 | zoom_level() : first(0), second(0), z(0) {} 36 | ulong first, second, z; 37 | }; 38 | 39 | void aggregateTile(const SpatialDimension* hashing, const Query& query, Response& response, ulong level) const; 40 | 41 | inline ulong getIndex(ulong x, ulong y) const; 42 | 43 | inline bool last() const; 44 | inline void setLast(); 45 | 46 | size_t hashSingle(const SpatialDimension* hashing, Data& data, response_container& response, ulong zoom); 47 | size_t hashMultiple(const SpatialDimension* hashing, Data& data, response_container& response, std::vector zoom, ulong level); 48 | 49 | TilePivot _pivot; 50 | std::array, 4> _container{}; 51 | }; 52 | 53 | ulong TileNode::getIndex(ulong x, ulong y) const { 54 | if (x % 2 == 0) { 55 | if (y % 2 == 0) return 0; 56 | else return 1; 57 | } else { 58 | if (y % 2 == 0) return 2; 59 | else return 3; 60 | } 61 | } 62 | 63 | bool TileNode::last() const { 64 | return _pivot.last(); 65 | } 66 | 67 | void TileNode::setLast() { 68 | _pivot.setLast(); 69 | } 70 | 71 | const ulong TileNode::front() const { 72 | return _pivot.front(); 73 | } 74 | 75 | const ulong TileNode::back() const { 76 | return _pivot.back(); 77 | } -------------------------------------------------------------------------------- /src/TilePivot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Types.h" 4 | #include "Pivot.h" 5 | 6 | class TilePivot : public Pivot { 7 | public: 8 | TilePivot() = default; 9 | 10 | TilePivot(ulong first, ulong second, const tile_t& value) : Pivot(first, second), _value(value) { } 11 | TilePivot(const Pivot& pivot, const tile_t& value) : Pivot(pivot), _value(value) { } 12 | ~TilePivot() = default; 13 | 14 | inline const tile_t& value() const; 15 | 16 | inline bool last() const; 17 | inline void setLast(); 18 | 19 | protected: 20 | 21 | tile_t _value; 22 | }; 23 | 24 | const tile_t& TilePivot::value() const { 25 | return _value; 26 | } 27 | 28 | bool TilePivot::last() const { 29 | return _value.l == 1; 30 | } 31 | 32 | void TilePivot::setLast() { 33 | _value.l = 1; 34 | } 35 | -------------------------------------------------------------------------------- /src/TripLoader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DataLoader.h" 4 | #include "InMemoryDataGenerator.h" 5 | 6 | class TripLoader : public DataLoader { 7 | public: 8 | static TripLoader& getInstance(); 9 | virtual void write(const std::string& path) override; 10 | 11 | protected: 12 | virtual InMemoryDataGenerator getInMemoryGenerator(const std::string& path) override; 13 | 14 | private: 15 | TripLoader() = default; 16 | ~TripLoader() = default; 17 | }; 18 | -------------------------------------------------------------------------------- /src/Trunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace util { 4 | inline double trunc(double d) { 5 | return std::trunc(d * 100000.0) / 100000.0; 6 | } 7 | 8 | inline int linearScale(float min, float max, float a, float b, float x) { 9 | return std::floor((((b - a) * (x - min)) / (max - min)) + a); 10 | //return value >= b ? (b - 1) : (value < a ? a : value); 11 | } 12 | } // namespace util -------------------------------------------------------------------------------- /src/Types.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Types.h" 3 | #include "Mercator.h" 4 | 5 | Tile::Tile(int _x, int _y, ulong _z) : Tile::Tile((ulong)_x, (ulong)_y, _z) {} 6 | 7 | Tile::Tile(ulong _x, ulong _y, ulong _z) : x(_x), y(_y), z(_z) { 8 | lat0 = util::tiley2lat(y, z); 9 | lon0 = util::tilex2lon(x, z); 10 | 11 | lat1 = util::tiley2lat(y + 1, z); 12 | lon1 = util::tilex2lon(x + 1, z); 13 | } 14 | 15 | TileBounds::TileBounds(ulong _x0, ulong _y0, ulong _x1, ulong _y1, ulong _z) 16 | : x0(_x0), y0(_y0), x1(_x1), y1(_y1), z(_z) { 17 | 18 | lat0 = util::tiley2lat(y0, z); 19 | lon0 = util::tilex2lon(x0, z); 20 | 21 | lat1 = util::tiley2lat(y1 + 1, z); 22 | lon1 = util::tilex2lon(x1 + 1, z); 23 | } 24 | -------------------------------------------------------------------------------- /src/Types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct data_container { 5 | typedef std::vector result; 6 | }; 7 | 8 | typedef unsigned long ulong; 9 | 10 | typedef unsigned char categorical_t; 11 | 12 | typedef unsigned long temporal_t; 13 | 14 | enum DimensionType { 15 | Spatial, 16 | Categorical, 17 | Temporal 18 | }; 19 | 20 | struct tile_t { 21 | tile_t() : x(0), y(0), z(0), l(0) {} 22 | tile_t(uint32_t _x, uint32_t _y, uint8_t _z, uint8_t _l = 0) : x(_x), y(_y), z(_z), l(_l) {} 23 | 24 | inline bool operator ==(const tile_t &other) const { 25 | return (z == other.z && x == other.x && y == other.y); 26 | } 27 | 28 | uint64_t x : 29; 29 | uint64_t y : 29; 30 | uint64_t z : 5; 31 | uint64_t l : 1; 32 | 33 | friend std::ostream& operator<< (std::ostream& stream, const tile_t& tile) { 34 | stream << tile.x << "/" << tile.y << "/" << tile.z; 35 | return stream; 36 | } 37 | }; 38 | 39 | namespace std { 40 | template <> struct hash { 41 | std::size_t operator()(const tile_t k) const { 42 | return (k.x * ((2 << k.z) - 1)) + k.y; 43 | } 44 | }; 45 | } 46 | 47 | struct Tile { 48 | Tile() = default; 49 | Tile(int _x, int _y, ulong _z); 50 | Tile(ulong _x, ulong _y, ulong _z); 51 | 52 | int z { -1}; 53 | ulong x, y; 54 | float lat0, lon0, lat1, lon1; 55 | 56 | inline bool isValid() const { 57 | return z != -1; 58 | } 59 | 60 | inline bool operator ==(const tile_t &tile) const { 61 | return z == tile.z && x == tile.x && y == tile.y; 62 | } 63 | 64 | friend std::ostream& operator<< (std::ostream& stream, const Tile& tile) { 65 | stream << tile.x << "/" << tile.y << "/" << tile.z; 66 | return stream; 67 | } 68 | }; 69 | 70 | struct TileBounds { 71 | TileBounds() = default; 72 | TileBounds(ulong _x0, ulong _y0, ulong _x1, ulong _y1, ulong _z); 73 | 74 | int z{ -1 }; 75 | ulong x0, y0, x1, y1; 76 | float lat0, lon0, lat1, lon1; 77 | 78 | inline bool isValid() const { 79 | return z != -1; 80 | } 81 | 82 | friend std::ostream& operator<< (std::ostream& stream, const TileBounds& tile) { 83 | stream << tile.x0 << "/" << tile.y0 << "/" << tile.x1 << "/" << tile.y1; 84 | return stream; 85 | } 86 | }; 87 | 88 | struct LatLon { 89 | LatLon(double _lat, double _lon) : lat(_lat), lon(_lon) {} 90 | double lat, lon; 91 | }; 92 | 93 | struct LatLngBounds { 94 | LatLngBounds(LatLon _latlon0, LatLon _latlon1) : latlon0(_latlon0), latlon1(_latlon1) {} 95 | LatLon latlon0, latlon1; 96 | }; 97 | 98 | struct Schema { 99 | std::string name, path, loader; 100 | 101 | float fraction { 1.f }; 102 | ulong leaf { 32 }; 103 | ulong sql_threshold { 250 }; 104 | 105 | std::vector spatial; 106 | std::vector> categorical; 107 | std::vector> temporal; 108 | }; 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // cpp-hashedcubes.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NOMINMAX 4 | #define _CRT_SECURE_NO_WARNINGS 5 | 6 | #pragma warning( disable : 4250) 7 | #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS 8 | 9 | // stl 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #define _USE_MATH_DEFINES 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | 51 | // meerkat 52 | #include 53 | 54 | // rapidjson 55 | #include 56 | #include 57 | 58 | // boost 59 | #include 60 | 61 | #include 62 | 63 | #include 64 | #include 65 | 66 | #include 67 | #include 68 | 69 | #include 70 | #include 71 | #include 72 | 73 | #include 74 | #include 75 | #include 76 | #include 77 | 78 | // util 79 | #include "Trunc.h" 80 | #include "Date.h" 81 | #include "StringUtil.h" 82 | 83 | #include "Types.h" 84 | #include "Mercator.h" 85 | 86 | #include "ResidentSetSize.h" 87 | 88 | #include 89 | #include "SQLiteCpp/SQLiteCpp.h" 90 | 91 | typedef std::tuple token_t; 92 | typedef std::tuple tuple_t; 93 | 94 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 95 | TypeName(const TypeName&) = delete; \ 96 | void operator=(const TypeName&) = delete; 97 | 98 | template struct bits; 99 | template<> struct bits<1> { enum { value = 1 }; }; 100 | template struct bits { enum { value = 1 + bits<(N >> 1)>::value }; }; 101 | -------------------------------------------------------------------------------- /xml/brightkite-immens.xml: -------------------------------------------------------------------------------- 1 | 2 | snap 3 | brightkite 4 | ./data/brightkite/ 5 | 32 6 | 7 | 8 | 0 9 | 10 | 11 | month_of_year 12 | 12 13 | 14 | 15 | hour_of_day 16 | 24 17 | 18 | 19 | day_of_month 20 | 31 21 | 22 | 23 | -------------------------------------------------------------------------------- /xml/brightkite-nanocubes.xml: -------------------------------------------------------------------------------- 1 | 2 | snap 3 | brightkite 4 | ./data/brightkite/ 5 | 32 6 | 100 7 | 8 | 9 | 0 10 | 11 | 12 | day_of_week 13 | 7 14 | 15 | 16 | hour_of_day 17 | 24 18 | 19 | 20 | tseries 21 | 604800 22 | 23 | 24 | -------------------------------------------------------------------------------- /xml/gowalla.xml: -------------------------------------------------------------------------------- 1 | 2 | snap 3 | gowalla 4 | ./data/gowalla/ 5 | 32 6 | 100 7 | 8 | 9 | 0 10 | 11 | 12 | day_of_week 13 | 7 14 | 15 | 16 | hour_of_day 17 | 24 18 | 19 | 20 | tseries 21 | 604800 22 | 23 | 24 | --------------------------------------------------------------------------------