Development reference
c++11 Model View Controller skeleton |
---|
Three objects contain most of the functionality. In addition, utilities.* provides crosscut features like global logging.
CONTROLLER header #include "HTDJInterface.h" #include "HTDJLocalModel.h" #include "HTDJRemoteModel.h" class HTDJController HTDJController( HTDJLocalModel& local, HTDJRemoteModel& remote, HTDJInterface& hinterface |
VIEW header
class HTDJController; class HTDJInterface { HTDJInterface( HTDJController* p_controller) |
MODEL header
class HTDJLocalModel; // Note that we want GLOBAL ACCESS to a GENERIC local model. extern HTDJLocalModel* g_p_local; class HTDJLocalModel { HTDJLocalModel(); |
c++11 containers | |
---|---|
sorted_vector | use when doing lots of unsorted insertions and maintaining constant sort would be expensive; vector is good for a big pile of things that only occasionally needs a sorted lookup |
map | sorted binary search tree; always sorted by key; you can walk through in sorted order (choose unordered if not needed!) |
multimap | same as map but allows dupe keys (not as common) |
unordered_map | hashmap; always sorted by key; additional bucket required for hash collisions; no defined order when walking through |
unordered_multimap | same as map but allows dupe keys; dupes are obviously in the same bucket, and you can walk just the dupes if needed |
set multiset unordered_set unordered_multiset |
sets are just like maps, except the key is embedded in the object, nice for encapsulation. Items must be const (!) since they are the key - sounds bad, but this is mitigated by the mutable keyword. |
set (etc.) of pointers | sets of pointers are the pinnacle of object stores The entire object can be dereferenced and accessed then without const issues. map vs key redux use a key in the set, derive a class from it with the contents + small key + encapsulation - requires mutable to solve the const problem use a key in the set, key includes a mutable object + encapsulation - weird bc everything uses a const object but we have const functions like save() that change the mutable subobject use a map + small key - no encapsulation, have to deal with a pair instead of an object can we just put a ref to key in the value? sure why not - err, bc we don't have access to it + solves const problem bc value is totally mutable by design + we can have multiple keys - and the value can have multiple refs to them + simpler equal and hash functions map: create an object with internal key(s) create map index(es) with duplicate key values outside the object - dupe data is the downside use set(s) with one static key for find(): create an object with internal key(s) create set index(es) with specific hash/equals functor(s) when finding, use one static key object (even across indexes!) so there isn't a big construction each time; just set the necessary key values that proves difficult when dealing with member vars that are references but to solve it, just set up a structure of dummy static key objects that use each other; then provide a function to setKey(Object& keyref) { keyref_ = keyref; } nope, can't reassign refs the solution: use pointers not references yes that's right just do it apparently there was a reason i was anti-reference for all those years two reasons to use pointers: dynamically allocated reassignment required there ya go. simple. get it done. when accessing find results from the set, use a const_cast on the object! WARNING: a separate base class with the key sounds good... but fails when you have more than one index on the object. just use a static key object for them all! |
c++11 example for large groups of objects with frequent crud AND search |
---|
Best solution is an unordered set of pointers:
typedef boost::unordered_set<MajorObject*> MajorObjects; |
c++11 example for large groups of objects with infrequent crud and frequent search |
---|
Best solution is a vector of pointers sorted on demand (sorted_vector):
TODO |
c++11 example to associate two complex objects (one the map key, one the map value) |
---|
Use unordered_map with a custom object as key. You must add hash and equals functions. Boost makes it easy:
static bool operator==(MyKeyObject const& m1, MyKeyObject const& m2) { return m1.id_0 == m2.id_0 && m1.id_1 == m2.id_1; } static std::size_t hash_value(MyKeyObject const& mko) { std::size_t seed = 0; boost::hash_combine(seed, mko.id_0); boost::hash_combine(seed, mko.id_1); return seed; } typedef boost::unordered_map<MyKeyObject, MyValueObject*> MyMap; Note that you can extend this to use a pointer to a key object, whoop. |
c++11 example for multiple unordered_set indexes into one group of objects |
---|
Objects will be dynamically created. One set should include them all and be responsible for memory allocation cleanup:
TODO |
c++11 example for set with specific sorting |
---|
Use set with a specific sort functor. You can create as many of these indexes as you want!
struct customers_set_sort_functor { bool operator()(const MyObject* l, const MyObject* r) const { // the id is the key return l->id_ < r->id_; } }; typedef set<MyObject*,myobject_sort_by_id_functor> MyObjectsById; |
c++11 loop through vector to erase some items |
---|
Note that other containers' iterators may not be invalidated so you can just erase() as needed...
For vectors, you have to play with iterators to get it right - watch for proper ++ pre/postfix! for (it = numbers.begin(); it != numbers.end(); ) // NOTE we increment below, only if we don't erase { if (*it.no_good()) { numbers.erase(it++); // NOTE that we ERASE THEN INCREMENT here. } else { ++it; } } I thought I had always looped backwards to do this, I *think* that's ok too, but I don't see it used in my code, I think I'll avoid. :-) |
c++11 range based for loop, jacked with boost index if needed |
---|
No iterator usage at all. Nice at times, not enough at others. Make SURE to always use a reference or you will be working on a COPY. Make it const if you aren't changing the object.
for (auto& mc : my_container) mc.setString("default"); for (const auto& cmc : my_container) cout << cmc.asString(); boost index can give you the index if you need it, sweet: #include <boost/range/adaptor/indexed.hpp> ... for (const auto &element: boost::adaptors::index(mah_container)) cout << element.value() << element.index(); |
c++11 for loop using lambda |
---|
This C++11 for loop is clean and elegant and a perfect way to check if your compiler is ready for c++11:
vector<int> v; for_each( v.begin(), v.end(), [] (int val) { cout << val; } ); This is using a lambda function, we should switch from iterators and functors to those - but not quite yet, since we're writing cross-platform code. Do not touch this until we can be sure that all platforms provide compatible C++11 handling. |
c++11 integer types |
---|
I really like the "fast" C++11 types, that give best performance for a guaranteed minimum bit width.
Use them when you know a variable will not exceed the maximum value of that bit width, but does not have to be a precise bit width in memory or elsewhere. Pick specific-width fields whenever data is shared with other processes and components and you want a guarantee of its bit width. And when using pointer size and array indices you should use types defined for those specific situations. FAST types: int_fast8_t int_fast16_t fastest signed integer type with width of int_fast32_t at least 8, 16, 32 and 64 bits respectively int_fast64_t uint_fast8_t uint_fast16_t fastest unsigned integer type with width of uint_fast32_t at least 8, 16, 32 and 64 bits respectively uint_fast64_t SMALL types: int_least8_t int_least16_t smallest signed integer type with width of int_least32_t at least 8, 16, 32 and 64 bits respectively int_least64_t uint_least8_t uint_least16_t smallest unsigned integer type with width of uint_least32_t at least 8, 16, 32 and 64 bits respectively uint_least64_t EXACT types: int8_t signed integer type with width of int16_t exactly 8, 16, 32 and 64 bits respectively int32_t with no padding bits and using 2's complement for negative values int64_t (provided only if the implementation directly supports the type) uint8_t unsigned integer type with width of uint16_t exactly 8, 16, 32 and 64 bits respectively uint32_t (provided only if the implementation directly supports the type) uint64_t SPECIFIC-USE types: intptr_t integer type capable of holding a pointer uintptr_t unsigned integer type capable of holding a pointer size_t unsigned integer type capable of holding an array index (same size as uintptr_t) |
C++11 scoped enumeration |
---|
C++11 has scoped enumeration, which lets you specify the SPECIFIC VARIABLE TYPE for the enum. Perfect, let's use uint_fast32_t.
enum class STRING_PREF_INDEX int_fast32_t: { ... }; Unfortunately, gcc gives me a scary warning, and stuff fails. For some reason, it does not know about the provided type, although it is definitely defined. Revisit this later if you have time. warning: elaborated-type-specifier for a scoped enum must not use the ‘class’ keyword Old skool is still cool: typedef enum { // assert( SP_COUNT == 2 ); SP_FIRST = 0 , SP_SOME_PREF = SP_FIRST , SP_ANOTHA , SP_COUNT } STRING_PREF_INDEX; |
c++ in-memory storage of "major" objects |
---|
OBSERVATION ONE Consider An Important Qt Design: QObjects cannot normally be copied their copy constructors and assignment operators are private why? A Qt Object... might have a unique QObject::objectName(). If we copy a Qt Object, what name should we give the copy? has a location in an object hierarchy. If we copy a Qt Object, where should the copy be located? can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy? can have new properties added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original? in other words, a QObject is a pretty serious object that has the ability to be tied to other objects and resources in ways that make copying dangerous isn't this true of all serious objects? pretty much OBSERVATION TWO if you have a vector of objects, you often want to track them individually outside the vector if you use a vector of pointers, you can move the object around much more cheaply, and not worry about costly large vector reallocations a vector of objects (not pointers) only makes sense if the number of objects is initially known and does not change over time OBSERVATION THREE STL vectors can store your pointers, iterate thru them, etc. for a vector of any substantial size, you want to keep objects sorted so you can find them quickly that's what my sorted_vector class is for; it simply bolts vector together with sort calls and a b_sorted status following STL practices, to get sorting, you have to provide operator< for whatever is in your vector BUT... you are not allowed to do operator<(const MyObjectPtr* right) because it would require a reference to a pointer which is not allowed BUT... you can provide a FUNCTOR to do the job, then provide it when sorting/searching a functor is basically a structure with a bool operator()(const MyObjectPtr* left, const MyObjectPtr* right) OBSERVATION FOUR unordered_set works even better when combining frequent CRUD with frequent lookups SUMMARY Dealing with tons of objects is par for the course in any significant app. Finding a needle in the haystack of those objects is also standard fare. Having multiple indices into those objects is also essential. Using unordered_set with object pointers and is very powerful. |
c++ stl reverse iterator skeleton |
---|
From SGI...
reverse_iterator rfirst(V.end()); reverse_iterator rlast(V.begin()); while (rfirst != rlast) { cout << *rfirst << endl; ... rfirst++; } |
c++ stl reading a binary file into a string |
---|
std::ifstream in("my.zip",std::ios::binary); if (!in) { std::cout << "problem with file open" << std::endl; return 0; } in.seekg(0,std::ios::end); unsigned long length = in.tellg(); in.seekg(0,std::ios::beg); string str(length,0); std::copy( std::istreambuf_iterator< char >(in) , std::istreambuf_iterator< char >() , str.begin() ); For more, see c++ stl reading a binary file |
C/C++ best-in-class tool selection |
---|
I need to have easy setup of debug-level tool support for portable C++11 code. And I need to decide and stick to it to be efficient.
|
c/c++ gdb debugging |
---|
(gdb) help break Set breakpoint at specified line or function. Argument may be line number, function name, or "*" and an address. If line number is specified, break at start of code for that line. If function is specified, break at start of code for that function. If an address is specified, break at that exact address. With no arg, uses current execution address of selected stack frame. This is useful for breaking on return to a stack frame. Multiple breakpoints at one place are permitted, and useful if conditional. Do "help breakpoints" for info on other commands dealing with breakpoints. |
ddd gives you a front end. I need to use it more, compare to other options |
C - Create a portable command line C project in Visual Studio |
---|
Visual Studio: File -> New -> project Visual C++ -> Win32 -> Win32 Console Application name: oms_with_emap next -> click OFF precompiled header checkbox (even tho it didn't seem to respect it) you'll get a _tmain(..., TCHAR*...) change it to main(..., char*...) change the project to explicitly say "Not using precompiled header" remove the f'in stdafx.h recompile! should be clean vs will recognize C files and compile accordingly |
c++ Create a portable C++ project in Visual Studio |
---|
It's probably best to create a project_name.cpp file with your main() function. int main( int argc, char * argv[] ) { return 0; } Then in Visual Studio... File->New->Project from existing code C++ (then use mostly defaults on this page, once you provide file location and project name) Project file location: <base>\project_name Project name: project_name [x] Add files from these folders Add subs [x] <base>\project_name NEXT Use Visual Studio Console application project No ATL, MFC, CLR NEXT NEXT FINISH Then add boost include and lib paths, required preprocessor definitions, etc. Example (if you built 1.53 in place with Visual Studio): INCLUDE: C:\Software Development\boost_1_53_0 LIB: C:\Software Development\boost_1_53_0\stage\lib |
boost release and debug build for linux |
---|
# download latest boost, eg: boost_1_58_0 cd boost_1_##_0 build_boost_release_and_debug.sh # then patch .bashrc as instructed # eclipse and server/nix/bootstrap.sh are customized to match |
boost build for both 32 and 64 bit Windows |
---|
Open a VS2013 x64 Native Tools Command Prompt.
EITHER: for new installs, you have to run bootstrap.bat first, it will build bjam; OR: for reruns, remove boost dirs: [bin.v2, stage]. Then build 64-bit: cd "C:\Michael's Data\development\sixth_column\boost_1_55_0" bjam --toolset=msvc-12.0 address-model=64 --build-type=complete --stagedir=windows_lib\x64 stage Now open VS2013 x86 Native Tools Command Prompt and build 32-bit: cd "C:\Michael's Data\development\sixth_column\boost_1_55_0" bjam --toolset=msvc-12.0 address-model=32 --build-type=complete --stagedir=windows_lib\x86 stage |
php debugging |
---|
Tail these:
tail -f /var/log/apache2/sitelogs/thedigitalage.org/ssl_error_log tail -f /var/log/ampache-tda/ampache.(today).log |
This leads to too much noise, not needed...
emacs /etc/php/apache2-php5.3/php.ini display_errors = On /etc/init.d/apache restart |
Eclipse debug and release env var settings |
---|
eclipse env settings:
Project->Settings->C++ Build->Build vars-> Debug: CPPFLAGS: $CPPFLAGS LDFLAGS: $DEBUG_LDFLAGS CFLAGS: -ggdb3 -O0 CXXFLAGS: -ggdb3 -O0 Release: CPPFLAGS: $CPPFLAGS LDFLAGS: $RELEASE_LDFLAGS Run->Run configurations->C++ App-> Debug: LD_LIBRARY_PATH: /home/m/development/boost_1_58_0/lib-debug/ NOTE: you suck eclipse, this doesn't work: LD_LIBRARY_PATH: $DEBUG_LD_LIBRARY_PATH Release: LD_LIBRARY_PATH: /home/m/development/boost_1_58_0/lib-release/ NOTE: nope: LD_LIBRARY_PATH: $RELEASE_LD_LIBRARY_PATH |
eclipse settings |
---|
I have reconfigured crackhead Eclipse 1000xs.
Finally I took the time to capture the settings. Clone them, and push updates!
cd /home/m/development/eclipse-workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings ln -s /home/m/development/config/common/home/m/development/eclipse-workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/* . That should get you configured very well. Here are some of the settings that are used:
|
eclipse java project layout format |
---|
Eclipse uses a workspace which holds projects. Java apps written with Eclipse are organized as follows:
|
eclipse new project from existing code |
---|
You can set up a new project without specifying anything about it, just to browse the code.
File->New Project->Empty Name: bbby2e05 Location: c:\ [ ] Create subdir --- Show all files select everything in include, rc->include in project repeat for src dont worry about mak or install folders for now, just add files later as needed save all --- then set up a repo for it! cd c:\bbb2e05 git init (plus add cpp c hpp h, commit, set up daily, sync on bitpost) |
It is also possible to set up a C++ makefile or PHP project from existing code.
(rclick projects area)->New->Project...->C++->Makefile Project with existing code (name it and make sure Show all files is selected) |
emacs configuration |
---|
This common config should work well in both terminal and UI:
/home/m/development/config/common/home/m/.emacs NOTE that you need some other things to be configured properly:
export TERM=xterm-256color
|
SQL Server 2008+ proper upsert using MERGE |
---|
-- We need an "upsert": if record exists, update it, otherwise insert. -- There are several options to do that. -- Trying to do it correctly means... -- 1) use a lock or transaction to make the upsert atomic -- 2) use the best-available operation to maximize performance -- SQL Server 2008 has MERGE which may be slightly more efficient than -- separate check && (insert||update) steps. And we can do it with -- a single lock instead of a full transaction (which may be better?). -- It's messy to code up though since three blocks of fields must be specified. -- Cest la vie. MERGE [dbo].[FACT_DCSR_RemPeriodMonthlyReport] WITH (HOLDLOCK) AS rpmr USING (SELECT @ID AS ID) AS new_foo ON rpmr.ID = new_foo.ID @last_months_year as DCSRYear, @last_month as DCSRMonth, @last_month_name as MonthName, Device_Type_ID, WHEN MATCHED THEN UPDATE SET f.UpdateSpid = @@SPID, UpdateTime = SYSDATETIME() WHEN NOT MATCHED THEN INSERT ( ID, InsertSpid, InsertTime ) VALUES ( new_foo.ID, @@SPID, SYSDATETIME() ); |
git use kdiff3 as difftool and mergetool | |
---|---|
It's been made easy on linux...
[diff] tool = kdiff3 [merge] tool = kdiff3 |
Before - What a ridiculous pita... copy this into .git/config...
[difftool "kdiff3"] path = /usr/bin/kdiff3 trustExitCode = false [difftool] prompt = false [diff] tool = kdiff3 [mergetool "kdiff3"] path = /usr/bin/kdiff3 trustExitCode = false [mergetool] keepBackup = false [merge] tool = kdiff3
[difftool "kdiff3"] path = C:/Progra~1/KDiff3/kdiff3.exe trustExitCode = false [difftool] prompt = false [diff] tool = kdiff3 [mergetool "kdiff3"] path = C:/Progra~1/KDiff3/kdiff3.exe trustExitCode = false [mergetool] keepBackup = false [merge] tool = kdiff3 |
git create merge-to command |
---|
Add this handy alias command to all git repos' .config file...
[alias] merge-to = "!gitmergeto() { export tmp_branch=`git branch | grep '* ' | tr -d '* '` && git checkout $1 && git merge $tmp_branch && git checkout $tmp_branch; unset tmp_branch; }; gitmergeto" |
git shared repo |
---|
There are two possibilities (I prefer the latter).
git config core.sharedRepository true To set it on a new git repo during initial setup, make sure devs are in the same group, and use: git init --shared=group |
git create new branch on server, pull to client |
---|
# ON CENTRAL SERVER git checkout master # as needed; we are assuming that master is clean enough as a starting point git checkout -b mynewbranchy # HOWEVER, use this instead if you need a new "clean" repo and even master is dirty... # You need the rm because git "leaves your working folder intact". git checkout --orphan mynewbranchy git rm -rf . # ON CLIENT git pull git checkout -b mynewbranchy origin/mynewbranchy # if files are in the way from the previously checked-out branch, you can force it... git checkout -f -b mynewbranchy origin/mynewbranchy |
git windows configure notepad++ editor |
---|
git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" |
git pull when untracked files are in the way |
---|
This will pull, forcing untracked files to be overwritten by newly tracked ones in the repo:
git fetch --all git reset --hard origin/mymatchingbranch |
git create new branch when untracked files are in the way |
---|
git checkout -b bj143 origin/bj143 git : error: The following untracked working tree files would be overwritten by checkout: (etc) TOTAL PURGE FIX (too much): git clean -d -fn "" -d dirs too -f force, required -x include ignored files (don't use this) -n dry run BEST FIX (just overwrite what is in the way): git checkout -f -b bj143 origin/bj143 |
git fix push behavior - ONLY PUSH CURRENT doh |
---|
git config --global push.default current |
git recreate repo |
---|
git clone ssh://m@thedigitalmachine.com/home/m/development/thedigitalage/ampache-with-hangthedj-module cd ampache-with-hangthedj-module git checkout -b daily_grind origin/daily_grind If you already have the daily_grind branches and just need to connect them: git branch -u origin/daily_grind daily_grind |
git connect to origin after the fact |
---|
git remote add origin ssh:// m@bitpost.com/home/m/development/logs git fetch From ssh:// bitpost/home/m/development/logs * [new branch] daily_grind -> origin/daily_grind * [new branch] master -> origin/master git branch -u origin/daily_grind daily_grind git checkout master git branch -u origin/master master |
Windows command prompt FULL SCREEN |
---|
Type cmd in start search box and right-click on the cmd shortcut which appears in the results. Select Run CMD as administrator.
Next, in the command prompt, type wmic and hit Enter. Now try to maximize it! Close it and again open it. It will open as a maximized window! You may have to ensure that the Quick Edit Mode in the Options tab is checked. |
bash chmod dirs |
---|
find /path/to/base/dir -type d -exec chmod g+x {} \; |
Web Services |
---|
Firefox Addon development |
---|
mediawiki collapsible skeleton |
---|
#replace# |
mediawiki collapsible example |
---|
DJs are kept on the active Active djs are maintained Active djs are maintained Active djs are maintained Active djs are maintained Active djs are maintained Active djs are maintained djs list when both the server and the dj are enabled. |
All djs are shown in the prefs djs list.
Line 2 Line 3 All djs are shown in the prefs djs list.All djs are shown in the prefs djs list.All djs are shown in the prefs djs list.All djs are shown in the prefs djs list.All djs are shown in the prefs djs list. cd /var/www/localhost/htdocs/mediawiki emacs LocalSettings_redirector.php (to hardcode each site) php maintenance/update.php (repeat for each site) emacs LocalSettings_redirector.php (to reset dynamic behavior) |