//////////////////////////////////////////////////////////////////////////
        // HGridWriter
        //////////////////////////////////////////////////////////////////////////

        // Write a grid
        public override void writeGrid(HGrid grid)
        {
            // grid begin
            m_swOut.Write("{\n");

            // meta
            m_swOut.Write("\"meta\": {\"ver\":\"2.0\"");
            writeDictTags(grid.meta, false);
            m_swOut.Write("},\n");

            // columns
            m_swOut.Write("\"cols\":[\n");
            for (int i = 0; i < grid.numCols; i++)
            {
                if (i > 0)
                {
                    m_swOut.Write(",\n");
                }
                HCol col = grid.col(i);
                m_swOut.Write("{\"name\":");
                m_swOut.Write(HStr.toCode(col.Name));
                writeDictTags(col.meta, false);
                m_swOut.Write("}");
            }
            m_swOut.Write("\n],\n");

            // rows
            m_swOut.Write("\"rows\":[\n");
            for (int i = 0; i < grid.numRows; i++)
            {
                if (i > 0)
                {
                    m_swOut.Write(",\n");
                }
                writeDict(grid.row(i));
            }
            m_swOut.Write("\n]\n");

            // grid end
            m_swOut.Write("}\n");
            m_swOut.Flush();
        }
        private void writeDictTags(HDict dict, bool first)
        {
            bool bLocalFirst = first;

            // Is ther a multi-threaded issue here - for a changing size of dict
            for (int i = 0; i < dict.size(); i++)
            {
                if (bLocalFirst)
                {
                    bLocalFirst = false;
                }
                else
                {
                    m_swOut.Write(", ");
                }
                string name = dict.getKeyAt(i, true);
                HVal   val  = dict.get(name, false);
                m_swOut.Write(HStr.toCode(name));
                m_swOut.Write(":");
                writeVal(val);
            }
        }
 private void writeVal(HVal val)
 {
     if (val == null)
     {
         m_swOut.Write("null");
     }
     else if (val is HBool)
     {
         m_swOut.Write(val);
     }
     else if (val is HDict)
     {
         writeDict((HDict)val);
     }
     else if (val is HGrid)
     {
         writeGrid((HGrid)val);
     }
     else
     {
         m_swOut.Write(HStr.toCode(val.toJson()));
     }
 }