Recent Entries 10
- pattern minor 112d agoOpenGL 4.5 Core Buffer wrapperI recently wrote this OpenGL buffer wrapper which covers the 4.5 Core specification. I feel like the typed interface could be done better. Any feedback is greatly appreciated. ``` #ifndef MAKINA_CORE_RENDERING_BACKENDS_OPENGL_BUFFER_HPP_ #define MAKINA_CORE_RENDERING_BACKENDS_OPENGL_BUFFER_HPP_ #include #include #include #include #ifdef MAKINA_OPENGL_CUDA_INTEROP #include #include #endif #include namespace mak { namespace gl { template class MAKINA_EXPORT buffer { public: // 6.0 Buffer objects. buffer() { glCreateBuffers(1, &id_); } buffer(GLuint id) : id_(id), managed_(false) { } buffer(const buffer& that) : buffer() { that.is_immutable() ? set_data_immutable(that.size(), nullptr, that.storage_flags()) : set_data (that.size(), nullptr, that.usage ()); copy_sub_data(that, 0, 0, size()); } buffer( buffer&& temp) = default; ~buffer() { if(managed_) glDeleteBuffers(1, &id_); } buffer& operator=(const buffer& that) { that.is_immutable() ? set_data_immutable(that.size(), nullptr, that.storage_flags()) : set_data (that.size(), nullptr, that.usage ()); copy_sub_data(that, 0, 0, size()); return *this; } buffer& operator=( buffer&& temp) = default; // 6.1 Create and bind buffer objects. void bind () const { glBindBuffer(target, id_); } static void unbind () { glBindBuffer(target, 0); } template::type> void bind_range(GLuint index, GLintptr offset, GLsizeiptr size) const { glBindBufferRange(target, index, id_, offset, size); } template::type> void bind_base (GLuint index) const { glBindBufferBase(target, index, id_); } // 6.2 Create / modify buffer object data (bindless). void set_data_immutable (GLsizeiptr size, const void* data = nullptr, GLbitfield storage_flags = GL_DYNAMIC_STORAGE_BIT) { glNamedBufferStorage(id_, size, data, stora
- pattern minor 112d agoSimple C++ wrapper over libYAMLFor a personal project, I need to parse YAML file. I chose to use C-based libYAML instead of yaml-cpp, because: - I try to keep my dependencies to what's commonly installed and Debian statistics show 45% installs already have libYAML, vs 0.5% for yaml-cpp. - I don't need variant node types, as the config parser that uses this wrapper builds the final datastructures directly using a state machine. I wrote this lightweight wrapper around the library. The wrapper aims at encapsulating all the details of the C library, throwing exceptions when errors arise and leaking no resources in the process. In addition, its header must not have any libYAML-related stuff in it, so I can change the underlying implementation later should I want to. Provided API is an inheritable class that converts parsing events into virtual method calls, a la hierarchical visitor pattern, but without conditional navigation. Here comes the API (YAMLParser.h): ``` #ifndef YAML_PARSER_H #define YAML_PARSER_H #include #include #include #include class YAMLParser { public: class ParseError : public std::exception { public: ParseError(const std::string & what, size_t line, size_t col); ParseError(const std::string & what, size_t line, size_t col, const std::string & context, size_t ctx_line); const char *what() const noexcept override { return m_what.c_str(); } protected: std::string m_what; }; public: virtual ~YAMLParser() {} virtual void parse(std::istream & stream); protected: virtual void streamStart() = 0; virtual void streamEnd() = 0; virtual void documentStart() = 0; virtual void documentEnd() = 0; virtual void sequenceStart(const std::string & tag, const std::string & anchor) = 0; virtual void sequenceEnd() = 0; virtual void mappingStart(const std::string & tag, const std::string & anchor) = 0; virtual void
- pattern minor 112d agoLinux/Mac hashing SHA-1To do password exchange on the SQL server I need to use SHA-1 to generate a hash (no plain password exchange). This is done differently on Linux/Mac so I abstracted it slightly. ThorCryptWrapper.h ``` #ifndef THORS_ANVIL_MYSQL_DETAILS_THOR_CRYPTO_WRAPPER_H #define THORS_ANVIL_MYSQL_DETAILS_THOR_CRYPTO_WRAPPER_H #ifdef __APPLE__ #define COMMON_DIGEST_FOR_OPENSSL #include #define THOR_SHA1(data, len, dst) CC_SHA1(data, len, dst) #else #include #define THOR_SHA1(data, len, dst) SHA1(data, len, dst) #endif namespace ThorsAnvil { namespace MySQL { typedef unsigned char ThorSHADigestStore[SHA_DIGEST_LENGTH]; inline void thorSHA1(ThorSHADigestStore& dest, ThorSHADigestStore& src) { THOR_SHA1(src, SHA_DIGEST_LENGTH, dest); } inline void thorSHA1(ThorSHADigestStore& dest, std::string const& src) { THOR_SHA1(reinterpret_cast(&src[0]), src.length(), dest); } } } #endif ```
- pattern minor 112d agoWrapping libusb library in C++I want to use libusb library in my C++ application. I have created classes which wraps libusb functions. You can see that libusb API is split into 8 sections: http://libusb.sourceforge.net/api-1.0/modules.html For me the most necessary sections are: - Device handling and enumeration - Synchronous device I/O - Library initialization/deinitialization - Miscellaneous I have also split "Device handling and enumeration" section to "Device Info" and "Device Handling". To use libusb functions it is need to initialize libusb library (call `libusb_init` function), store somewhere its initialized `libusb_context *`, next - call functions (`libusb_get_device_list`, `libusb_open_device_with_vid_pid`) to obtain and store somewhere "device pointer" (in libusb known as `libusb_device*` or `libusb_device_handle*`), and then finally call functions for obtaining device info or performing some USB transfers (for instance: `libusb_set_configuration`, `libusb_get_bus_number`). Note, that these functions require "device pointer": `libusb_device_handle*` or `libusb_device_*` as first parameter. You can see whole process of initializing/opening/controlling device here: http://www.dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/ Currenlty my solution consists of following classes: - LibusbInfoAPI: provides functions to obtain device info - LibusbControlAPI: provides functions to control device - LibusbHandlingAPI: creates devices, destroys, manages them, and stores `libusb_context *`, `libusb_device *`, `libusb_device_handle *` LibusbControlAPI header: ``` class LibusbControlAPI { public: int GetConfiguration(DevHandlePtr deviceHandle, int& activeConfiguration); int SetConfiguration(DevHandlePtr deviceHandle, int targetConfiguration); int ClaimInterface(DevHandlePtr deviceHandle, int interfaceNumber); int ReleaseInterface(DevHandlePtr deviceHandle, int interfaceNumber); int SetInterfaceAlternateSetting(DevHandlePtr deviceHandle, int int
- pattern minor 112d agoEnum wrapped in a structI was thinking about how I was going to use some enums I made, how I was going to make sure they had valid values and how to call the class which would contain the necessary extensions methods. And then I thought: why not wrap the enum in a struct. I wrote up a little example code and it looks like this (ignore the fact that it's a very common day enum, I needed something as an example): ``` public struct Day { private enum DayE { Monday = 1, Tuesday, Wednesday, Thursday, Friday } private readonly DayE value; public static Day Monday { get { return new Day( DayE.Monday ); } } public static Day Tuesday { get { return new Day( DayE.Tuesday ); } } public static Day Wednesday { get { return new Day( DayE.Wednesday ); } } public static Day Thursday { get { return new Day( DayE.Thursday ); } } public static Day Friday { get { return new Day( DayE.Friday ); } } private Day( DayE value ) { this.value = value; } public override string ToString() { switch( value ) { case DayE.Monday: return "mo"; case DayE.Tuesday: return "tu"; case DayE.Wednesday: return "we"; case DayE.Thursday: return "th"; case DayE.Friday: return "fr"; default: throw new InvalidOperationException( "Can't convert 0 value" ); } } } ``` Some advantages of this approach I could think of: - Allows you to limit the possible values, only the ones you construct using the private constructor can be made. (Of course, the 0 value can always be constructed using `default(Day)` or `new Day()`.) This means you only have to test if the value is not 0 to make sure it's valid. If 0 is a valid value, you don't have to test for validity. - No need for an helper class for the extension methods, you can just put them in th
- pattern minor 112d agoC++ Wrapper for cURL: Multithreading and serializing asynchronous opsI did this library to help me from one of my projects and decided to publish it on GitHub hoping people might find it useful, convenient and easy to use in their projects too. It's a header-only library. The library design is inspired by some popular Java code conventions, like naming of classes and the popular usage of chaining call of methods. As of now, there are only two HTTP methods I made from `CppUrl` class, which are the `GET` and `POST` with the two corresponding "fetch" functions to execute it either on main thread, or on another thread namely: `execute()` (synchronous) and `async()` (asynchronous). I haven't really tested this on some complicated scenarios so if I may ask, what could probably go wrong here? I could smell some data corruption or some deadlocks when this has been used on an intensive and complicated task, but it might just me. I want the user of this library to type as less as possible of code. So, what do you think of using `std::map` as a function parameter for passing files on a `POST` method? Is it suitable (considering the context)? If not, can you suggest another constructive and simpler way? ``` class CppUrl { using ResponseCallback = std::function; public: class MissingHttpMethodException : std::exception { public: std::string what() { return "No HTTP method used"; } }; CppUrl() : task(nullptr) { if (curlInstanceCount == 0) { curl_global_init(CURL_GLOBAL_ALL); } handle = curl_easy_init(); if (handle) { curlInstanceCount++; } } CppUrl(const CppUrl&) = delete; CppUrl& operator= (CppUrl const&); ~CppUrl() { curlInstanceCount--; curl_easy_cleanup(handle); cleanTask(); handle = nullptr; // busy = false; }); return *this; } /** * Perform a request with a POST method * @param const std::string &url: URL to be requested * @param s
- pattern minor 112d agoRandom generator extension for VSCodeBackground A VSCode extension that uses Chance.JS to generate random data types. Concerns - My main concern is that there are 4 levels of function references that feels like a hack. From registerCommand → insertFunc* → randomFunc* → processSelection. - If the code is sensible TypeScript/JavaScript The Code ``` export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.commands.registerCommand('randomeverything.int', insertRandomInt)); context.subscriptions.push(vscode.commands.registerCommand('randomeverything.letters', insertRandomLetters)); context.subscriptions.push(vscode.commands.registerCommand('randomeverything.lettersAndNumbers', insertRandomLettersAndNumbers)); context.subscriptions.push(vscode.commands.registerCommand('randomeverything.iPv4Address', insertRandomIPv4Address)); context.subscriptions.push(vscode.commands.registerCommand('randomeverything.iPV6Address', insertRandomIPV6Address)); /* More commands... */ } function insertRandomInt(): void { var max:number; var min:number; Window.showInputBox({prompt: "Please enter [MIN-MAX]", value:"1-100"}).then( function(txt){ if(txt){ var args = txt.split("-"); min = Number.parseInt(args[0]); max = Number.parseInt(args[1]); if(args.length != 2 || isNaN(min) || isNaN(max)) { Window.showErrorMessage("Invalid format."); return; } processSelection(randomIntString, [min, max]); } }); } function insertRandomLetters(): void { processSelection(randomLetters, []); } function insertRandomLettersAndNumbers(): void { processSelection(randomLettersAndNumbers, []); } function insertRandomIPv4Address(): void { processSelection(randomIP, ['ipv4']); } function insertRandomIPV6Address(): void { processSelection(randomIP, ['ipv6']); } /* More
- pattern minor 112d agoC++ Dirent.h "Wrapper"I do not want to call this a wrapper, but no other name comes to mind right now, so I'll use it incorrectly for the rest of the question - It's just a class that adds C++ functions to `dirent.h` but it's very specific to my use case. All of the code works well, but I've never worked with the `dirent.h` library and jumping right into a C++ wrapper is something, so I'm really insecure about it's performance and memory usage in practical scenarios. ~But, of course please also judge the readability - I want to know if I should add comments or if my naming scheme and layout is self explanatory. Quick Description I'm working on C++ based file manager that needs functions that return vectors of whole directories, of course, that it can display it in one loop. It will also need some more info (metadata I guess), like it's type so it can do all the fancy color syntax. Here is the final version so far (with some debug code): inode.h ``` #ifndef INODECLASS #define INODECLASS #include #include #include #include #include class Inode { public: struct InodeMeta { std::string name; std::string path; unsigned char type; }; private: std::string pwd_path_; std::vector buffer_; public: Inode(const std::string &); ~Inode(); void ClearBuffer(); bool ReloadBuffer(const std::string &); std::vector DumpBuffer(const std::string &); }; #endif ``` inode.cc ``` #include "inode.h" Inode::Inode(const std::string &arg_path = ".") { if ( !ReloadBuffer(arg_path) ) ClearBuffer(); } Inode::~Inode() { ClearBuffer(); } void Inode::ClearBuffer() { for (auto &item : buffer_) delete item; buffer_.clear(); } bool Inode::ReloadBuffer(const std::string &arg_path = "") { if (arg_path.length() != 0) pwd_path_ = arg_path; DIR *dirstream; dirent *diritem; ClearBuffer(); if ( (dirstream = opendir(pwd_path_.c_str())) != NULL ) { while ( (diritem = readdir(dirstream)) != NULL ) { if ( strcmp(diritem->d_name, ".") != 0
- pattern minor 112d agoShort header file for safe CLI input handling in CProper input handling is a pain in the butt in C, so as part of a project of mine, this header is used to handle reoccurring command line input tasks such as input loops, reading lines and tokenizing strings in a safe and robust way. Would be great if some C veterans could share their opinion about potential flaws. You can check the updated version here. ``` #include #include #include #include #include #include #define TRUE 1 /* * Contains functions for input related operations */ /// Wraps fgets to handle errors and safely replaces the newline /// \param line - The buffer which holds the string /// \param length - The size of the buffer void get_line(char *line, const int length) { if (fgets(line, length, stdin)) { char *newline = strchr(line, '\n'); if (newline) { *newline = '\0'; } } else { fprintf(stderr, "Could not read line from stdin!"); exit(EXIT_FAILURE); } } /// Tokenizes a line into EXACTLY number_of_tokens tokens using the " " delimiter. Excess tokens are omitted. This /// function will alter the line parameter, so be sure to pass a copy if you want to preserve it. /// \param line - The string to be processed /// \param tokens - The buffer holding the tokens /// \return EXIT_FAILURE if the supplied line does not contain enough tokens. int get_tokens(char *line, char **tokens, const size_t number_of_tokens) { for (size_t i = 0; i INT_MAX) { fprintf(stderr, "%ld is greater than INT_MAX\n", value); } else if (value SIZE_MAX) { fprintf(stderr, "%ld is greater than SIZE_MAX\n", value); } else { *size = (size_t) value; return EXIT_SUCCESS; } return EXIT_FAILURE; } /// Prompts for an integer value once /// \param value - A pointer to the integer /// \return EXIT_FAILURE if the supplied input doesn't match int get_integer(int *value) { char buffer[BUFSIZ]; get_line(buffer, BUFSIZ); char **tokens = malloc(sizeof(char*))
- pattern minor 112d agoPython 'wrapper' around `dig` for easier TSIG signing of queriesI wrote this Python script as a utility script for me. It's something that could be achieved in a simple shell script or alias, but it wasn't 'verbose' enough for me in that format, or customizable. This script, basically, is just designed to take and process whether a specified DNS TSIG keyfile (necessary for 'signed' requests to DNS servers for different types of requests that need authentication/authorization to be processed) exists, and then calls out to `dig`, specifying the relevant `-k` filepath (either a filename, in which case it checks current directory, a full file path, or if no `-k` is provided then a hard-coded default path). Basically, looking for feedback on how I could improve this. Any and all feedback is appreciated. (Just don't crucify me for making a more complicated Python script to do something a simple shell alias or script could do, please.) dig+key.py: ``` #!/usr/bin/env python import argparse import os import subprocess DEV_DEBUG_MODE = False CURRENT_WORKING_DIR = os.getcwd() + "/" DEFAULT_TSIG_MD5_KEYFILE = "/path/to/tsig/keyfile" # noinspection PyClassHasNoInit class _Errors: class KeyfilePathIssue(IOError): """Error that triggers only when an issue occurred with regards to the specified keyfile""" def __init__(self, custommsg): if custommsg: self.msg = custommsg else: self.msg = self.message def __str__(self): return self.msg class NoDigBinaryFound(IOError): """Error that triggers when we couldn't find the 'dig' binary""" def __init__(self, custommsg): if custommsg: self.msg = custommsg else: self.msg = self.message def __str__(self): return self.msg def _check_if_dig_exists(): try: for p in os.environ["PATH"].split(os.pathsep): if DEV_DEBUG_MODE: print "'dig' in %s: %s" % (p, os.path.exists