001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
427:
Min/Max










































































































































































































































































































































































































































/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(OMNI_STACK_BUFFER_HPP)
#define OMNI_STACK_BUFFER_HPP 1
#include <omni/defs/class_macros.hpp>
#include <omni/string/util.hpp>
#include <cstdarg>

namespace omni {
    template < typename T, uint16_t SZ >
    class stack_buffer
    {
        public:
            typedef const T* const_iterator;
            typedef T* iterator;
            typedef T value_type;

            stack_buffer() :
                OMNI_CTOR_FW(omni::stack_buffer)
                m_data()
            {
                if (SZ == 0) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::memset(this->m_data, 0, SZ);
            }

            stack_buffer(const T (&data)[SZ]) :
                OMNI_CTOR_FW(omni::stack_buffer)
                m_data()
            {
                if (SZ == 0) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::memcpy(this->m_data, data, SZ);
            }
            
            stack_buffer(T val1, ...) :
                OMNI_CTOR_FW(omni::stack_buffer)
                m_data()
            {
                if (SZ == 0) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::va_list args;
                va_start(args, val1);
                this->m_data[0] = val1;
                for (std::size_t i = 1; i < SZ; ++i) {
                    this->m_data[i] = static_cast<T>(va_arg(args, T));
                }
                va_end(args);
            }

            template < uint16_t OTHER_SZ >
            stack_buffer(const T (&data)[OTHER_SZ]) :
                OMNI_CTOR_FW(omni::stack_buffer)
                m_data()
            {
                if ((OTHER_SZ == 0) || (OTHER_SZ > SZ)) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::memset(this->m_data, 0, SZ);
                std::memcpy(this->m_data, data, OTHER_SZ);
            }
            
            stack_buffer(const stack_buffer& cp) :
                OMNI_CTOR_FW(omni::stack_buffer)
                m_data()
            {
                if (SZ == 0) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::memcpy(this->m_data, cp.m_data, SZ);
            }

            ~stack_buffer()
            {
                OMNI_TRY_FW
                std::memset(this->m_data, 0, SZ);
                OMNI_DTOR_FW
                OMNI_CATCH_FW
                OMNI_D5_FW("destroyed");
            }

            T& at(uint16_t index)
            {
                if (index > SZ) {
                    OMNI_ERRV_RETV_FW(OMNI_INDEX_OOR_STR, index, omni::exceptions::index_out_of_range(index), T())
                }
                return this->m_data[index];
            }

            T* back()
            {
                return this->m_data + SZ;
            }

            iterator begin()
            {
                return this->m_data;
            }

            const_iterator begin() const
            {
                return const_cast<const T*>(&this->m_data[0]);
            }

            std::size_t capacity() const
            {
                return SZ;
            }

            T* data()
            {
                return this->m_data;
            }

            const T *const data() const
            {
                return this->m_data;
            }
            
            iterator end()
            {
                return this->m_data + SZ;
            }

            const_iterator end() const
            {
                return this->m_data + SZ;
            }

            T* front()
            {
                return this->m_data;
            }

            void fill(T value)
            {
                for (std::size_t i = 0; i < SZ; ++i) {
                    this->m_data[i] = value;
                }
            }

            std::size_t memory_size() const
            {
                return SZ * sizeof(T);
            }

            void swap(stack_buffer& other)
            {
                if (this != &other) {
                    std::swap(this->m_data, other.m_data);
                }
            }

            void swap(T (&data)[SZ])
            {
                if (&this->m_data != &data) {
                    std::swap(this->m_data, data);
                }
            }

            std::size_t size() const
            {
                return SZ;
            }

            void zeroize()
            {
                std::memset(this->m_data, 0, sizeof(T)*SZ);
            }

            omni::string_t to_string_t() const
            {
                omni::sstream_t s;
                s << this->m_data;
                return s.str();
            }

            std::string to_string() const
            {
                std::stringstream s;
                s << this->m_data;
                return s.str();
            }

            std::wstring to_wstring() const
            {
                std::wstringstream s;
                s << this->m_data;
                return s.str();
            }        

            stack_buffer& operator=(const stack_buffer& other)
            {
                if (this != &other) {
                    OMNI_ASSIGN_FW(other)
                    std::memcpy(this->m_data, other.m_data, SZ);
                }
                return *this;
            }

            stack_buffer& operator=(const T (&data)[SZ])
            {
                if (&this->m_data != &data) {
                    std::memcpy(this->m_data, data, SZ);
                }
                return *this;
            }

            template < uint16_t OTHER_SZ >
            stack_buffer& operator=(const T (&data)[OTHER_SZ])
            {
                if ((OTHER_SZ == 0) || (OTHER_SZ > SZ)) {
                    OMNI_ERR_FW(OMNI_INDEX_OOR_STR, omni::exceptions::index_out_of_range())
                }
                std::memset(this->m_data, 0, SZ);
                std::memcpy(this->m_data, data, OTHER_SZ);
                return *this;
            }

            bool operator==(const stack_buffer& other) const
            {
                if (this != &other) {
                    return (std::memcmp(this->m_data, other.m_data, SZ) == 0);
                }
                return true;
            }

            bool operator==(const T (&data)[SZ]) const
            {
                return (std::memcmp(this->m_data, data, SZ) == 0);
            }

            inline bool operator!=(const stack_buffer& other) const
            {
                return !(*this == other);
            }

            inline bool operator!=(const T (&data)[SZ]) const
            {
                return !(*this == data);
            }

            bool operator<(const stack_buffer& other) const
            {
                if (this == &other) { return false; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] >= other.m_data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator<(const T (&data)[SZ]) const
            {
                if (&this->m_data == &data) { return false; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] >= data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator>(const stack_buffer& other) const
            {
                if (this == &other) { return false; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] <= other.m_data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator>(const T (&data)[SZ]) const
            {
                if (&this->m_data == &data) { return false; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] <= data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator<=(const stack_buffer& other) const
            {
                if (this == &other) { return true; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] > other.m_data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator<=(const T (&data)[SZ]) const
            {
                if (&this->m_data == &data) { return true; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] > data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator>=(const stack_buffer& other) const
            {
                if (this == &other) { return true; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] < other.m_data[i]) {
                        return false;
                    }
                }
                return true;
            }

            bool operator>=(const T (&data)[SZ]) const
            {
                if (&this->m_data == &data) { return true; }
                for (uint16_t i = 0; i < SZ; ++i) {
                    if (this->m_data[i] < data[i]) {
                        return false;
                    }
                }
                return true;
            }

            operator std::string() const
            {
                return this->to_string();
            }

            operator std::wstring() const
            {
                return this->to_wstring();
            }

            template < template < class, class > class std_seq_t, typename std_allocator_t >
            operator std_seq_t < T, std_allocator_t >() const
            {
                return std_seq_t < T, std_allocator_t >(this->begin(), this->end());
            }

            template < template < class, class > class std_seq_t >
            operator std_seq_t < T, std::allocator<T> >() const
            {
                return std_seq_t < T, std::allocator<T> >(this->begin(), this->end());
            }

            T operator[](std::size_t index) const
            {
                return this->m_data[index];
            }

            T& operator[](std::size_t index)
            {
                return this->m_data[index];
            }

            operator const T *const() const
            {
                return this->m_data;
            }

            operator T *const()
            {
                return this->m_data;
            }

            OMNI_MEMBERS_FW(omni::stack_buffer<T, SZ>) // disposing,name,type(),hash()

            OMNI_OSTREAM_FW(omni::stack_buffer<T, SZ>)

            static std::size_t max_size()
            {
                return std::numeric_limits<uint16_t>::max();
            }

        private:
            T m_data[SZ];
    };
}

namespace std {
    template < typename T, uint16_t SZ >
    inline void swap(omni::stack_buffer<T, SZ>& o1, omni::stack_buffer<T, SZ>& o2)
    {
        o1.swap(o2);
    }

    template < typename T, uint16_t SZ >
    inline void swap(omni::stack_buffer<T, SZ>& o1, T (&data)[SZ])
    {
        o1.swap(data);
    }

    template < typename T, uint16_t SZ >
    inline void swap(T (&data)[SZ], omni::stack_buffer<T, SZ>& o1)
    {
        o1.swap(data);
    }
}

#endif // OMNI_STACK_BUFFER_HPP