вторник, 18 июня 2013 г.

Vala и конфиг в json

Как то в один прекрасный день потребоволось хранить дерево в одной программе на vala. И обуяла меня жажда велосипедостроения (ну за одно и потренироваться в работе с json оказалось неплохо).  В результате родился ниже приведенный класс. Класс умеет проверять наличие ключа (не значения) в json - структуре. Читать с диска и сохранять на диск результат а так же работать с строковыми значениями. Остальные значения допустимые в json  в данном примере не включены из за эконимии места, и строкового типа хватить для показа работоспособности.

Так как используется модуль Json то при сборке проэкта не забудьте указать пакет json-glib-1.0. К примеру строка сборки тестового примера у меня выглядит как vala --pkg json-glib-1.0 -o test_config_d -g
Для разделения веток конфига используется символ "/".
К примеру чтение значение cfg.get_string_value("Key 1/Key 2/Key 3") примененое к json файлу вида
 {
           "Key 1":{"Key 2":{"Key 3":"value 2"},
                          "Key 4":"value 1"
                        }
}
 вернет значение value 2


/**
* LGPL 2
* CAV Inc. 
* cavinc@mail.ru
*/

using Json;

struct leaf {
   int level;
   string value;
}

class Config{
  private Json.Object root_config;

  public Config(){
    root_config=new Json.Object();
  }
  /* читаем файл с конфигом*/
  public void LoadCFG(string fname){
    Json.Parser parser = new Json.Parser ();
    try {
      parser.load_from_file(fname);
      root_config = parser.get_root ().get_object ();
    }  catch (Error e) {
      warning("%s", e.message);
    } 
   
  }
  /* пишем файл с конфигом */
  public void SaveCFG(string fname){
    Json.Generator gen=new Json.Generator();
    Json.Node rt=new Json.Node(NodeType.OBJECT);
    rt.set_object(root_config);
    gen.set_root(rt);

    gen.to_file(fname);

  }

  /* добавляем целый элемент*/
  private Json.Object set_int(string key,int value){
    Json.Object obj=new Json.Object();
    obj.set_int_member(key,value);
    return obj; 
  }
 
 
  private void __set_str(Json.Object obj,string[] key, string value){
     if (key.length!=1){
       if (obj.has_member(key[0])) {
        Json.Node node=obj.get_member(key[0]);
        if (node.get_node_type()==NodeType.OBJECT){
          __set_str(node.get_object(),key[1:key.length],value);
        }
        if (node.get_node_type()==NodeType.VALUE){
          obj.set_string_member(key[0],value); // ???
        }
       }else{
         obj.set_object_member(key[0],new Json.Object());
         __set_str(obj.get_object_member(key[0]),key[1:key.length],value);
       }
      
     } else{
       obj.set_string_member(key[0],value);
     }
  }
  /* добавляем строковой элемент */
  public void set_string_value(string key,string value){
    string[] lkey=key.split("/");
    if (lkey.length==1) {
      root_config.set_string_member(lkey[0],value);
    }else{
      __set_str(root_config,lkey,value);
    }

  }
 

  /* извлекаем строку из объекта */
  private string _get_string(Json.Object obj,string[] key,int index){
    Json.Node node=obj.get_member(key[index]);
    int i=index;
    if (node.get_node_type()==NodeType.OBJECT){
      i+=1;
      return _get_string(node.get_object(),key,i);
    }
    if (node.get_node_type()==NodeType.VALUE){
      return obj.get_string_member(key[index]);
    }
    return "";
  }

  /* читаем строковой элемент */
  public string get_string_value(string key){
    string[] lkey=key.split("/");
    return _get_string(root_config,lkey,0);
  }
 

  /* проверяем наличие ключа на объекте */
  private bool __has_key(Json.Object obj,string key){
    return obj.has_member(key);
  }
  /* рекурсивно обходим ветку останавливаемся если не нашли хотя бы один из ключей */
  private bool __has_key_rec(Json.Object obj,string[] key,int index){
    int i=index;
    if (__has_key(obj,key[index])) {
      Json.Node node=obj.get_member(key[index]);
      if (node.get_node_type()==NodeType.OBJECT){
       i+=1; 
       if (i<=key.length){
         return __has_key_rec(node.get_object(),key,i);
       }
      }
      return true;
    } else{
      return false;
    }
  }

  public bool has_key(string key){
     string[] lkey=key.split("/");
     return __has_key_rec(root_config,lkey,0);
  }
}

Комментариев нет:

Отправить комментарий