Difference between revisions of "Development reference"

From Bitpost wiki
Jump to navigation Jump to search
 
(17 intermediate revisions by the same user not shown)
Line 16: Line 16:
 
{| class="wikitable"
 
{| class="wikitable"
 
! [http://www.aosabook.org/en/index.html Architecture of major open source apps]
 
! [http://www.aosabook.org/en/index.html Architecture of major open source apps]
 +
|}
 +
{| class="wikitable"
 +
! [[Security]]
 
|}
 
|}
 
{| class="wikitable"
 
{| class="wikitable"
Line 21: Line 24:
 
|}
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
! String escape formatting across different languages and systems
+
! nosql enhances, not replaces, SQL
 
|-
 
|-
|  
+
| Not all data should be denormalized, and not all data should be normalized.  The optimal mix considers the extent of the data. 
* c++ to JSON: always use nlohmann::json j.dump() to encode, to ensure strings are properly escaped
+
 
* JSON to c++: always use nlohmann::json j.parse() "
+
* Precise schemas are good when not overdone
* c++ to Javascript: use raw_to_Javascript() to properly escape
+
* When a container has an array with a large number of elements, it should be normalized
* c++ to sqlite: use SqliteLocalModel::safestr(), which uses double_doublequotes(str)
+
* Sparse data and heterogeneous data are the best candidates for denormalization
 +
 
 +
Postgres with JSON allows an elegant combination of nosql and SQL.
 
|}
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
Line 59: Line 64:
 
|-
 
|-
 
| Among competing hypotheses, the one with the fewest assumptions should be selected.
 
| Among competing hypotheses, the one with the fewest assumptions should be selected.
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Security
 
|-
 
| Notes to review before interviews, etc:
 
 
    ---------------------------
 
    fedramp cloud certification
 
    ---------------------------
 
      strong encryption, eg AES 256-bit
 
      data should be encrypted before it leaves end-user "organization"
 
      encrypt: data-at-rest, data-in-transit, data-in-use
 
      encryption keys MUST be kept within end-user org
 
      CSP requirements: implement security, third-party assess, maintain authorization, comply with continous monitoring
 
     
 
  basics review
 
 
      public-private key
 
      ------------------
 
      plain -> encrypted -> plain
 
            ^            ^
 
          publickey      privatekey
 
         
 
     
 
      SSL HANDSHAKE
 
      -------------
 
      client                                                    server
 
            -> hello ->       
 
            < cert
 
      (check)
 
              send secret encryped with server public key >    decrypt secret)
 
              (opt) send client cert >                        (check - but not otherwise used?)
 
              ack>
 
              <ack
 
              exchange with shared secret key
 
 
  best encryption to date
 
    ssl labs:
 
      Key RSA 2048 bits (e 65537)
 
      signature SHA256withRSA
 
      certchain includes Let's Encrypt Authority X3, RSA 2048 bits, Signature: SHA256withRSA
 
      TLS 1.2 (not allowed: TLS 1.1, 1.0; SSL 3, SSL 2
 
        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)  ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)  ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)    ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)      DH 2048 bits  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x67)      DH 2048 bits  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)        DH 2048 bits  FS     
 
   
 
    review
 
 
      AES 256-bit for encryption
 
        aka Rijndael, which won in the original NIST AES selection process (in 2001!)
 
        symmetric key algorithm (same key to encrypt and decrypt)
 
        block size 128
 
        key length 256 (can be 128 and 192)
 
 
      SHA-256 for signatures
 
        a bit-specific SHA-2
 
        deprecates SHA-1
 
        NOT deprecated by SHA-3 (an alternative developed through NIST competition)
 
        256-bit "hash values" aka digests aka signatures)
 
        server + client ssl certificate process
 
       
 
      HMAC is a signature with a key - what I'm doing with JWT (HMAC-SHA256)
 
       
 
    broken: RC2 RC4 DES IDEA ...
 
 
    next-gen: https://security.stackexchange.com/questions/135054/whats-after-aes
 
      TLS 1.3, which is still a draft, is going with two authenticated ciphers as its required choices:
 
        AES-GCM, with either 128- or 256-bit keys;
 
        ChaCha20/Poly1305
 
      The reasons we have two are the following:
 
        As a backup—if one of them is broken, everybody can switch to the other;
 
        They have different strengths:
 
        AES-GCM has excellent hardware support in many platforms;
 
        ChaCha20/Poly1305 has faster all-software implementations than AES-GCM does.
 
 
    good for https with SSL certs, according to SSL labs:
 
        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)  ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)  ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)    ECDH secp256r1 (eq. 3072 bits RSA)  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)      DH 2048 bits  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x67)      DH 2048 bits  FS 128
 
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)        DH 2048 bits  FS     
 
 
 
 
  NIST (National Institute of Standards and Technology)
 
 
 
    SHA-3 competition 2007-2012 (SHA = Secure Hash Algorithm)
 
      64 entries
 
      5 finalists: BLAKE, Grøstl, JH, Keccak and Skein
 
      winner: Keccak
 
      schneier's feedback:
 
        Yes, I would have rather my own Skein had won, but it was a good choice.
 
 
  NSA has Suite A (classified algorithms that will not be released) and Suite B cryptography algorithms
 
    Suite B's components are:
 
   
 
    Advanced Encryption Standard (AES) with key sizes of 128 and 256 bits.
 
      For traffic flow, AES should be used with either
 
        the Counter Mode (CTR) for low bandwidth traffic or
 
        the Galois/Counter Mode (GCM) mode of operation for high bandwidth traffic (THIS CAN BE PARALLELIZED)
 
    Elliptic Curve Digital Signature Algorithm (ECDSA) – digital signatures
 
    Elliptic Curve Diffie–Hellman (ECDH) – key agreement
 
    Secure Hash Algorithm 2 (SHA-256 and SHA-384) – message digest
 
 
  talk about my projects
 
 
    nopc
 
      energy market
 
      need to measure power behind the consumers meter
 
      i wrote a client that lives on embedded devices
 
      i cross-compiled openssl, libmodbus, libcurl, libwebsockets, zlib
 
 
      ssl / websockets work:
 
        libwebsockets uses openssl, but i have played a bit with optional ssl: wolfssl
 
          has streaming media support, including the HC-128 and RABBIT stream ciphers
 
          Standard ciphers are supported, including EDH on both the client and server side. 
 
          wolfSSL recently added support for BLAKE2b, one of the SHA-3 finalists as well.
 
          wolfSSL’s underlying cryptography library is called wolfCrypt.
 
        i wouldn't want to stray from openssl unless there was a more compelling reason, since it gets so many eyeballs on it
 
        people don't like its depth of support for other algorithms, just stick with best-in-class
 
          Key RSA 2048 bits (e 65537)
 
          signature SHA256withRSA
 
          pki: rsa
 
 
      given a guid token, it uses that to generate ssl certs on the device
 
      then it runs 24/7 on the embedded device
 
      it has a tight loop with callbacks, C is gross but you can do pretty much anything
 
        in factthats the problem, you have to do everything!
 
        again, i heavily rely on reusable helpers
 
      so it has a single-threaded loop with callbacks
 
      poll:
 
        if !config configure client
 
        else poll and store meter data, buffered to memory then volatile then nonvolatile storage
 
        if ws not connected initiate connection
 
        service the connection callbacks (sending bi-directionally as needed)
 
 
    just added jwt to abettertrader
 
      uses HMAC-SHA256 (uses a secret during signature generation)
 
      client sends u/p
 
      server builds header+payload+HMAC-SHA256 signature with its own secret
 
      server sends back base64-encoded token to client
 
      client uses token on every API call
 
      when token times out, user must log in again
 
      server can almost instantly determine user's priviledges without a db hit
 
      that's why they call it stateless
 
 
    abettertrader c++ based webserver, gets A+ rating at ssllabs
 
    via haproxy!
 
      I serve up several domains from my home
 
      most of them use SNI with apache
 
        with SNI the hostname is sent outside of the encrypted traffic
 
        so you can serve up different apache sites based on the requested hostname
 
        it's fantastic - for years i had to serve up my different sites on different ports
 
        and it was hard to do https that way
 
      but! ... i'm running a C++ https server as well
 
      and i had to solve the problem of getting incoming https traffic to that server running on that port
 
      haproxy is THE BOMB for these kinds of things
 
      i configured haproxy to read the domain name and redirect traffic to the c++ http server and port
 
      but i am so excited about this, i got these bonuses with zero effort:
 
        ALL ssl handshaking is now done by haproxy!  i just give it ALL my certs, and it does the negotiations
 
          i was able to limit availabe ciphers to those listed as secure at ssllabs
 
            ssl-default-bind-options no-sslv3 no-tls-tickets force-tlsv12
 
            ssl-default-bind-ciphers AES128+EECDH:AES128+EDH
 
        ALSO i was able to turn on HSTS - this forces all http requests into https requests
 
          and that got me an A+ rating on ssllabs - for ALL My sites - in one fell swoop!
 
          i felt like that giant that killed 7 flies or whatever
 
     
 
    abettertrader uses a map of lambas and regexs
 
      when a url comes in, it plays it against all the registered regexs
 
      if it finds a match, it calls the lambda
 
      it's really fast and really fun
 
     
 
    i set up node.js scripting for my continuous integration
 
      i have an open source package called radscripts - it does an automatic semver bump on every commit
 
      i'm totally addicted to that
 
      you can turn it off and still get all the benefits -
 
      i turned off auto-tagging at causam because they wanted to control the specific numbers of releases
 
      but semver dictates: ...
 
     
 
    i am always tinkering, i keep track of my projects in phabricator, an agile ticket tool that sprang out of facebook         
 
      do you want to see it?
 
      willcodeforcoffee.org moodboom/G
 
 
  write a c++ app that sorts an array then encrypts it then decrypts it
 
    int main() {
 
      return 0;
 
    }
 
   
 
  review c++11, c++14, interview questions
 
    RAII resource acquisition is initializaztion- constructor acquires, destructor releases
 
 
  c++
 
    c++11 features I love:
 
      automatic type detection - this is great esp for iterators so you don't have to type as much
 
      for loops
 
        if you don't need to walk forwards or backwards as you loop, these greatly simplify code profile
 
        but if you need the iterator as you loop, you can stick with the old way
 
      lambda expressions - really fast to write inline functions
 
      move semantics - you don't have to copy out results when you're done in a function, you can move them - and it's largely automatic, really nice
 
      initialization syntax - i love this for creating test data, you can easily initialize big arrays, whatever, right in code
 
      delegating constructors - this si great, so you don't have to rewrite all the base class constructors to be able to add a new one
 
      threading - a lot of this is available with boost - but it's nice to have the standard incorporate all the best boost work
 
    c++14 seems much more incremental than 11 was
 
      you can use auto for function return types - that was already how lambdas worked in c++11, i thought...
 
      lamdba parameters can be auto - kind of like templating, seems really crazy and cool - haven't played with this much yet
 
      and closures, how cool is that!!!  "lambda captures"  it carries along the scope from where it was called. 
 
        javascript of course makes us a huge fan of this.
 
        but i wonder about the performance penalty involved. - again, haven't played with it much
 
        deprecated keyword, binary literals
 
    and then c++17 is on the way - c++ has always made me happy, i find it incredibly elegant compared to lower C or higher java/C# arenas
 
      i think javascript actually hits a sweeter spot than those
 
      so i'm enjoying C++ and javascript more than anything these days
 
      i wrote some utilities in node so i can use node for scripting, which has been really productive
 
      but i have to say, python would be a welcome addition
 
 
  c++ containers
 
   
 
    i use hashmaps of pointers via unordered_map
 
    unordered set lets you contain pointers, and specify the hash and equals values for the object pointed to
 
    typedef std::unordered_set<AutotradeParameterSet*,PersistentIDObject_hash,PersistentIDObjects_equal > AutotradeParameterSets;
 
    then you can set up a second "index" into the object store
 
    you have to maintain all indexes as you add and remove, of course
 
   
 
    unordered_map uses the hash to find the right bucket O(1)
 
    map uses a binary tree and a comparison operator O(log(n))
 
    std::find() on vector uses quicksort O(N*log(n)) or insertsort which uses heapsort for worst case
 
      mergesort is good to preserve order of equal items (in-place)
 
   
 
    python has TimSort, pretty cool - looks for presorted sections, then merges those, COOL
 
      in use in python since about 2002
 
   
 
    i also use a sorted vector class i derived from the standard vector class
 
      it too can use pointers instead of objects, allowing for multiple indexes on a set of objects
 
      it has push_unsorted(), bSorted() and sort(sort_function) functions
 
      usually with vectors you use lower_bound to find things
 
      sorted vector has find helpers, and they always sort if unsorted
 
      it's really useful when you have a huge amount of objects and only sort on occasion
 
 
  - nagging question: how do you add functionality to a product that's new? 
 
      this was a very valuable question that I didn't answer well
 
      can i ammend my answer?
 
        i mentioned that I would diagram function flows - that would definitely be a key strategy
 
        and to read any and all available documentation on the software
 
      what should have also been part of my answer:
 
        generate my own documentation as needed
 
        a fantastic tool for that is doxygen
 
        i ran it yesterday against a recent project, and it did a nice job creating class hierarchies etc.
 
 
 
      clang-tidy is suggested to be the best on reddit
 
        even has a -fix flag to fix in place, ha
 
        cmake can call it for you!!
 
      cppcheck
 
      coverity for Paid solutions
 
 
      jsonlint
 
 
|}
 
|}
 
|}
 
|}
Line 829: Line 576:
 
|-
 
|-
 
|
 
|
 +
{| class="mw-collapsible mw-collapsed wikitable"
 +
! String escape formatting across different languages and systems
 +
|-
 +
|
 +
* c++ to JSON: always use nlohmann::json j.dump() to encode, to ensure strings are properly escaped
 +
* JSON to c++: always use nlohmann::json j.parse() "
 +
* c++ to Javascript: use raw_to_Javascript() to properly escape
 +
* c++ to sqlite: use SqliteLocalModel::safestr(), which uses double_doublequotes(str)
 +
|}
 +
[[Postgres]]
 +
 
[[Simple-Web-Server]]
 
[[Simple-Web-Server]]
  
Line 889: Line 647:
 
  CC=gcc-4.9
 
  CC=gcc-4.9
 
|}
 
|}
 +
|}
 +
<!--
 +
 +
 +
===========================================================================================================================================================================================================================================================================================
 +
 +
 +
-->
 +
{| class="wikitable"
 +
! [[git]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 898: Line 666:
 
-->
 
-->
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
! C/C++ debugging
+
! Debugging
 
|-
 
|-
 
|
 
|
 +
{| class="mw-collapsible mw-collapsed wikitable"
 +
! Chrome capture large JSON variable
 +
|-
 +
| This is just pointlessly bizarre:
 +
* hit a breakpoint in the chrome debugger
 +
* right-click a variable and say "copy to global variable" (console will show name, typically "temp1")
 +
* push the variable to the clipboard by typing this in the console:
 +
copy(temp1)
 +
|}
 +
{| class="mw-collapsible mw-collapsed wikitable"
 +
! Visual Studio Code capture large string variable
 +
|-
 +
| While debugging, you can use the Debug Console to print memory, including the content of strings that are clipped by default in the variables and watch windows.
 +
View > Open View > Debug Console
 +
From there, send gdb a command to print memory – 300 characters of a string in this example:
 +
-exec x/300sb Query.c_str()
 +
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Qt Creator conditional breakpoint
 
! Qt Creator conditional breakpoint
Line 1,011: Line 796:
 
|}
 
|}
 
<!--  
 
<!--  
 
 
===========================================================================================================================================================================================================================================================================================
 
 
 
-->
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Bootstrap
 
|-
 
|
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Single Page Application
 
|-
 
| css:
 
<pre>
 
  .mdm-scrollable-div
 
  {
 
    height: 100%;
 
    overflow: auto;
 
  }
 
</pre>
 
html:
 
<pre>
 
  <-- header -->
 
 
  <div class="frame" id="frame1top">
 
    <div class="mdm-scrollable-div">
 
      ...
 
    </div>
 
  </div>
 
 
  <-- footer -->
 
</pre>
 
js:
 
<pre>
 
  // We need to adjust layout on resize, in ready handler, and programmatically as needed.
 
  $(window).resize(adjustLayout).resize();
 
 
  $( document ).ready(function() {
 
 
    // We need to adjust in ready handler, on resize, and programmatically as needed
 
    adjustLayout();
 
 
    /* your other page load code here*/
 
 
  });
 
 
  function adjustLayout(){
 
 
      // ----------------------
 
      // Fundamental dimensions
 
      var hh = $('#theheader').outerHeight();
 
      var fh = $('#thefooter').outerHeight();
 
      var workspace_height = $(window).height() - hh - fh;
 
      var workspace_width = $(window).width();
 
      // ----------------------
 
     
 
      var cols = 1;
 
      var col_gap = 16;
 
     
 
      // Margin is based on percent of one column width, so it goes to zero before column width does.  :-)
 
      // Width is based on total width minus margins, then split between columns.
 
      var margin = ($(window).width() / cols) * .04;
 
      var w = ($(window).width() - (margin * (cols + 1))) / cols;
 
     
 
      var h1 = workspace_height;
 
     
 
      $('#frame1top').css({
 
          display:'block',
 
          position:'absolute',
 
          left: margin * 1 + w * 0,
 
          top: hh,
 
          width: w,
 
          height: h1
 
      });
 
  }
 
</pre>
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Button handlers
 
|-
 
| Buttons can be represented with labels; in that case, use a click handler:
 
<pre>
 
    jQuery('<label id="'+cycle.apsID+'" class="btn">MahButt</label>')
 
    .appendTo('#'+chartid+'-apsbar')
 
    .on('click', function(){
 
      $(location).attr('href','/v1/parameters/'+this.id+'.html');
 
    });
 
</pre>
 
You can also get the checked state, and prevent the button from being pressed, among other things:
 
<pre>
 
      jQuery('<label id="'+cycle.run+'" ...
 
      .on('click', function(e){
 
        var run = this.id;
 
        // Look for the (label->input)
 
        if (this.firstChild.checked)
 
        ...
 
        // To prevent checked/pressed state if desired:
 
        e.stopPropagation();
 
      } 
 
</pre>
 
Button bars are represented by labels wrapped around inputs:
 
<pre>
 
    <div class="btn-group live-buttons" data-toggle="buttons"><div class="btn-group"><label class="btn"><input type="checkbox">text...
 
</pre>
 
In that case use a change handler on the input:
 
<pre>
 
      var label = jQuery('<label class="btn btn-sm btn-'+color+'"></label>').appendTo(action_button_bar);
 
      var input = jQuery('<input class="run-'+cmd+'" type="checkbox" autocomplete="off" value="'+cycle.run+'">').appendTo(label)
 
      .on('change', cycle.owned? function(){
 
        patchPick(this.value,'{ "action" : "run-hold"      }');
 
      } : function() {
 
        patchPick(this.value,'{ "action" : "run-buy"        }');
 
      });
 
      var text = jQuery('<span class="glyphicon glyphicon-'+glyph+'"></span> <span class="hidden-xs">'+cmd+'</span>').appendTo(label);
 
</pre>
 
If you just need clicks from the button bar, you do NOT NEED input:
 
<pre>
 
    <div class="btn-group live-buttons" data-toggle="buttons"><div class="btn-group"><label class="btn">text...
 
</pre>
 
Then you can put the change handler right on the label:
 
<pre>
 
    var applybar = jQuery('<div id="applybar-'+cycle.run+'" class="btn-group pull-right" data-toggle="buttons" />');
 
    var apply_button = jQuery('<label id="apply-'+cycle.run+'" class="btn btn-sm btn-moneygreen"><span class="glyphicon glyphicon-ok"></span><span class="hidden-xs"> Apply</span></input></label>')
 
    .on('click', function(e) {   
 
   
 
        // Do work
 
 
        e.stopPropagation();
 
    })
 
    .appendTo(applybar)
 
    ;
 
</pre>
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Programmatically pressing a button
 
|-
 
| You MUST DO TWO THINGS:
 
* Set the active class on the button/label
 
* Set the input to checked
 
<label class="btn active">
 
  <input type="checkbox" autocomplete="off" checked>
 
  Click me
 
</label>
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Handling the UNCHECK event on a pushbutton
 
|-
 
| Again you MUST SET BOTH active and checked STATES PROPERLY when creating the button (see above).  Do not set either if the button is unpressed; set both if it is pressed.
 
 
Then you can use a single change event:
 
  $("input[type='checkbox'][class='run-hold-on-buy'    ]").change(function() { patchPick(this.value,'{ "action" : "'+(this.checked?'hold-on-buy-on'    :'hold-on-buy-off'    )+'"}');  });
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Collapsible panel
 
|-
 
|
 
* Use a unique id on content div, data-target to connect panel header to content, mdm-panel-collapser so javascript can find icon, abt-scrollable-panel for margin.
 
* HTML for each panel (starts collapsed)
 
<pre>
 
    <div class="panel panel-default abt-scrollable-panel">
 
      <div class="panel-heading collapsed" data-toggle="collapse" data-target="#my-content-block-one">Software development skills<span class="mdm-panel-collapser text-muted glyphicon glyphicon-chevron-down pull-right"></span></div>
 
      <div class="collapse" id="my-content-block-one">
 
        <div class="mdm-panel-body">
 
 
 
        <!-- CONTENT, can include another nested panel, just add .mdm-nested-panel to class; example: -->
 
 
 
          <div class="panel panel-default mdm-scrollable-panel mdm-nested-panel">
 
            <div class="panel-heading collapsed mdm-job-panel-heading" data-toggle="collapse" data-target="#toshiba-job"><p><strong>Senior Developer and Offshore Manager</strong><i> - Toshiba Global Commerce Solutions, Inc.</i><span class="mdm-panel-collapser text-muted glyphicon glyphicon-chevron-up pull-right"></span></p><p><small>April 2014 – August 2015</small></p></div>
 
            <div class="collapse in" id="toshiba-job">
 
              <div class="mdm-panel-body">
 
                <!-- SUBCONT(IN)ENT im so funny -->
 
              </div>
 
            </div>
 
          </div>
 
         
 
 
        </div>
 
      </div>
 
    </div>
 
</pre>
 
* For an expanded panel, simply change icon from down to up, and add "in" to content div:
 
<pre>
 
    ... glyphicon-chevron-up ...
 
    <div class="collapse in mdm-panel-body" id="collapseOrderItems1">
 
</pre>
 
* Define Javascript collapser once on load
 
  $('.collapse').on('hide.bs.collapse show.bs.collapse',
 
    toggleCollapser
 
  );
 
* CSS
 
    .mdm-nested-panel {
 
      margin-top: 1em;
 
      margin-left: 1em;
 
    }
 
    collapse.mdm-panel-body collapsing.mdm-panel-body {
 
        margin: 1em;
 
    }
 
* Common reusable function:
 
  function toggleCollapser(e) {
 
      $(e.target)
 
          .prev('.panel-heading')
 
          .find('.mdm-panel-collapser')
 
          .toggleClass('glyphicon-chevron-down glyphicon-chevron-up');
 
 
 
    // Prevent bubble up to any parent collapsers.
 
    // This allows nested collapsers, whoop.
 
    e.stopPropagation();
 
  }
 
|}
 
|}
 
<!--
 
 
 
===========================================================================================================================================================================================================================================================================================
 
 
 
-->
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! D3
 
|-
 
|
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! ALWAYS initialize incoming data
 
|-
 
| Hard-earned data-import lessons:
 
* tsv() will do complete date formatting, so when you remove it to use JSON directly, you HAVE TO convert JSON timestamps of ANY kind to full Javascript date objects:
 
  var data = [{"date":"2017-04-01T04:00:00.000Z",...
 
  // MDM WE MUST MASSAGE DATA HERE
 
  // JSON VALUES ARE ALWAYS STRINGS, we need to change to Javascript DATE!
 
  // Incoming datasets need a bit of massaging.
 
  // We do that in a function so we can reuse it on incoming dataset updates.
 
  function initializeDataset(dataset) {
 
      // TIME ON X
 
      // Convert date strings to actual date values.
 
      // MDM MAKE SURE this matches the incoming format.
 
      // Adding date so we can run the chart across days without trouble.
 
      // var parseDate = d3.time.format("%H:%M:%S %m-%d-%Y").parse;
 
      // var parseDate = d3.timeParse("%Y %b %d");
 
      var parseDate = d3.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
 
      dataset.forEach(function(d) {
 
          // there is NO SKIPING THIS STEP, you have to get valid Javascript date objects out of JSON strings
 
          d.date = parseDate(d.date);
 
          // we WOULD have to divide all data by zero,
 
          // but we already grabbed post-data that was already converted
 
          // This WORKS but makes data / 10000 (very small numbers)
 
          //for (var i = 1, n = dataset.columns.length; i < n; ++i) d[dataset.columns[i]] = d[dataset.columns[i]] / 100;
 
      });
 
  }
 
  initializeDataset(data);
 
 
* tsv() will create an ARRAY but it also jams in a columns PROPERY; it takes two steps to duplicate that:
 
  var data = [
 
    {"date":"2015-06-15T04:00:00.000Z","Google Chrome":0.48090000000000005,...},
 
    {"date":"2015-06-22T04:00:00.000Z","Google Chrome":0.48979999999999996,...),
 
  ];
 
  data.columns = ["date","Google Chrome","Internet Explorer",...  ];
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! ALWAYS set range and domain properly
 
|-
 
| You have to know your display size (range) and the min and max of your data (domain), on each axis.  From [https://bost.ocks.org/mike/bar/ Mike's docs]:
 
 
D3’s scales specify a mapping from data space (domain) to display space (range).
 
        D3’s scales can also be used to interpolate many other
 
        types of display-space values, such as paths, color spaces
 
        and geometric transforms.
 
       
 
          var x = d3.scale.linear()
 
              .domain([0, d3.max(data)])
 
              .range([0, 420]);
 
 
 
        Although x here looks like an object, it is also a function
 
        that returns the scaled display value in the range
 
        for a given data value in the domain.
 
        For example, an input value of 4 returns 40, and an input value of 16
 
        returns 160. To use the new scale, simply replace the
 
        hard-coded multiplication by calling the scale function:
 
       
 
        d3.select(".chart")
 
          .selectAll("div")
 
            .data(data)
 
          .enter().append("div")
 
            .style("width", function(d) { return x(d) + "px"; })
 
            .text(function(d) { return d; });
 
Watch out for Mike's examples where he (trickily) doesn't bother to set a domain because his data is in the [0..1] set, and that's the default domain, apparently.
 
|}
 
|}<!--
 
  
  
Line 1,334: Line 831:
 
-->
 
-->
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
! Javascript and JQuery
+
! css
|-
 
|
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Formatting examples (numbers dates etc.)
 
 
|-
 
|-
 
|  
 
|  
   // Javascript sucks at dates.
+
   /* class="first second" */
   // d3 to the rescue! 
+
  .first.second {}
  var parseInitDate = d3.utcParse("%Y-%m-%dT%H:%M:%SZ");
+
   /* class="first" OR class="second" */
  var initDate = parseInitDate(initial_managed_value_date);
+
   .first, .second {}
   var initDateString =
+
  /* class="first second", or class="second", or class="third second", or class="second third" */
      initDate.getUTCFullYear()
+
   .second {}
      +"/"+ (initDate.getUTCMonth()+1)
+
   /* apply to any .child at any depth under .parent */
      +"/"+ initDate.getUTCDate()
+
   .parent .child {}
      + " " + initDate.getUTCHours()
+
  /* apply to .child if it is DIRECTLY under .parent */
      + ":" + initDate.getUTCMinutes()
+
   .parent > .child {}
      + ":" + initDate.getUTCSeconds();
 
 
 
   var rightNow = new Date;
 
   var initToNow_DecimalDays = parseFloat(rightNow - initDate) / 864e5;  // 86,400,000 ms/day
 
   var initToNow_PercentOfYear = initToNow_DecimalDays / 365.0;
 
   var change_in_value = (parseFloat(total_managed_value) - parseFloat(initial_managed_value))/parseFloat(initial_managed_value);
 
  
  $('#initial_managed_value').val(initial_managed_value.toFixed(2));
 
  $('#initial_managed_value_date').val(initDateString);
 
  $('#change_in_value').val((change_in_value*100.0).toFixed(1)+ "%");
 
  $('#equivalent_apr').val((change_in_value/initToNow_PercentOfYear*100.0).toFixed(1)+ "%");
 
  $('#total_managed_value_readonly').val(total_managed_value.toFixed(2));
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Array vs Object lifetime
 
|-
 
|
 
        // If the JSON data were an array, we would need to slice-to-clone to keep it around:
 
        //    var dataCopy = data.slice();
 
        //    updateStockData(run,dataCopy);
 
        // We have an object so we can pass a reference, and it will keep the object around.
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Event handlers
 
|-
 
| Three basic methods:
 
* Attach a function to an event of a specific element; charts.js example:
 
      var label = jQuery('<label class="btn btn-sm btn-'+color+'"></label>').appendTo(action_button_bar);
 
      var input = jQuery('<input class="run-'+cmd+'" type="checkbox" autocomplete="off" value="'+cycle.run+'">').appendTo(label)
 
      .on('change', cycle.owned? function(){
 
        patchPick(this.value,'{ "action" : "run-hold"      }');
 
      } : function() {
 
        patchPick(this.value,'{ "action" : "run-buy"        }');
 
      });
 
      var text = jQuery('<span class="glyphicon glyphicon-'+glyph+'"></span> <span class="hidden-xs">'+cmd+'</span>').appendTo(label);
 
 
* Add a function handler once, for a class of elements; picks.js example:
 
  $("input[type='checkbox'][class='run-top'    ]").change(function() { patchPick(this.value,'{ "action" : "run-move-top"  }');  });
 
* Event delegation: Javascript takes events and "bubbles them up" through the chain of parents; set up a handler on a parent to listen for these bubbles.
 
* At end of handler, prevent further bubbling with stopPropagation() - still finishes the current event (eg following the href of an <a>):
 
<pre>
 
    var datepicker = jQuery(
 
      '<div class="input-group date form-inline pull-left" data-provide="datepicker" id="datepicker'+cycle.run+'">'+
 
        '<input type="text" class="input-sm form-control">'+
 
        '<div class="input-group-addon">'+
 
            '<span class="glyphicon glyphicon-th"></span>'+
 
        '</div>'+
 
      '</div>'
 
    )
 
    .on('changeDate', function(e){
 
      alert('next '+cycle.run);
 
      e.stopPropagation();
 
    })
 
    ;   
 
</pre>
 
* Or use preventDefault() to stop completely:
 
<pre>
 
    var datepicker_next = jQuery(
 
      '<a href="">My javascript action</a>'
 
    )
 
    .on('click', function(e){
 
      alert('next '+cycle.run);
 
      e.preventDefault();
 
    })
 
    ;
 
</pre>
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Debug clicks on ANY PAGE
 
|-
 
|
 
* Press F12 => Sources => Event Listener Breakpoints righthand pane => Mouse => [x] click
 
B O O M  we have it captured and can step into ANYTHING.
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! JWT flow
 
|-
 
| Client is easy!
 
<pre>
 
  Client application                                            API
 
  --------                                              -----------
 
        |                                                      |
 
        |                  GET /api/employees                |
 
        |----------------------------------------------------->|
 
        |                    403 Forbidden                    |
 
        |<-----------------------------------------------------|
 
        |                                                      |
 
        |                                                      |
 
        |                POST /api/authenticate              |
 
        |    { login: "john.doe", password: "password" }      |
 
        |----------------------------------------------------->|
 
        |                      200 Success                    |
 
        |            { token: "my.personal.token" }          |
 
        |<-----------------------------------------------------|
 
        |                                                      |
 
        |                                                      |
 
        |                GET /api/employees                  |
 
        | Header { "Authorization: Token "my.personal.token" } |
 
        |----------------------------------------------------->|
 
        |                      200 Success                    |
 
        |<-----------------------------------------------------|
 
        |                                                      |
 
</pre>
 
|}
 
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,464: Line 854:
 
-->
 
-->
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
! Node.js
+
! SQL
 
|-
 
|-
 
|
 
|
{| class="wikitable"
 
! [[Node.js]] installation
 
|}
 
{| class="wikitable"
 
! [[Node create a new module]]
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Register with npm
 
|-
 
| A one-time registration is required on a new machine if you want to publish from it:
 
npm adduser
 
Username: moodboom
 
Password: (see private)
 
Email: (this IS public) moodboom@gmail.com
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Publish a node module
 
|-
 
|
 
sudo npm install -g # keep doing this until you are happy with local install
 
# update version in package.json
 
# this creates a FULL "annotated" tag, not a "lightweight" tag that doesn't show up for [git describe] - it also removes the need for a separate commit
 
git tag -a 1.0.5 -m "changes include..."
 
git push && git push --tags  # NOTE: bitpost has a git hook to push changes all the way up to github
 
npm publish
 
|}
 
 
{| class="mw-collapsible mw-collapsed wikitable"
 
{| class="mw-collapsible mw-collapsed wikitable"
! Update a node module's dependencies
+
! Count records within a range
 
|-
 
|-
|  
+
| This groups records into ranges, sorts by them, and gives a count, sweet:
# make sure dependency in package.json has a carat at the beginning of its version (^x means "at least" version x)
+
    select count(*), id/1000000 as groupid from AccountHistory group by groupid;
# make sure the dependency has a new version available - completely publish it first if it is your own
 
# then you can simply reinstall from within the module folder to get all dependencies upgraded
 
sudo npm install -g
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Develop several node modules at once
 
|-
 
| Convert dependencies to use local packages instead of published versions, eg:
 
cd ~/development/mah-haus
 
npm install -S /home/m/development/thedigitalage/rad-scripts
 
Then reinstall everything (local dependent modules, then parent modules, pita - consider links if doing longer-term dev)
 
sudo npm install -g
 
Then convert back to published versions as they become available (it's up to me to stabilize and publish new module versions):
 
cd ~/development/mah-haus
 
npm install -S rad-scripts
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! auto AWS
 
|-
 
|
 
* npm install -g aws-sdk
 
* Add credentials here: C:\Users\Administrator\.aws
 
* see existing scripts, anything is possible
 
|}
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! install bootstrap
 
|-
 
|
 
* npm install -g grunt-cli
 
* mkdir mysite && cd mysite
 
* npm install bootstrap
 
* cd node_modules/bootstrap
 
* npm install # to actually pull down dependencies
 
* grunt dist # builds and minifies so you're good to go!
 
 
|}
 
|}
 +
[[postgres]] - [[sqlite]] - [[mysql]] - [[SQL Server]] - [[Robomongo]] - [[DBeaver]] - [[pgadmin3]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,541: Line 872:
  
 
-->
 
-->
{| class="mw-collapsible mw-collapsed wikitable"
+
{| class="wikitable"
! css
+
! [[Android]]
|-
 
|
 
  /* class="first second" */
 
  .first.second {}
 
  /* class="first" OR class="second" */
 
  .first, .second {}
 
  /* class="first second", or class="second", or class="third second", or class="second third" */
 
  .second {}
 
  /* apply to any .child at any depth under .parent */
 
  .parent .child {}
 
  /* apply to .child if it is DIRECTLY under .parent */
 
  .parent > .child {}
 
 
 
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,564: Line 882:
  
 
-->
 
-->
{| class="mw-collapsible mw-collapsed wikitable"
+
{| class="wikitable"
! SQL
+
! [[Java]]
|-
 
|
 
{| class="mw-collapsible mw-collapsed wikitable"
 
! Sqlite timestamp-to-readable-date query
 
|-
 
|
 
select quote, timestamp, strftime('%Y-%m-%d %H:%M:%S', datetime(timestamp, 'unixepoch')) from StockQuotes as s where s.symbol="TSLA" order by timestamp;
 
|}
 
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,583: Line 893:
 
-->
 
-->
 
{| class="wikitable"
 
{| class="wikitable"
! [[Android]]
+
! [[Kotlin]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,593: Line 903:
 
-->
 
-->
 
{| class="wikitable"
 
{| class="wikitable"
! [[Java]]
+
! [[Maven]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,603: Line 913:
 
-->
 
-->
 
{| class="wikitable"
 
{| class="wikitable"
! [[Python]]
+
! [[Scala]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,613: Line 923:
 
-->
 
-->
 
{| class="wikitable"
 
{| class="wikitable"
! [[Scala]]
+
! [[Python]]
 
|}
 
|}
 
<!--  
 
<!--  
Line 1,648: Line 958:
 
  /etc/init.d/apache restart
 
  /etc/init.d/apache restart
 
|}
 
|}
|}
 
<!--
 
 
 
===========================================================================================================================================================================================================================================================================================
 
 
 
-->
 
{| class="wikitable"
 
! [[git]]
 
 
|}
 
|}
 
<!--  
 
<!--  

Latest revision as of 14:50, 8 May 2019

Design, programming and version control.

Patterns
Major Objects
Quick-http
Continuous Integration
Architecture of major open source apps
Security
Model View Controller
nosql enhances, not replaces, SQL
Not all data should be denormalized, and not all data should be normalized. The optimal mix considers the extent of the data.
  • Precise schemas are good when not overdone
  • When a container has an array with a large number of elements, it should be normalized
  • Sparse data and heterogeneous data are the best candidates for denormalization

Postgres with JSON allows an elegant combination of nosql and SQL.

Web design mantra
  1. DESIGN INPUT TO THE INPUT DEVICE
    1. respect the input device
    2. detect it and use a reasonable default guess
    3. allow manual override
    4. [mouse/pen]...[finger]
    5. sm-md-lg ... sm-md-lg
  2. DESIGN VISUALS TO THE SCREEN
    1. high-res = SHOW LOTS OF DETAIL
    2. responsive, zoomable
git central shared repository
Use bare repos for any central shared repositories. Use the [####.git] suffix on bare repo names.

Bare repositories are designed to be shared. Maintenance on the central server is easier because you don't have local files to manage permissions or constant flux. Plus, you can always have a second repo on the central server where you check out a specific branch (e.g. to serve up with apache). If you want a dynamically updated central repo, clone the ###.git repo to ###, and add a post-receive hook (see bitpost quick-http.git for a good example).

To configure the repo as shared:

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
Occam's razor
Among competing hypotheses, the one with the fewest assumptions should be selected.
C++
Deleting multiple elements in a collection
  • For sequences (vector, list...), best practice is to use the erase-remove STL pattern
  • For associative containers (set, map...): just recurse and remove iterators, they won't muck up the sequence. example

See MemoryModel::saveDirtyObjectsAsNeeded() for example code.

c++ Create a portable C/C++ project
Use QtCreator + CMake, both available everywhere!
   set up:
       create a Qt project as: New Project-> Non-Qt/Plain C Project (CMake Build)
           pick the PARENT and use the name of the existing folder
           set up a build folder in the existing folder, called (base)/qtcreator-release-build
           it creates CMakeLists.txt (THIS IS BASICALLY THE PROJECT FILE!)
           also creates main.c or something
           build it!  make sure it works
           NOW we can edit CMakeLists.txt - change . to ./src to get it to scan the src folder for code!
           and easily add "known" libs!  this was all i needed:
               TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread websockets)
           make sure it builds
           now we want a DEBUG build as well!
           Projects->Build&Run->pick Build in weird Build/Run pillbox->Edit build configs:
               Rename: release
               CMake build dir: Make sure build dir is set to release ie qtcreator-debug-build
               Add: Clone: release, name: debug
                   for debug, add a custom build step BEFORE make step:
                       command: /usr/bin/cmake
                       args: -DCMAKE_BUILD_TYPE=Debug .
                       working dir: %{buildDir}
                       (add it, and move it up above make)
                       (build em both)
           Projects->Build&Run->pick Run in weird Build/Run pillbox
               Run Configuration: rename to "{...} release"
               clone it into "{...} debug"
               change working dir to match Build path
               change any needed params
   Now you should have build+run debug+release configurations, selectable in the weird project icon in bottom of left-side toolbar ("mode selector")
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.
  • Compiler selection
    • linux and mac: gcc
    • windows: Visual Studio
  • IDE selection
    • linux and mac: Qt Creator
    • windows: Qt Creator (OR Visual Studio OR eclipse?)
  • Debugger selection
    • linux and mac: Qt Creator
    • windows: Qt Creator (OR Visual Studio OR eclipse?)
c++11
c++11 include base constructor (etc) in derived class
The awesome C++11 way to steal the constructor from the base class, oh man I've been waiting for this one...
 class HttpsServer : public Server<HTTPS>
 {
   // DOES THIS FOR YOU!
   /*
   HttpsServer(unsigned short port, size_t num_threads, const std::string& cert_file, const std::string& private_key_file)
   :
       // Call base class
       Server<HTTPS>::Server(port, num_threads, cert_file, private_key_file)
   {}
   */
   using Server<HTTPS>::Server;
   ....
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.
You can use mutable on the variables that are not part of the key to remove the const.
This changes the constness of the object from binary (completely const) to logical (constness is defined by the developer).
So... set is a good way to achieve both encapsulation and logical const - make const work for you, not against! :-)

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.
A pointer functor can be provided that does a sort by dereferencing the pointer to the object.
Two requirements: you must make sure yourself that you do not change the key values - you can mark them const, provided in constructor;
you must create sort/equal/hash functors that dereference the pointers to use object contents
(the default will be by pointer address).
The arguably biggest advantage, as a result, is that you can create multiple sets
to reference the same group of objects with different sort funtors to create multiple indices.
You just have to manage the keys carefully, so that they don't change (which would invalidate the sorting).
The primary container can manage object allocation; using a heap-based unique_ptr allocation

   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;
boost
boost release and debug build for linux
   # download latest boost, eg: boost_1_59_0 
   m@wallee:~/development$ 7z x boost_1_59_0.7z
   rm boost && ln -s boost_1_59 boost
   cd boost
   build_boost_release_and_debug.sh
   # IMPORTANT: then patch .bashrc as instructed
   #     cmake-###/clean.sh and cmake-###/build.sh are customized to match
   #     (and older eclipse and server/nix/bootstrap.sh) 

To upgrade a CMake project:

   cd cmake-###/
   ./clean.sh
   ./build.sh

To upgrade an older autotools project:

   cd nix
   make distclean  # removes nasty .deps folders that link to old boost if you let them
   make clean      # removes .o files etc
   cd ../build-Release && make distclean && make clean
   cd ../build-Debug && make distclean && make clean
   cd ..
   ./bootstrap force release
   ./bootstrap force debug
boost release and debug build for Windows
Open a VS2015 x64 Native Tools Command Prompt.

EITHER: for new installs, you have to run bootstrap.bat first, it will build b2; OR: for reruns, remove boost dirs: [bin.v2, stage]. Then build 64-bit:

cd "....\boost_1_59_0"
b2 toolset=msvc variant=release,debug link=static address-model=64
rem trying to avoid excessive options, assuming I don't need these: threading=multi
(old stuff)
      --toolset=msvc-14.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
boost regex (very similar to c++11, with LESS BUGS and MORE POWER)
boost regex does everything you could need, take your time to get it right
  • regex_search will work hard to find substrings, while regex_match requires your regex to match entire input
  • smatch is a great way to get back a bunch of iterators to the results

example:

   virtual bool url_upgrade_any_old_semver(string& url)
   {
     // Perform a regex to update the embedded version if needed.
     // We have to see if (1) we have a semver and (2) it is not the current semver.
     // Only then do we take action.
     boost::regex regex("/([v0-9.]+?)/(.*)");
     boost::smatch sm_res;
     if (boost::regex_match(url,sm_res,regex,boost::match_default))
     {
       string incoming_semver(sm_res[1].first,sm_res[1].second);
       if (incoming_semver != semanticVersion())
       {
         url = string("/")+semanticVersion()+"/"+string(sm_res[2].first,sm_res[2].second);
         return true;
       }      
     }
     return false;
   }

results:

     original string:    string(sm_res[0].first,sm_res[0].second);
     first group:        string(sm_res[1].first,sm_res[1].second);
     second group:       string(sm_res[2].first,sm_res[2].second);
     etc.
C++ libraries
String escape formatting across different languages and systems
  • c++ to JSON: always use nlohmann::json j.dump() to encode, to ensure strings are properly escaped
  • JSON to c++: always use nlohmann::json j.parse() "
  • c++ to Javascript: use raw_to_Javascript() to properly escape
  • c++ to sqlite: use SqliteLocalModel::safestr(), which uses double_doublequotes(str)

Postgres

Simple-Web-Server

C++ https libraries

Configure Qt development on Windows + Mac + linux

Build the TagLib library with Visual Studio 2013

C/C++ building/linking
gcc makefile pain
  • I went through a LOT of pain to determine that gcc requires libraries to be listed AFTER the source and output parameters
  • set LD_LIBRARY_PATH to point to your libs if they are not in system location
  • Make sure Makefile uses TABS NOT SPACES. it's a FACT OF LIFE. hate it if you want. plenty more things to hate about linux/C as well.
gcc install multiple versions in ubuntu (4 and 5 in wily, eg)
My code will not compile with gcc 5, the version provided with Ubuntu wily.

It gives warnings like this:

/home/m/development/boost_1_59_0/boost/smart_ptr/shared_ptr.hpp:547:34: warning: ‘template<class> class std::auto_ptr’ is deprecated [-Wdeprecated-declarations]

and outright errors like this:

depbase=`echo AtServer.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
g++ -DPACKAGE_NAME=\"at_server\" -DPACKAGE_TARNAME=\"at_server\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"at_server\ 1.0\" -DPACKAGE_BUGREPORT=\"m@abettersoftware.com\" -DPACKAGE_URL=\"\" -DPACKAGE=\"at_server\" -DVERSION=\"1.0\" -I. -I../../src  -I/home/m/development/Reusable/c++ -I/home/m/development/Reusable/c++/sqlite -std=c++11 -I/home/m/development/boost_1_59_0  -ggdb3 -O0 -std=c++11 -MT AtServer.o -MD -MP -MF $depbase.Tpo -c -o AtServer.o ../../src/AtServer.cpp &&\
mv -f $depbase.Tpo $depbase.Po
In file included from /usr/include/c++/5/bits/stl_algo.h:60:0,
                from /usr/include/c++/5/algorithm:62,
                from /usr/include/c++/5/ext/slist:47,
                from /home/m/development/boost_1_59_0/boost/algorithm/string/std/slist_traits.hpp:16,
                from /home/m/development/boost_1_59_0/boost/algorithm/string/std_containers_traits.hpp:23,
                from /home/m/development/boost_1_59_0/boost/algorithm/string.hpp:18,
                from /home/m/development/Reusable/c++/utilities.hpp:4,
                from ../../src/MemoryModel.hpp:11,
                from ../../src/SqliteLocalModel.hpp:13,
                from ../../src/AtServer.cpp:70:
/usr/include/c++/5/bits/algorithmfwd.h:573:13: error: initializer provided for function
    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
            ^
/usr/include/c++/5/bits/algorithmfwd.h:582:13: error: initializer provided for function
    noexcept(noexcept(swap(*__a, *__b)))

You can set up the update-alternatives tool to switch out the symlinks:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 20 --slave /usr/bin/g++ g++ /usr/bin/g++-5

BUT that seems BAD to me to switch out the compiler used by the SYSTEM. Instead, we should specify the compiler required by the PROJECT. This is supposed to do it, but it still uses /usr/include/c++/5, which seems wrong, and gives me errors:

CC=gcc-4.9
git
Debugging
Chrome capture large JSON variable
This is just pointlessly bizarre:
  • hit a breakpoint in the chrome debugger
  • right-click a variable and say "copy to global variable" (console will show name, typically "temp1")
  • push the variable to the clipboard by typing this in the console:
copy(temp1)
Visual Studio Code capture large string variable
While debugging, you can use the Debug Console to print memory, including the content of strings that are clipped by default in the variables and watch windows.
View > Open View > Debug Console

From there, send gdb a command to print memory – 300 characters of a string in this example:

-exec x/300sb Query.c_str()
Qt Creator conditional breakpoint
To break on line number with string condition:
  • Set the breakpoint on the line as usual: F9 or click in left border
  • In the breakpoints list, rclick Edit
  • Add a condition; to break on a string value, THIS WORKS:
         ((int)strcmp(strSymbol.c_str(), "GMO")) == 0
     
  • BUT THERE IS A PRICE TO PAY. qt/gcc won't continue properly, unless you sset ANOTHER common breakpoint, hit it, and resume from that. It appears gcc continues (we hit the breakpoint after all), but qt does no logging or debugging, bah
Qt Creator and linux debug libraries
  • I was able to build lws in debug, install in /usr/local, then I could step right into its code
m@case:~/development/causam/git/np/nop-bigress-client-c$ ./build_lws_debug
 Install the project...
 -- Install configuration: "DEBUG"
 -- Installing: /usr/local/lib/pkgconfig/libwebsockets.pc
 -- Installing: /usr/local/lib/libwebsockets.a
 -- Up-to-date: /usr/local/include/libwebsockets.h
 (etc)
  • Signals: At some point I needed to force gdb to pass SIGINT, SIGPIPE... signals to the app instead of gdb, after ssl kept causing Qt to pop a message and break in the debugger. To do so:
       Qt Creator->Options->Debugger->
           [ ] Show a message box when receiving a signal
           Debugger Helper Customization: handle SIGPIPE pass nostop noprint
  • You should be able to install debug builds of libraries into /usr/local (as mentioned above). Older notes if you can't get that going: To debug into an included library that is not installed system-wide:
use Tools->Options->General->Source Paths Map
 source: /home/m/development/causam/git/nop-bigress-client-c/cmake-debug
   that's the COMPLETE PATH TO DEBUG EXE
 target: /home/m/development/causam/git/libwebsockets-master/lib
   at first i thought this would work: /usr/local/lib
   but i did a static build so i needed teh actual exe!  COOL
QT Creator valgrind EASY
Valgrind is easy to use. Just find debugger pane top-left dropdown, switch mode from Debugger to Memcheck, and restart debugger.
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
Library handling in linux
gcc library basics (good to know for autotools and CMake too)
  • The gcc -l command line option specifies a specific library NAME. It will add the rest to give you (eg) lib[NAME].a
  • Specify the library search path with the -L option. Things that you as a user install seem to default to /usr/local/lib
  • This will link myprogram with the static library libfoo.a in the folder /home/me/foo/lib.
       gcc -o myprogram -lfoo -L/home/me/foo/lib myprogram.c

Tools to check library dependencies:

  • ldd [executable]
  • objdump -p /path/to/program | grep NEEDED
  • objdump -x [object.so]
  • readelf -d [exe]
  • sudo pldd <PID>
  • sudo pmap <PID>

Cross Compiling

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
Javascript
RESTFul http
Verbs
  • get - to make requests that are simple -response may be complex
  • post - to push a form or JSON to the server
css
 /* class="first second" */
 .first.second {}
 /* class="first" OR class="second" */
 .first, .second {}
 /* class="first second", or class="second", or class="third second", or class="second third" */
 .second {}
 /* apply to any .child at any depth under .parent */
 .parent .child {}
 /* apply to .child if it is DIRECTLY under .parent */
 .parent > .child {}
SQL
Count records within a range
This groups records into ranges, sorts by them, and gives a count, sweet:
   select count(*), id/1000000 as groupid from AccountHistory group by groupid;

postgres - sqlite - mysql - SQL Server - Robomongo - DBeaver - pgadmin3

Android
Java
Kotlin
Maven
Scala
Python
Go
PHP
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
Bash basics but please prefer node or python :-)
misc
SVN repo move across servers
  • use a tool like VisualSVN to stop SVN server
  • copy the repo's entire svn server directory, eg: c:\svn\Software
  • copy it into the new server under a unique name, eg: c:\svn\NewSoftware
  • use a tool like VisualSVN to restart SVN server

You should now have the new code, accessible as usual from svn. NOTE from Tom: If you move code around, make sure you tag it, then copy the tag, to preserve history (as opposed to directly moving the folder). Weird but true.

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()
             );
Web Services
Firefox Addon development
c++ Create a portable autotools C++ project in linux
(OLD, USE CMAKE NOW)

For anything serious, it's best to clone an existing project's skeleton.

  • main.cpp
  • MVC code
  • nix/copy_from folder
  • make sure .bashrc is configured for boost
  • nix$ bootstrap_autotools_project.sh force release debug
  • set up eclipse according to screenshots in Eclipse
c++ Create a portable C++ project in Visual Studio
(OLD, USE CMAKE NOW)

If you don't have existing code, 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 Reusable and boost include and lib paths: Example if you built boost according to notes below:

Project->Properties->All Configurations->Configuration Properties->VC++ Directories->Include Directories->
   $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\Reusable\c++
INCLUDE: C:\Software Development\boost_1_53_0
LIB: C:\Software Development\boost_1_53_0\stage\lib