├── .cproject
├── .gitignore
├── .project
├── LICENSE
├── Makefile
├── README.md
├── std
├── algorithm.h
├── array.h
├── bits.cpp
├── bits.h
├── boundary.h
├── container.h
├── file.cpp
├── file.h
├── fill.h
├── filter.h
├── graph.h
├── hash_map.h
├── hash_set.cpp
├── hash_set.h
├── heap.h
├── implier.h
├── index_list.h
├── interface.h
├── io.cpp
├── io.h
├── list.h
├── map.h
├── pair.h
├── partite.h
├── range.h
├── search.h
├── slice.h
├── sort.h
├── sparse_range.h
├── stream.cpp
├── stream.h
├── string.cpp
└── string.h
└── test
├── algorithm.cpp
├── array_iterator.cpp
├── array_struct.cpp
├── bits.cpp
├── fill_iterator.cpp
├── fill_struct.cpp
├── filter.cpp
├── graph_iterator.cpp
├── graph_struct.cpp
├── hash_map_struct.cpp
├── hash_set_iterator.cpp
├── hash_set_struct.cpp
├── heap.cpp
├── implier.cpp
├── index_list_iterator.cpp
├── index_list_struct.cpp
├── list_iterator.cpp
├── list_struct.cpp
├── map.cpp
├── pair.cpp
├── range_iterator.cpp
├── range_struct.cpp
├── search.cpp
├── slice_iterator.cpp
├── slice_struct.cpp
├── sort.cpp
├── sparse_range_iterator.cpp
└── sparse_range_struct.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
30 | # Dependency Files
31 | *.d
32 |
33 | # Misc Files
34 | .settings
35 | test_stdcore
36 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | stdcore
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.core.ccnature
24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Ned Bingham
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CXXFLAGS = -g -O2 -Wall -fmessage-length=0 -I.
2 | # -g -fprofile-arcs -ftest-coverage
3 | SOURCES := $(wildcard std/*.cpp)
4 | TESTS := $(wildcard test/*.cpp)
5 | OBJECTS := $(SOURCES:%.cpp=%.o)
6 | TEST_OBJECTS := $(TESTS:.cpp=.o)
7 | DEPS := $(OBJECTS:.o=.d)
8 | TEST_DEPS := $(TEST_OBJECTS:.o=.d)
9 | GTEST := ../googletest
10 | GTEST_I := -I$(GTEST)/include -I.
11 | GTEST_L := -L$(GTEST) -L.
12 | TARGET = libstdcore.a
13 | TEST_TARGET = test_stdcore
14 |
15 | -include $(DEPS)
16 | -include $(TEST_DEPS)
17 |
18 | all: lib
19 |
20 | lib: $(TARGET)
21 |
22 | test: lib $(TEST_TARGET)
23 |
24 | check: test
25 | ./$(TEST_TARGET)
26 |
27 | $(TARGET): $(OBJECTS)
28 | ar rvs $(TARGET) $(OBJECTS)
29 |
30 | std/%.o: std/%.cpp
31 | $(CXX) $(CXXFLAGS) -MM -MF $(patsubst %.o,%.d,$@) -MT $@ -c $<
32 | $(CXX) $(CXXFLAGS) -c -o $@ $<
33 |
34 | $(TEST_TARGET): $(TEST_OBJECTS) test/gtest_main.o
35 | $(CXX) $(CXXFLAGS) $(GTEST_L) $^ -pthread -lstdcore -lgtest -o $(TEST_TARGET)
36 |
37 | test/%.o: test/%.cpp
38 | $(CXX) $(CXXFLAGS) $(GTEST_I) -MM -MF $(patsubst %.o,%.d,$@) -MT $@ -c $<
39 | $(CXX) $(CXXFLAGS) $(GTEST_I) $< -c -o $@
40 |
41 | test/gtest_main.o: $(GTEST)/src/gtest_main.cc
42 | $(CXX) $(CXXFLAGS) $(GTEST_I) $< -c -o $@
43 |
44 | clean:
45 | rm -f std/*.o test/*.o
46 | rm -f std/*.d test/*.d
47 | rm -f std/*.gcda test/*.gcda
48 | rm -f std/*.gcno test/*.gcno
49 | rm -f $(TARGET) $(TEST_TARGET)
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Standard Core
2 |
3 | Welcome to the Standard Core. This is a library for standard containers and their associated algorithms.
4 |
5 | For thorough documentation, check out the [wiki](https://github.com/nbingham1/stdcore/wiki).
6 |
7 | # Why does this exist?
8 |
9 | I've been working with C++ for over a decade at this point. Every now and then, I would need to do something that the C++ Standard Library couldn't do. So I would make the necessary thing and move on. After a while, I noticed that I had managed to implement a full standard library scattered throughout my code base. So, I pulled it all together into a library, and well... here we are.
10 |
11 | ## Why should I care?
12 |
13 | Quite by accident, this library is an interesting case study of a different programming paradigm. I make no claims that this code is optimized, verified, secured, or stabilized. It is provided as is with no guarantee and no promises. However, the resulting API is simple, clean, and expressive. So let's get started.
14 |
15 | # Linking
16 |
17 | Lets start with a basic program which will include the array header. Every header in this library is found in the `std` directory. Every structure and function are contained within the `core` namespace.
18 |
19 | ```c++
20 | #include
21 | #include
22 |
23 | using namespace core;
24 |
25 | int main()
26 | {
27 | return 0;
28 | }
29 | ```
30 |
31 | This can be compiled with the following command.
32 |
33 | ```
34 | g++ example.cpp -Ipath/to/include -Lpath/to/lib -lstdcore -o example
35 | ```
36 |
37 | # Paradigms
38 |
39 | This library differs from the C++ Standard Library on a few key paradigms. It is these paradigms that make this library unique.
40 |
41 | ## The Simple Things in Life
42 |
43 | First, while the typical array, list, map, and string containers are still the center of the library, there are also dedicated containers for simpler data. This means fill, range, and sparse_range.
44 |
45 | ```c++
46 | cout << "fill = " << fill(7, 5) << endl;
47 | cout << "range = " << range(5, 15) << endl;
48 | cout << "sparse_range = " << sparse_range(5, 25, 2) << endl;
49 | ```
50 |
51 | ```
52 | fill = {5, 5, 5, 5, 5, 5, 5}
53 | range = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
54 | sparse_range = {5, 7, 9, 11, 13, 15, 17, 19, 21, 23}
55 | ```
56 |
57 | ## Power to the Iterator
58 |
59 | Second, iterators have full power to modify their base structure. This means that iterators can push, pop, drop, replace, append, and swap. These actions can still invalidate other iterators depending upon the container structure.
60 |
61 | ```c++
62 | array arr = range(0, 10);
63 | cout << "arr = " << arr << endl << endl;
64 |
65 | cout << "arr.at(5).pop(3) = " << arr.at(5).pop(3) << endl;
66 | cout << "arr = " << arr << endl << endl;
67 |
68 | cout << "arr.at(2).push(3)" << endl;
69 | arr.at(2).push(3);
70 | cout << "arr = " << arr << endl << endl;
71 |
72 | cout << "arr.at(3).append(range(2, 8))" << endl;
73 | arr.at(3).append(range(2, 8));
74 | cout << "arr = " << arr << endl << endl;
75 |
76 | cout << "arr.at(4).replace(3, 10)" << endl;
77 | arr.at(4).replace(3, 10);
78 | cout << "arr = " << arr << endl;
79 | ```
80 |
81 | ```
82 | arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
83 |
84 | arr.at(5).pop(3) = {5, 6, 7}
85 | arr = {0, 1, 2, 3, 4, 8, 9}
86 |
87 | arr.at(2).push(3)
88 | arr = {0, 1, 3, 2, 3, 4, 8, 9}
89 |
90 | arr.at(3).append(range(2, 8))
91 | arr = {0, 1, 3, 2, 3, 4, 5, 6, 7, 2, 3, 4, 8, 9}
92 |
93 | arr.at(4).replace(3, 10)
94 | arr = {0, 1, 3, 2, 10, 6, 7, 2, 3, 4, 8, 9}
95 | ```
96 |
97 | ## Slice and Dice
98 |
99 | Third, this has a full implementation of slices. You can use any container to slice another container. These slices make the API significantly cleaner and easier to use while introducing very little run-time overhead.
100 |
101 | ```c++
102 | array arr = range(0, 10);
103 | cout << "arr = " << arr << endl << endl;
104 |
105 | slice::iterator> > slc = arr.sub(2, 6);
106 | cout << "slc = " << slc << endl << endl;
107 |
108 | cout << "slc[1] = 100" << endl;
109 | slc[1] = 100;
110 | cout << "slc = " << slc << endl;
111 | cout << "arr = " << arr << endl << endl;
112 |
113 | slice::iterator> > slc2 = array_t(4, 2, 5, 0, 1).sample(arr);
114 | cout << "slc2 = " << slc2 << endl << endl;
115 |
116 | cout << "slc2[1] = 200" << endl;
117 | slc2[1] = 200;
118 | cout << "slc2 = " << slc2 << endl;
119 | cout << "arr = " << arr << endl;
120 | cout << "slc = " << slc << endl;
121 | ```
122 |
123 | ```
124 | arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
125 |
126 | slc = {2, 3, 4, 5}
127 |
128 | slc[1] = 100
129 | slc = {2, 100, 4, 5}
130 | arr = {0, 1, 2, 100, 4, 5, 6, 7, 8, 9}
131 |
132 | slc2 = {2, 5, 0, 1}
133 |
134 | slc2[1] = 200
135 | slc2 = {2, 200, 0, 1}
136 | arr = {0, 1, 2, 100, 4, 200, 6, 7, 8, 9}
137 | slc = {2, 100, 4, 200}
138 | ```
139 |
140 | ## Simplicity Breeds Sanity
141 |
142 | All algorithmic functions like sort, unique, reverse, etc can be run either in place or on a copy of the container in line.
143 |
144 | ```c++
145 | array arr = array_t(10, 2, 6, 3, 2, 7, 3, 7, 5, 1, 0);
146 | cout << "arr = " << arr << endl << endl;
147 |
148 | cout << "sort_quick(arr) = " << sort_quick(arr) << endl;
149 | cout << "arr = " << arr << endl << endl;
150 |
151 | cout << "sort_quick_inplace(arr)" << endl;
152 | sort_quick_inplace(arr);
153 | cout << "arr = " << arr << endl;
154 | ```
155 |
156 | ```
157 | arr = {2, 6, 3, 2, 7, 3, 7, 5, 1, 0}
158 |
159 | sort_quick(arr) = {0, 1, 2, 2, 3, 3, 5, 6, 7, 7}
160 | arr = {2, 6, 3, 2, 7, 3, 7, 5, 1, 0}
161 |
162 | sort_quick_inplace(arr)
163 | arr = {0, 1, 2, 2, 3, 3, 5, 6, 7, 7}
164 | ```
165 |
--------------------------------------------------------------------------------
/std/bits.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * bits.cpp
3 | *
4 | * Created on: Jun 20, 2015
5 | * Author: nbingham
6 | */
7 |
8 | #include
9 |
10 | namespace core
11 | {
12 |
13 | bits::bits()
14 | {
15 |
16 | }
17 |
18 | bits::~bits()
19 | {
20 |
21 | }
22 |
23 | bits &operator<<(bits &str, char v)
24 | {
25 | str.push_back((unsigned char)v);
26 | return str;
27 | }
28 |
29 | bits &operator<<(bits &str, unsigned char v)
30 | {
31 | str.push_back(v);
32 | return str;
33 | }
34 |
35 | bits &operator<<(bits &str, short v)
36 | {
37 | str.reserve(str.size() + sizeof(short));
38 | memcpy(str.data + str.size(), &v, sizeof(short));
39 | str.alloc_back(sizeof(short));
40 | return str;
41 | }
42 |
43 | bits &operator<<(bits &str, unsigned short v)
44 | {
45 | str.reserve(str.size() + sizeof(unsigned short));
46 | memcpy(str.data + str.size(), &v, sizeof(unsigned short));
47 | str.alloc_back(sizeof(unsigned short));
48 | return str;
49 | }
50 |
51 | bits &operator<<(bits &str, int v)
52 | {
53 | str.reserve(str.size() + sizeof(int));
54 | memcpy(str.data + str.size(), &v, sizeof(int));
55 | str.alloc_back(sizeof(int));
56 | return str;
57 | }
58 |
59 | bits &operator<<(bits &str, unsigned int v)
60 | {
61 | str.reserve(str.size() + sizeof(unsigned int));
62 | memcpy(str.data + str.size(), &v, sizeof(unsigned int));
63 | str.alloc_back(sizeof(unsigned int));
64 | return str;
65 | }
66 |
67 | bits &operator<<(bits &str, long v)
68 | {
69 | str.reserve(str.size() + sizeof(long));
70 | memcpy(str.data + str.size(), &v, sizeof(long));
71 | str.alloc_back(sizeof(long));
72 | return str;
73 | }
74 |
75 | bits &operator<<(bits &str, unsigned long v)
76 | {
77 | str.reserve(str.size() + sizeof(unsigned long));
78 | memcpy(str.data + str.size(), &v, sizeof(unsigned long));
79 | str.alloc_back(sizeof(unsigned long));
80 | return str;
81 | }
82 |
83 | bits &operator<<(bits &str, long long v)
84 | {
85 | str.reserve(str.size() + sizeof(long long));
86 | memcpy(str.data + str.size(), &v, sizeof(long long));
87 | str.alloc_back(sizeof(long long));
88 | return str;
89 | }
90 |
91 | bits &operator<<(bits &str, unsigned long long v)
92 | {
93 | str.reserve(str.size() + sizeof(unsigned long long));
94 | memcpy(str.data + str.size(), &v, sizeof(unsigned long long));
95 | str.alloc_back(sizeof(unsigned long long));
96 | return str;
97 | }
98 |
99 | bits &operator<<(bits &str, bool v)
100 | {
101 | str.reserve(str.size() + sizeof(bool));
102 | memcpy(str.data + str.size(), &v, sizeof(bool));
103 | str.alloc_back(sizeof(bool));
104 | return str;
105 | }
106 |
107 | bits &operator<<(bits &str, float v)
108 | {
109 | str.reserve(str.size() + sizeof(float));
110 | memcpy(str.data + str.size(), &v, sizeof(float));
111 | str.alloc_back(sizeof(float));
112 | return str;
113 | }
114 |
115 | bits &operator<<(bits &str, double v)
116 | {
117 | str.reserve(str.size() + sizeof(double));
118 | memcpy(str.data + str.size(), &v, sizeof(double));
119 | str.alloc_back(sizeof(double));
120 | return str;
121 | }
122 |
123 | bits &operator<<(bits &str, const char *v)
124 | {
125 | int n = strlen(v);
126 | str.reserve(str.size() + n);
127 | memcpy(str.data + str.size(), v, n);
128 | str.alloc_back(n);
129 | return str;
130 | }
131 |
132 | bits &operator<<(bits &str, char *v)
133 | {
134 | int n = strlen(v);
135 | str.reserve(str.size() + n);
136 | memcpy(str.data + str.size(), v, n);
137 | str.alloc_back(n);
138 | return str;
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/std/bits.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bits.h
3 | *
4 | * Created on: Jun 20, 2015
5 | * Author: nbingham
6 | */
7 |
8 | #pragma once
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | namespace core
15 | {
16 |
17 | struct bits : array
18 | {
19 | bits();
20 | ~bits();
21 |
22 | using typename array::type;
23 | using typename array::iterator;
24 | using typename array::const_iterator;
25 |
26 | using array::begin;
27 | using array::end;
28 | using array::rbegin;
29 | using array::rend;
30 | using array::sub;
31 | using array::size;
32 |
33 | using array::operator=;
34 | };
35 |
36 | bits &operator<<(bits &str, char v);
37 | bits &operator<<(bits &str, short v);
38 | bits &operator<<(bits &str, int v);
39 | bits &operator<<(bits &str, long v);
40 | bits &operator<<(bits &str, long long v);
41 | bits &operator<<(bits &str, unsigned char v);
42 | bits &operator<<(bits &str, unsigned short v);
43 | bits &operator<<(bits &str, unsigned int v);
44 | bits &operator<<(bits &str, unsigned long v);
45 | bits &operator<<(bits &str, unsigned long long v);
46 | bits &operator<<(bits &str, bool v);
47 | bits &operator<<(bits &str, float v);
48 | bits &operator<<(bits &str, double v);
49 | bits &operator<<(bits &str, const char *v);
50 | bits &operator<<(bits &str, char *v);
51 |
52 | template
53 | bits &operator<<(bits &str, const container &v)
54 | {
55 | for (typename container::const_iterator i = v.begin(); i != v.end(); i++)
56 | str << *i;
57 | return str;
58 | }
59 |
60 | template
61 | bits &operator<<(bits &str, const pair &v)
62 | {
63 | str << v.first << v.second;
64 | return str;
65 | }
66 |
67 | template
68 | bits &operator<<(bits &str, const implier &v)
69 | {
70 | str << v.key << v.value;
71 | return str;
72 | }
73 |
74 | template
75 | bits &hash_data(bits &str, T value)
76 | {
77 | str << value;
78 | return str;
79 | }
80 |
81 | template
82 | bits &hash_data(bits &str, const implier &value)
83 | {
84 | str << value.key;
85 | return str;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/std/boundary.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #ifndef NULL
6 | #define NULL 0
7 | #endif
8 |
9 | namespace core
10 | {
11 |
12 | template
13 | struct boundary;
14 |
15 | template
16 | struct boundary_const_iterator
17 | {
18 | friend class boundary;
19 |
20 | protected:
21 | const boundary *root;
22 | value_type value;
23 |
24 | boundary_const_iterator(const boundary *root, value_type value)
25 | {
26 | this->root = root;
27 | this->value = value;
28 | }
29 | public:
30 | typedef value_type type;
31 |
32 | boundary_const_iterator()
33 | {
34 | this->root = NULL;
35 | }
36 |
37 | ~boundary_const_iterator()
38 | {
39 |
40 | }
41 |
42 | operator bool() const
43 | {
44 | return root != NULL && value != root->start-1 && value != root->finish;
45 | }
46 |
47 | value_type operator*() const
48 | {
49 | return value;
50 | }
51 |
52 | const value_type *operator->() const
53 | {
54 | return &value;
55 | }
56 |
57 | const value_type *ptr() const
58 | {
59 | return &value;
60 | }
61 |
62 | value_type get() const
63 | {
64 | return value;
65 | }
66 |
67 | int idx() const
68 | {
69 | return value - root->start;
70 | }
71 |
72 | boundary_const_iterator operator++(int)
73 | {
74 | boundary_const_iterator result = *this;
75 | value++;
76 | return result;
77 | }
78 |
79 | boundary_const_iterator operator--(int)
80 | {
81 | boundary_const_iterator result = *this;
82 | value--;
83 | return result;
84 | }
85 |
86 | boundary_const_iterator &operator++()
87 | {
88 | value++;
89 | return *this;
90 | }
91 |
92 | boundary_const_iterator &operator--()
93 | {
94 | value--;
95 | return *this;
96 | }
97 |
98 | boundary_const_iterator &operator+=(int n)
99 | {
100 | value += n;
101 | return *this;
102 | }
103 |
104 | boundary_const_iterator &operator-=(int n)
105 | {
106 | value -= n;
107 | return *this;
108 | }
109 |
110 | boundary_const_iterator operator+(int n) const
111 | {
112 | boundary_const_iterator result;
113 | result.root = root;
114 | result.value = value + n;
115 | return result;
116 | }
117 |
118 | boundary_const_iterator operator-(int n) const
119 | {
120 | boundary_const_iterator result;
121 | result.root = root;
122 | result.value = value - n;
123 | return result;
124 | }
125 |
126 | bool operator==(boundary_const_iterator i) const
127 | {
128 | return value == i.value;
129 | }
130 |
131 | bool operator!=(boundary_const_iterator i) const
132 | {
133 | return value != i.value;
134 | }
135 |
136 | int operator-(boundary_const_iterator i) const
137 | {
138 | return value - i.value;
139 | }
140 |
141 | boundary sub(int length) const
142 | {
143 | value_type bound = value+length;
144 | if (length < 0)
145 | return boundary(bound < root->start ? root->start : bound, value);
146 | else
147 | return boundary(value, bound > root->finish ? root->finish : bound);
148 | }
149 |
150 | boundary subcpy(int length) const
151 | {
152 | value_type bound = value+length;
153 | if (length < 0)
154 | return boundary(bound < root->start ? root->start : bound, value);
155 | else
156 | return boundary(value, bound > root->finish ? root->finish : bound);
157 | }
158 |
159 | boundary sub() const
160 | {
161 | return boundary(value, root->finish);
162 | }
163 |
164 | boundary subcpy() const
165 | {
166 | return boundary(value, root->finish);
167 | }
168 | };
169 |
170 | template
171 | struct boundary : container, boundary_const_iterator >
172 | {
173 | typedef container, boundary_const_iterator > super;
174 |
175 | using typename super::type;
176 | using typename super::iterator;
177 | using typename super::const_iterator;
178 |
179 | value_type start;
180 | value_type finish;
181 |
182 | boundary()
183 | {
184 | }
185 |
186 | boundary(value_type start, value_type finish)
187 | {
188 | this->start = start;
189 | this->finish = finish;
190 | }
191 |
192 | template
193 | boundary(const boundary &a)
194 | {
195 | this->start = a.start;
196 | this->finish = a.finish;
197 | }
198 |
199 | boundary(const_iterator start, const_iterator finish)
200 | {
201 | this->start = *start;
202 | this->finish = *finish;
203 | }
204 |
205 | virtual ~boundary()
206 | {
207 |
208 | }
209 |
210 | // Utility
211 |
212 | int size() const
213 | {
214 | return finish - start;
215 | }
216 |
217 | // Iterators
218 |
219 | const_iterator begin() const
220 | {
221 | return const_iterator(this, start);
222 | }
223 |
224 | const_iterator end() const
225 | {
226 | return const_iterator(this, finish);
227 | }
228 |
229 | const_iterator rbegin() const
230 | {
231 | return const_iterator(this, finish-1);
232 | }
233 |
234 | const_iterator rend() const
235 | {
236 | return const_iterator(this, start-1);
237 | }
238 |
239 | const_iterator at(int i) const
240 | {
241 | if (i < 0)
242 | i += size();
243 |
244 | return const_iterator(this, start + i);
245 | }
246 |
247 | // Accessors
248 |
249 | value_type front() const
250 | {
251 | return start;
252 | }
253 |
254 | value_type back() const
255 | {
256 | return finish-1;
257 | }
258 |
259 | value_type get(int i) const
260 | {
261 | if (i < 0)
262 | i += size();
263 | return start + i;
264 | }
265 |
266 | value_type operator[](int i) const
267 | {
268 | if (i < 0)
269 | i += size();
270 | return start + i;
271 | }
272 |
273 | // Slicing
274 | boundary sub(int start, int end) const
275 | {
276 | int count = size();
277 | start = start < 0 ? count + start : start;
278 | end = end < 0 ? count + end : end;
279 | return boundary(this->start + start, this->start + end);
280 | }
281 |
282 | boundary sub(int start) const
283 | {
284 | int count = size();
285 | start = start < 0 ? count + start : start;
286 | return boundary(this->start + start, this->finish);
287 | }
288 |
289 | boundary sub() const
290 | {
291 | return boundary(start, finish);
292 | }
293 |
294 | boundary subcpy(int start, int end) const
295 | {
296 | int count = size();
297 | start = start < 0 ? count + start : start;
298 | end = end < 0 ? count + end : end;
299 | return boundary(this->start + start, this->start + end);
300 | }
301 |
302 | boundary subcpy(int start) const
303 | {
304 | int count = size();
305 | start = start < 0 ? count + start : start;
306 | return boundary(this->start + start, this->finish);
307 | }
308 |
309 | boundary subcpy() const
310 | {
311 | return boundary(start, finish);
312 | }
313 |
314 | template
315 | boundary sample(container &c) const
316 | {
317 | return boundary(c.at(start), c.at(finish));
318 | }
319 |
320 | template
321 | boundary sample(const container &c) const
322 | {
323 | return boundary(c.at(start), c.at(finish));
324 | }
325 |
326 | boundary idx() const
327 | {
328 | return boundary(start.idx(), finish.idx());
329 | }
330 |
331 | // Modifiers
332 |
333 | void swap(boundary &root)
334 | {
335 | value_type tmp_start = start;
336 | value_type tmp_finish = finish;
337 | start = root.start;
338 | finish = root.finish;
339 | root.start = tmp_start;
340 | root.finish = tmp_finish;
341 | }
342 |
343 | boundary &operator=(const boundary &root)
344 | {
345 | start = root.start;
346 | finish = root.finish;
347 | return *this;
348 | }
349 | };
350 |
351 | // Faster comparison algorithms
352 |
353 | template
354 | bool operator==(boundary s1, boundary s2)
355 | {
356 | return (s1.start == s2.start && s1.finish == s2.finish);
357 | }
358 |
359 | template
360 | bool operator!=(boundary s1, boundary s2)
361 | {
362 | return (s1.start != s2.start || s1.finish != s2.finish);
363 | }
364 |
365 | template
366 | bool operator<(boundary s1, boundary s2)
367 | {
368 | return (s1.start < s2.start || (s1.start == s2.start &&
369 | s1.finish < s2.finish));
370 | }
371 |
372 | template
373 | bool operator>(boundary s1, boundary s2)
374 | {
375 | return (s1.start > s2.start || (s1.start == s2.start &&
376 | s1.finish > s2.finish));
377 | }
378 |
379 | template
380 | bool operator<=(boundary s1, boundary s2)
381 | {
382 | return (s1.start < s2.start || (s1.start == s2.start &&
383 | s1.finish <= s2.finish));
384 | }
385 |
386 | template
387 | bool operator>=(boundary s1, boundary s2)
388 | {
389 | return (s1.start > s2.start || (s1.start == s2.start &&
390 | s1.finish >= s2.finish));
391 | }
392 |
393 | // Constructers that auto-determine value_type
394 | template
395 | boundary boundary_t(value_type start, value_type finish)
396 | {
397 | return boundary(start, finish);
398 | }
399 |
400 | }
401 |
402 |
--------------------------------------------------------------------------------
/std/container.h:
--------------------------------------------------------------------------------
1 | /*
2 | * slice.h
3 | *
4 | * Created on: Oct 13, 2014
5 | * Author: nbingham
6 | */
7 |
8 | #pragma once
9 |
10 | namespace core
11 | {
12 |
13 | template
14 | struct container
15 | {
16 | typedef value_type type;
17 | typedef container_iterator iterator;
18 | typedef container_const_iterator const_iterator;
19 |
20 | container() {}
21 | virtual ~container() {};
22 |
23 | virtual const_iterator begin() const = 0;
24 | virtual const_iterator end() const = 0;
25 | virtual const_iterator rbegin() const = 0;
26 | virtual const_iterator rend() const = 0;
27 | };
28 |
29 | template
30 | bool compare(const container &a, const container &b)
31 | {
32 | ci0 i = a.begin();
33 | ci1 j = b.begin();
34 | for (; i && j; i++, j++)
35 | {
36 | if (*i < *j)
37 | return -1;
38 | else if (*j < *i)
39 | return 1;
40 | }
41 | if (j)
42 | return -1;
43 | else if (i)
44 | return 1;
45 | else
46 | return 0;
47 | }
48 |
49 | template
50 | bool operator==(const container &a, const container &b)
51 | {
52 | ci0 i = a.begin();
53 | ci1 j = b.begin();
54 | for (; i && j; i++, j++)
55 | if (!(*i == *j))
56 | return false;
57 |
58 | return !(i || j);
59 | }
60 |
61 | template
62 | bool operator!=(const container &a, const container &b)
63 | {
64 | return !(a == b);
65 | }
66 |
67 | template
68 | bool operator<(const container &a, const container &b)
69 | {
70 | ci0 i = a.begin();
71 | ci1 j = b.begin();
72 | for (; i && j; i++, j++)
73 | {
74 | if (*i < *j)
75 | return true;
76 | else if (!(*i == *j))
77 | return false;
78 | }
79 |
80 | return j;
81 | }
82 |
83 | template
84 | bool operator>(const container &a, const container &b)
85 | {
86 | ci0 i = a.begin();
87 | ci1 j = b.begin();
88 | for (; i && j; i++, j++)
89 | {
90 | if (*i > *j)
91 | return true;
92 | else if (!(*i == *j))
93 | return false;
94 | }
95 |
96 | return i;
97 | }
98 |
99 | template
100 | bool operator<=(const container &a, const container &b)
101 | {
102 | return !(a > b);
103 | }
104 |
105 | template
106 | bool operator>=(const container &a, const container &b)
107 | {
108 | return !(a < b);
109 | }
110 |
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/std/file.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * file.cpp
3 | *
4 | * Created on: Feb 5, 2014
5 | * Author: nbingham
6 | */
7 |
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | namespace core
15 | {
16 |
17 | file::file()
18 | {
19 | desc = -1;
20 | }
21 |
22 | file::file(int desc)
23 | {
24 | this->desc = desc;
25 | index = -1;
26 | }
27 |
28 | file::file(const file ©)
29 | {
30 | desc = ::dup(copy.desc);
31 | index = copy.index;
32 | }
33 |
34 | file::file(const char *filename, unsigned char mode, unsigned char owner, unsigned char group, unsigned char user)
35 | {
36 | desc = -1;
37 | open(filename, mode, owner, group, user);
38 | }
39 |
40 | file::file(array filename, unsigned char mode, unsigned char owner, unsigned char group, unsigned char user)
41 | {
42 | desc = -1;
43 | open(filename, mode, owner, group, user);
44 | }
45 |
46 | file::~file()
47 | {
48 | close();
49 | }
50 |
51 | file::operator bool() const
52 | {
53 | return desc >= 0;
54 | }
55 |
56 | bool file::open(const char *filename, unsigned char mode, unsigned char owner, unsigned char group, unsigned char user)
57 | {
58 | if (desc >= 3)
59 | return false;
60 |
61 | int oflags = O_CREAT;
62 | int rights = 0;
63 | index = 0;
64 |
65 | if ((mode & rw) == rw)
66 | oflags |= O_RDWR;
67 | else if (mode & r)
68 | oflags |= O_RDONLY;
69 | else if (mode & w)
70 | oflags |= O_WRONLY;
71 |
72 | if (mode & replace)
73 | oflags |= O_TRUNC;
74 |
75 | if (mode & exists)
76 | oflags &= ~O_CREAT;
77 | else if (mode & not_exists)
78 | oflags |= O_EXCL;
79 |
80 | if (owner & r)
81 | rights |= S_IRUSR;
82 | if (owner & w)
83 | rights |= S_IWUSR;
84 | if (owner & x)
85 | rights |= S_IXUSR;
86 |
87 | if (group & r)
88 | rights |= S_IRGRP;
89 | if (group & w)
90 | rights |= S_IWGRP;
91 | if (group & x)
92 | rights |= S_IXGRP;
93 |
94 | if (user & r)
95 | rights |= S_IROTH;
96 | if (user & w)
97 | rights |= S_IWOTH;
98 | if (user & x)
99 | rights |= S_IXOTH;
100 |
101 | desc = ::open(filename, oflags, rights);
102 | return desc >= 3;
103 | }
104 |
105 | bool file::open(array filename, unsigned char mode, unsigned char owner, unsigned char group, unsigned char user)
106 | {
107 | if (filename[-1] != '\0')
108 | filename.push_back('\0');
109 | return open(filename.data, mode, owner, group, user);
110 | }
111 |
112 | bool file::close()
113 | {
114 | if (desc >= 3)
115 | return ::close(desc) == 0;
116 | else
117 | return true;
118 | }
119 |
120 | intptr_t file::size()
121 | {
122 | intptr_t result = ::lseek(desc, 0, SEEK_END);
123 | ::lseek(desc, index, SEEK_SET);
124 | return result;
125 | }
126 |
127 | intptr_t file::set(intptr_t offset)
128 | {
129 | if (offset >= 0)
130 | index = ::lseek(desc, offset, SEEK_SET);
131 | else
132 | index = ::lseek(desc, offset, SEEK_END);
133 | return index;
134 | }
135 |
136 | intptr_t file::mov(intptr_t offset)
137 | {
138 | index = ::lseek(desc, offset, SEEK_CUR);
139 | return index;
140 | }
141 |
142 | intptr_t file::read(intptr_t length, char *str)
143 | {
144 | intptr_t result = ::read(desc, str, length);
145 | index += result;
146 | return result;
147 | }
148 |
149 | intptr_t file::read(intptr_t length, array &str)
150 | {
151 | str.reserve(length);
152 | str.count = ::read(desc, str.data, length);
153 | index += str.count;
154 | return str.count;
155 | }
156 |
157 | array file::read(intptr_t length)
158 | {
159 | array result;
160 | result.reserve(length);
161 | result.count = ::read(desc, result.data, length);
162 | index += result.count;
163 | return result;
164 | }
165 |
166 | intptr_t file::write(intptr_t length, const char *str)
167 | {
168 | intptr_t result = ::write(desc, str, length);
169 | index += result;
170 | return result;
171 | }
172 |
173 | intptr_t file::write(const array &str)
174 | {
175 | intptr_t result = ::write(desc, str.data, str.count);
176 | index += result;
177 | return result;
178 | }
179 |
180 | intptr_t file::read_to(const char *delimiters, array &str)
181 | {
182 | const char *cptr;
183 | do {
184 | char c;
185 | intptr_t count = ::read(desc, &c, 1);
186 | if (count == 0) {
187 | return str.count;
188 | }
189 | str.push_back(c);
190 | for (cptr = delimiters; *cptr and c != *cptr; ++cptr);
191 | } while (not *cptr);
192 | return str.count;
193 | }
194 |
195 | }
196 |
--------------------------------------------------------------------------------
/std/file.h:
--------------------------------------------------------------------------------
1 | /*
2 | * file.h
3 | *
4 | * Created on: Feb 5, 2014
5 | * Author: nbingham
6 | */
7 |
8 | #pragma once
9 |
10 | #include
11 | #include
12 |
13 | namespace core
14 | {
15 |
16 | struct file
17 | {
18 | file();
19 | file(int desc);
20 | file(const file ©);
21 | file(const char *filename, unsigned char mode = rw, unsigned char owner = rw, unsigned char group = r, unsigned char user = r);
22 | file(array filename, unsigned char mode = rw, unsigned char owner = rw, unsigned char group = r, unsigned char user = r);
23 | ~file();
24 |
25 | enum {
26 | r = 0x01, // read
27 | w = 0x02, // write
28 | x = 0x04, // execute
29 | rw = 0x03,
30 | rx = 0x05,
31 | wx = 0x06,
32 | rwx = 0x07,
33 | replace = 0x8, // replace with empty file
34 | exists = 0x10, // fail if file doesn't exist
35 | not_exists = 0x20 // fail if file exists
36 | };
37 |
38 | int desc;
39 | intptr_t index;
40 |
41 | operator bool() const;
42 |
43 | bool open(const char *filename, unsigned char mode = rw, unsigned char owner = rw, unsigned char group = r, unsigned char user = r);
44 | bool open(array, unsigned char mode = rw, unsigned char owner = rw, unsigned char group = r, unsigned char user = r);
45 | bool close();
46 |
47 | intptr_t size();
48 |
49 | intptr_t set(intptr_t offset);
50 | intptr_t mov(intptr_t offset);
51 |
52 | intptr_t read(intptr_t length, char *str);
53 | intptr_t read(intptr_t length, array &str);
54 | array read(intptr_t length);
55 |
56 | intptr_t write(intptr_t length, const char *str);
57 | intptr_t write(const array &str);
58 |
59 | intptr_t read_to(const char *delimiters, array &str);
60 | };
61 |
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/std/fill.h:
--------------------------------------------------------------------------------
1 | /*
2 | * fill.h
3 | *
4 | * Created on: May 29, 2016
5 | * Author: nbingham
6 | */
7 |
8 | #pragma once
9 |
10 | #include
11 |
12 | namespace core
13 | {
14 |
15 | template
16 | struct fill;
17 |
18 | template
19 | struct fill_const_iterator
20 | {
21 | protected:
22 | friend class fill;
23 |
24 | const fill *root;
25 | int index;
26 |
27 | fill_const_iterator(const fill *root, int index)
28 | {
29 | this->root = root;
30 | this->index = index;
31 | }
32 | public:
33 | typedef value_type type;
34 |
35 | fill_const_iterator()
36 | {
37 | this->root = NULL;
38 | this->index = 0;
39 | }
40 |
41 | ~fill_const_iterator()
42 | {
43 |
44 | }
45 |
46 | operator bool() const
47 | {
48 | return root != NULL && index >= 0 && index < root->count;
49 | }
50 |
51 | value_type operator*()
52 | {
53 | return root->value;
54 | }
55 |
56 | const value_type *operator->() const
57 | {
58 | return &root->value;
59 | }
60 |
61 | const value_type *ptr() const
62 | {
63 | return &root->value;
64 | }
65 |
66 | value_type get()
67 | {
68 | return root->value;
69 | }
70 |
71 | fill_const_iterator &ref()
72 | {
73 | return *this;
74 | }
75 |
76 | const fill_const_iterator &ref() const
77 | {
78 | return *this;
79 | }
80 |
81 | int idx() const
82 | {
83 | return index;
84 | }
85 |
86 | fill_const_iterator operator++(int)
87 | {
88 | fill_const_iterator result = *this;
89 | index++;
90 | return result;
91 | }
92 |
93 | fill_const_iterator operator--(int)
94 | {
95 | fill_const_iterator result = *this;
96 | index--;
97 | return result;
98 | }
99 |
100 | fill_const_iterator &operator++()
101 | {
102 | index++;
103 | return *this;
104 | }
105 |
106 | fill_const_iterator &operator--()
107 | {
108 | index--;
109 | return *this;
110 | }
111 |
112 | fill_const_iterator &operator+=(int n)
113 | {
114 | index += n;
115 | return *this;
116 | }
117 |
118 | fill_const_iterator &operator-=(int n)
119 | {
120 | index -= n;
121 | return *this;
122 | }
123 |
124 | fill_const_iterator operator+(int n) const
125 | {
126 | fill_const_iterator result;
127 | result.root = root;
128 | result.index = index + n;
129 | return result;
130 | }
131 |
132 | fill_const_iterator operator-(int n) const
133 | {
134 | fill_const_iterator result;
135 | result.root = root;
136 | result.index = index - n;
137 | return result;
138 | }
139 |
140 | bool operator==(fill_const_iterator i) const
141 | {
142 | return index == i.index;
143 | }
144 |
145 | bool operator!=(fill_const_iterator i) const
146 | {
147 | return index != i.index;
148 | }
149 |
150 | int operator-(fill_const_iterator i) const
151 | {
152 | return index - i.index;
153 | }
154 |
155 | fill sub(int length) const
156 | {
157 | if (length < 0)
158 | return fill(-length < index ? -length : index, root->value);
159 | else
160 | return fill(length < root->count - index ? length : root->count - index, root->value);
161 | }
162 |
163 | fill subcpy(int length) const
164 | {
165 | if (length < 0)
166 | return fill(-length < index ? -length : index, root->value);
167 | else
168 | return fill(length < root->count - index ? length : root->count - index, root->value);
169 | }
170 |
171 | fill sub() const
172 | {
173 | return fill(root->count - index, root->value);
174 | }
175 |
176 | fill subcpy() const
177 | {
178 | return fill(root->count - index, root->value);
179 | }
180 | };
181 |
182 | template
183 | struct fill : container, fill_const_iterator >
184 | {
185 | friend class fill_const_iterator;
186 |
187 | typedef container, fill_const_iterator > super;
188 | using typename super::iterator;
189 | using typename super::const_iterator;
190 | using typename super::type;
191 |
192 | int count;
193 | value_type value;
194 |
195 | fill(int count, value_type value)
196 | {
197 | this->count = count;
198 | this->value = value;
199 | }
200 |
201 | fill(const_iterator left, const_iterator right)
202 | {
203 | this->count = right - left;
204 | this->value = left.root->value;
205 | }
206 |
207 | virtual ~fill()
208 | {
209 |
210 | }
211 |
212 | // Utility
213 |
214 | int size() const
215 | {
216 | return count;
217 | }
218 |
219 | // Iterators
220 |
221 | const_iterator begin() const
222 | {
223 | return const_iterator(this, 0);
224 | }
225 |
226 | const_iterator end() const
227 | {
228 | return const_iterator(this, count);
229 | }
230 |
231 | const_iterator rbegin() const
232 | {
233 | return const_iterator(this, count-1);
234 | }
235 |
236 | const_iterator rend() const
237 | {
238 | return const_iterator(this, -1);
239 | }
240 |
241 | const_iterator at(int i) const
242 | {
243 | if (i < 0)
244 | i += size();
245 |
246 | return const_iterator(this, i);
247 | }
248 |
249 | // Accessors
250 |
251 | value_type front() const
252 | {
253 | return value;
254 | }
255 |
256 | value_type back() const
257 | {
258 | return value;
259 | }
260 |
261 | value_type get(int i) const
262 | {
263 | return value;
264 | }
265 |
266 | value_type operator[](int i) const
267 | {
268 | return value;
269 | }
270 |
271 | // Slicing
272 | fill sub(int start, int end) const
273 | {
274 | start = start < 0 ? count + start : start;
275 | end = end < 0 ? count + end : end;
276 | return fill(end-start, value);
277 | }
278 |
279 | fill sub(int start) const
280 | {
281 | start = start < 0 ? count + start : start;
282 | return fill(count-start, value);
283 | }
284 |
285 | fill sub() const
286 | {
287 | return fill(count, value);
288 | }
289 |
290 | fill subcpy(int start, int end) const
291 | {
292 | start = start < 0 ? count + start : start;
293 | end = end < 0 ? count + end : end;
294 | return fill(end-start, value);
295 | }
296 |
297 | fill subcpy(int start) const
298 | {
299 | start = start < 0 ? count + start : start;
300 | return fill(count-start, value);
301 | }
302 |
303 | fill subcpy() const
304 | {
305 | return fill(count, value);
306 | }
307 |
308 | template
309 | fill sample(container &c)
310 | {
311 | return fill(count, c.at(value));
312 | }
313 |
314 | template
315 | fill sample(const container &c)
316 | {
317 | return fill(count, c.at(value));
318 | }
319 |
320 | fill idx()
321 | {
322 | return fill(count, value.idx());
323 | }
324 |
325 | // Modifiers
326 |
327 | void swap(fill &root)
328 | {
329 | int tmp_count = count;
330 | value_type tmp_value = value;
331 | count = root.count;
332 | value = root.value;
333 | root.count = tmp_count;
334 | root.value = tmp_value;
335 | }
336 |
337 | fill &operator=(const fill &root)
338 | {
339 | count = root.count;
340 | value = root.value;
341 | return *this;
342 | }
343 | };
344 |
345 | template
346 | bool operator==(fill s1, fill s2)
347 | {
348 | return (s1.count == s2.count && s1.value == s2.value);
349 | }
350 |
351 | template
352 | bool operator!=(fill s1, fill s2)
353 | {
354 | return (s1.count != s2.count || s1.value != s2.value);
355 | }
356 |
357 | template
358 | bool operator<(fill s1, fill s2)
359 | {
360 | return (s1.value < s2.value || (s1.value == s2.value &&
361 | (s1.count < s2.count)));
362 | }
363 |
364 | template
365 | bool operator>(fill s1, fill s2)
366 | {
367 | return (s1.value > s2.value || (s1.value == s2.value &&
368 | (s1.count > s2.count)));
369 | }
370 |
371 | template
372 | bool operator<=(fill s1, fill s2)
373 | {
374 | return (s1.value < s2.value || (s1.value == s2.value &&
375 | (s1.count <= s2.count)));
376 | }
377 |
378 | template
379 | bool operator>=(fill s1, fill s2)
380 | {
381 | return (s1.value > s2.value || (s1.value == s2.value &&
382 | (s1.count >= s2.count)));
383 | }
384 |
385 | template
386 | fill fill_t(int count, value_type value)
387 | {
388 | return fill(count, value);
389 | }
390 |
391 | }
392 |
--------------------------------------------------------------------------------
/std/filter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * filter.h
3 | *
4 | * Created on: Oct 7, 2014
5 | * Author: nbingham
6 | */
7 |
8 | #pragma once
9 |
10 | #include
11 | #include
12 |
13 | namespace core
14 | {
15 |
16 | template
17 | array filter(container &c, const element &t)
18 | {
19 | array results;
20 | for (typename container::iterator i = c.begin(); i != c.end(); i++)
21 | if (*i == t)
22 | results.push_back(i);
23 |
24 | return results;
25 | }
26 |
27 | template