7
8
2009
0

json 格式解析

json 是一种基于文本的轻量级的数据格式,类似于 xml,

它简单灵活而且被广泛的语言支持,是一种理想的数据交换格式。

http://json.org/  这里是一个 json 格式说明 以及相关语言解析库的列表。

可以看到对于大多数语言已经有了可以选择的 lib

这个文章接下来将会进行一次重复造轮子的尝试,实现一个c++ 下解析 json 的什么东西。

----------分割线--------------

首先来分析下 json 格式。

json 数据时基于文本的,也就是字符串,以 '\0' 结尾。

它的通用单位(这是我的叫法,原文为value)可以是以下之一:
 

首先看string


类似 c++ 的字符串,由双引号括起的 UNICODE 字符,可以用 '\' 转义。 

>数字 Number

 

和 c++ 的定义一致,除了没有8进制和16进制。

对象 Object

我觉得它更类似于 c ++ 的 pair,由“键” 和 “值” 构成的 “对”

这里的“值”又可以是最开始图中的7种之一。{"action":1}

array 数组

 

数组是若干个 value 的有序集合。[1,2,3,4,5,6]


true false相当于 c++ 中的 bool 类型了。

null空类型。

----------分割线--------------

下面是解析json的代码 未完成。

----------分割线--------------

 

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include <stdexcept>

#include <fstream>

using namespace std;

enum JsonTypeEnum
{
        JsonTypeString = 0,
        JsonTypeNumber,
        JsonTypeBool,
        JsonTypeNull,
        JsonTypeObject,
        JsonTypeArray
};

class JsonString;
class JsonNumber;
class JsonBool;
class JsonNull;
class JsonObject;
class JsonArray;


class JsonBase
{
public:
        virtual ~JsonBase(){};
        virtual string  Serialize() = 0;
        virtual int          Type() = 0;

        JsonBase & operator[](string key);
        JsonBase & operator[](unsigned int index);
};

class JsonString : public JsonBase
{
public:
        ~JsonString()
        {

        }

        string Serialize()
        {
                return "\"" + value + "\"";
        }

        int Type()
        {       
                return JsonTypeString;
        }

        //
        string value;
};

class JsonNumber : public JsonBase
{
public:
        ~JsonNumber()
        {

        }

        string Serialize()
        {               
                stringstream ss;
                ss.precision(10);
                ss << value;
                return ss.str();
        }

        int Type()
        {       
                return JsonTypeNumber;
        }

        //
        double value;
};

class JsonBool : public JsonBase
{
public:
        ~JsonBool()
        {

        }

        string Serialize()
        {
                return value?"true":"false";
        }

        int Type()
        {       
                return JsonTypeBool;
        }

        //
        bool value;
};

class JsonNull : public JsonBase
{
public:
        ~JsonNull()
        {

        }

        string Serialize()
        {     
                return "null";
        }

        int Type()
        {       
                return JsonTypeNull;
        }

        //
};

class JsonObject : public JsonBase
{
public:
        ~JsonObject()
        {             
                for( map<string, JsonBase *>::iterator it = value.begin();
                        it != value.end();
                        it++ )
                {
                        delete (*it).second;
                }

                value.clear();
        }

        string Serialize()
        {       
                string s("");
                s += "{";
                for( map<string, JsonBase *>::iterator it = value.begin();
                        it != value.end();
                        it++ )
                {
                        s += "\"";
                        s += (*it).first;
                        s += "\":";
                        s += (*it).second->Serialize();
                        s += ",";
                }

                s = s.substr(0,s.length()-1);
                s += "}";

                return s;
        }

        int Type()
        {       
                return JsonTypeObject;
        }

        //
        map<string, JsonBase *> value;
};

class JsonArray : public JsonBase
{
public:
        ~JsonArray()
        {
                for( vector<JsonBase *>::iterator it = value.begin();
                        it != value.end();
                        it++ )
                {
                        delete (*it);
                }

                value.clear();
        }

        string Serialize()
        {
                string s("");
                s += "[";
                for( vector<JsonBase *>::iterator it = value.begin();
                        it != value.end();
                        it++ )
                {
                        s += (*it)->Serialize();
                        s += ",";
                }

                s = s.substr(0,s.length()-1);
                s += "]";

                return s;
        }

        int Type()
        {       
                return JsonTypeArray;
        }

        vector<JsonBase *> value;
};


inline bool IsSpaceChar(char c)
{
        if(c==' '|| c=='\t'|| c=='\r'|| c=='\n')return true;
        return false;
}

JsonBase * JsonParse(const char * j)
{
        string t;              // token
        const char * p = j;     // position
        const char * q = NULL;

        while(*p)
        {
                if(IsSpaceChar(*p))while(IsSpaceChar(*p))p++;

                // string
                if(*p=='"')
                {
                        q = p+1;
                        while(*q!='\"')
                                if(!*q++)
                                        return NULL;
                        t = string(p+1,q);
                        q ++;
                        if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                        if(*q)
                                return NULL;
                        JsonString * js = new JsonString;
                        js->value = t;
                        return js;
                }

                // number dec
                if(*p>='0' && *p<='9')
                {
                        bool dot = false;
                        q = p+1;
                        while(*q>='0' && *q<='9' || *q=='.' && (dot=!dot))q++;
                        t = string(p,q);
                        //q ++;
                        if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                        if(*q)
                                return NULL;
                        stringstream ss;
                        ss << t;
                        JsonNumber * jn = new JsonNumber;
                        ss >> jn->value;
                        return jn;
                }

                // bool true
                if(*p == 't'&& *(p+1) == 'r'&& *(p+2)=='u'&& *(p+3)=='e')
                {
                        q = p+4;
                        if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                        if(*q)
                                return NULL;
                        JsonBool * jb = new JsonBool;
                        jb->value = true;
                        return jb;
                }

                // bool false
                if(*p == 'f'&& *(p+1) == 'a'&& *(p+2)=='l'&& *(p+3)=='s'&& *(p+4)=='e')
                {
                        q = p+5;
                        if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                        if(*q)
                                return NULL;
                        JsonBool * jb = new JsonBool;
                        jb->value = false;
                        return jb;
                }

                // null
                if(*p == 'n'&& *(p+1) == 'u'&& *(p+2)=='l'&& *(p+3)=='l')
                {
                        q = p+4;
                        if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                        if(*q)
                                return NULL;
                        JsonNull * jb = new JsonNull;
                        return jb;
                }

                // object
                if(*p == '{')
                {
                        p++;
                        JsonObject * jo = new JsonObject();

                        while(*p)
                        {
                                if(IsSpaceChar(*p))while(IsSpaceChar(*p))p++;   // skip space
                                q = p;
                                bool qt = false;
                               
                                if(*q == '\"')  // key with qt
                                {
                                        bool shift = false;
                                        while(*q++)
                                        {
                                                if(*q == '\"' && !shift)        // 2nd qt without shift
                                                {       
                                                        t = string(p+1, q-1);
                                                        q ++;   // skip the qt
                                                        break;
                                                }
                                        }
                                }
                                else // without qt, so take a word
                                {
                                        while(*q)
                                        {
                                                if(!(*q>='0' && *q<='9' ||
                                                         *q>='a' && *q<='z' ||
                                                         *q>='A' && *q<='Z' ||
                                                         *q == '_' ))
                                                {
                                                        if(p == q)
                                                                return NULL;
                                                        t = string(p, q);
                                                        break;
                                                }
                                                q ++;
                                        }
                                }

                                // now key in token

                                if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;
                                if(*q!=':')
                                        return NULL;
                                q ++;
                                p = q;
                                if(IsSpaceChar(*p))while(IsSpaceChar(*p))p++;
                                q = p;
                                qt = false;
                                int st = 0; // stack
                                while(*q)
                                {
                                        if(*q == '\"')qt = !qt;   
                                        if(*q == '{' && !qt)st ++;  // stack ++
                                        if(*q == '}' && !qt)
                                        {
                                                if(st)st--;                    // stack --
                                                else break;                    // stack empty
                                        }
                                        if(*q == ',' && !qt)
                                        {
                                                if(!st)break;
                                        }
                                        q++;
                                }
                                if(*q == '}')
                                {
                                        string v(p, q);
                                        JsonBase * jb = JsonParse(v.c_str());
                                        if(!jb)
                                                return NULL;
                                        jo->value[t] = jb;
                                        return jo;
                                }       
                                else if(*q == ',')
                                {
                                        string v(p, q);
                                        JsonBase * jb = JsonParse(v.c_str());
                                        if(!jb)
                                                return NULL;
                                        jo->value[t] = jb;
                                        p = q+1;
                                }
                                else
                                {
                                        return NULL;
                                }
                        } // while
                       
                }

                if(*p == '[')
                {
                        p ++;
                        JsonArray * ja = new JsonArray;
                        q = p;     

                        while(*q)
                        {
                                int st1 = 0;    // stack {}
                                int st2 = 0;    // stack []
                                bool qt = false;
                                bool shift = false;

                                if(IsSpaceChar(*q))while(IsSpaceChar(*q))q++;

                                while(*q)
                                {
                                        if(*q == '\"')qt = !qt;

                                        if(*q == '{' && !qt)st1++;
                                        if(*q == '}' && !qt)
                                        {
                                                if(st1)st1--;
                                                else
                                                {
                                                        delete ja;
                                                        return NULL;
                                                }
                                        }
                                        if(*q == '[' && !qt)st2++;
                                        if(*q == ']' && !qt)
                                        {
                                                if(st2)st2--;
                                                if(!st2)
                                                {
                                                        string v(p, q); // j = JsonParse("[1,2,3,4,5,false,\"7\"]");
                                                        JsonBase * jb = JsonParse(v.c_str());
                                                        if(!jb)
                                                        {
                                                                delete ja;
                                                                return NULL;
                                                        }
                                                        ja->value.push_back(jb);
                                                        return ja;
                                                }
                                        }
                                        if(*q == ',' && !qt && !st1 && !st2)
                                        {
                                                string v(p, q);
                                                JsonBase * jb = JsonParse(v.c_str());
                                                if(!jb)
                                                {
                                                        delete ja;
                                                        return NULL;
                                                }
                                                ja->value.push_back(jb);
                                                q ++;
                                                p = q;
                                                break;
                                        }
                                        q++;
                                } // while
                        } // while     

                }

                return NULL;
        }
        return NULL;
}

// -------

JsonBase & JsonBase::operator[](string key)
{
        if (Type() == JsonTypeObject)
        {
                JsonObject * jo = (JsonObject *)this;
                if(jo->value.find(key) == jo->value.end())throw range_error(key + " not found");
                return *jo->value[key];
        }
        else
                throw runtime_error("node is not an object");
}

JsonBase & JsonBase::operator[](unsigned int index)
{
        if (Type() == JsonTypeArray)
        {
                JsonArray * ja = (JsonArray *)this;
                if(index >=ja->value.size())throw range_error("out of rang");
                return *ja->value[index];
        }
        else
                throw runtime_error("node is not an array");

}

// ------


int main()
{
        /*
        ifstream input("test.txt");
        string json;
        string line;

        JsonBase * j;

        while(getline(input,line))
        {
                if(line=="")
                {
                        cout << json << endl;
                        cout << "..." << endl;
                        j = JsonParse(json.c_str());
                        json = "";
                        if(j) cout << j->Serialize() << endl;
                        else  cout << "error" << endl;
                        cout << "----------------" << endl;
                }
                else
                {
                        json += line;
                }
        }
        //*/


        //*
        JsonBase * j;
        j = JsonParse("{a:{d:4,e:[2,3,4,5,6]},b:2,c:3}");
        try{
                cout << (*j)["a"]["e"].Serialize() << endl;
        }catch(exception & e){
                cout << e.what() << endl;
        }
        //*/
        return 0;
}
 

 

 

Category: CXX | Tags: c++ json
6
21
2009
0

切换窗口到前台

 

// 发现那个传说中的 SwitchToThisWindow(Handle,true); 不是那么好用。

{// 这是切换别的窗口到前台   
    HWND    h1 = FindWindow("Notepad", NULL);
    DWORD   t1 = GetWindowThreadProcessId(h1, NULL);
    DWORD   t2 = GetCurrentThreadId();

    if(t1 != t2)
    {
        AttachThreadInput(t1, t2, true);
        BringWindowToTop(h1);
        ShowWindow(h1,SW_SHOW);
        AttachThreadInput(t1, t2, false);
    }
    else
    {
        BringWindowToTop(h1);
    }
}

{// 这是切换自己到前台   
    HWND    h1 = GetForegroundWindow();
    DWORD   t1 = GetWindowThreadProcessId(h1, NULL);
    DWORD   t2 = GetCurrentThreadId();

    if(t1 != t2)
    {
        AttachThreadInput(t1, t2, true);
        BringWindowToTop(Application->Handle);
        ShowWindow(Application->Handle,SW_SHOW);
        AttachThreadInput(t1, t2, false);
    }
    else
    {
        BringWindowToTop(h1);
    }
}
// 一会些个通用点的。

 

 

Category: CXX | Tags: c c++ api windows
5
12
2009
0

开始学习GoogleTest

最近正在做代码重构方面的事情,越来越觉得有必要使用 UnitTest 来提高代码质量

考虑使用现有的轻量 Test 框架,或者自己实现一个比价简单的。

先看看 Google Test,下面是看 GoogleTest Primer 的 Mindmap。

Category: CXX | Tags: test

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com