RoBoard魔人的機器人日誌

2012/3/26

[RoBoRC第七回] 介紹程式碼parse

本周介紹的RoBoRC程式碼為parse

它是用於demo mode所需文件的開檔及解析內容

再看這篇的同時 資料結構可能要學好 不然可能會不知道它在做什麼事情

parse.h
#ifndef __PARSETOOL_H
#define __PARSETOOL_H
#include "demo.h"

#ifdef __cplusplus
extern "C" {
#endif

int tool_GetItemRBVer(char *str, int *rbidx);
int tool_GetMode(char *str, int *mode_idx);
int tool_GetGroupFRM(char *str, int *frmno);
int tool_InsertACTPool(ACT_NODE **pool, int *idx);
int tool_ParseFile_FRM(DEF_t *def, char *filename);
int tool_ReadFile(char* dirname, DEF_t* def);
int tool_InitDEF(DEF_t *def);
void tool_FreeDEF(DEF_t *def);

#ifdef __cplusplus
}
#endif

#endif




parse.cpp
#include <string.h>
#include <stdlib.h>
#include "errcode.h"
#include "userio.h"
#include "const.h"
#include "fileio.h"
#include "parse.h"

#if defined(RB_LINUX)
    #define _stricmp  strcasecmp
    #define _strnicmp strncasecmp
#elif defined(RB_BC_DOS) || defined(RB_DJGPP)
    #define _stricmp  stricmp
    #define _strnicmp strnicmp
#endif

#define OUT 0
#define IN 1

#define BASE_CMD (2)
#define BASE_ACT (2)
#define BASE_FRM (2)

static char FileDir[255];
static char FullFileDir[511];

static char* GetPath(char* filename);

static int txt_GetItemCH(INI_ITEM_t *item, int *ch, int *value);
static int def_ParseFile_TXT(DEF_t *def, char *filename);

static void frm_InitFRM(FRM_NODE *node);
static int frm_GetGroupFRM(char *str, int *frmno);
static int frm_InsertPool(FRM_NODE **pool, int *idx);
static int frm_GetItemCH(INI_ITEM_t *item, int *ch, int *value);
static int def_ParseFile_FRM(DEF_t *def, char *filename);

static void act_InitACT(ACT_NODE *node);
static int act_GetGroupACT(char *str, int *actno);
static int act_InsertPool(ACT_NODE **pool, int *idx);
static int act_ParseItem(DEF_t *def, INI_ITEM_t *item);
static int act_GetItemMTF(char *str, int *frmno, int *time);
static int act_GetItemPause(char *str, int *time);
static int act_GetItemSnd(char *str, char **filename);
static int def_ParseFile_ACT(DEF_t *def, char *filename);

static void cmd_InitCMD(CMD_NODE *node);
static int cmd_CheckCMD(CMD_NODE *cmd);
static int cmd_InsertPool(CMD_NODE **pool, int *idx);
static int cmd_InsertCMD(DEF_t *def, CMD_NODE *cmd);
static int cmd_GetItemACT(char *str, int *actno);
static int def_ParseFile_CMD(DEF_t *def, char *filename);

static int def_ParseItem_Settings(DEF_t* def, INI_ITEM_t* item);
static int def_GetItemInitFrm(char *str, int *frmno, int *mode);
static int def_GetValueFrmMode(char *str, int *mode);
static int def_ParseItem_Channels(DEF_t* def, INI_ITEM_t* item);
static int def_GetCH(char *str, int *ch);
static int def_GetPINS(char *str, int *pin);
static int def_GetMode(char *str, int *mode_idx);
static int def_GetItemRBVer(char *str, int *rbidx);
static int def_ParseItem_File(DEF_t *def, INI_ITEM_t *item);
static int def_ParseFile_DEF(char* filename, DEF_t* def);

static char* GetPath(char* filename)  //the user should not modify the return string   //合併檔案位置的字
{
// if((int)strcspn(dirname, "/"))
 strcpy(FullFileDir, FileDir); //avoid the case where filepath == DEMOFILE_bufpath
 return strcat(FullFileDir, filename);
}

/*===========================  tool for offset file  ===========================*/
static int txt_GetItemCH(INI_ITEM_t *item, int *ch, int *value)         //抓取channel的編號   與偏移的值
{
 int sign, status;
 char *str;
 sign = 1;
 status = ini_GetCH(item->itemname, ch);              //抓取channel的編號  在fileio.cpp
 if(status != SUCCESS)
  return TXT_OFFSET + INVALID_NAME;              
 if(item->itemvalue[0] == '-'){
  sign = -1;
  str = ini_RemoveSpace(&item->itemvalue[1]);            //清空前後的空白  在fileio.cpp
 }
 else if(item->itemvalue[0] == '+')
  str = ini_RemoveSpace(&item->itemvalue[1]);            
 else
  str = item->itemvalue;
 status = ini_GetValue(str, value);               //將字串轉為數字  在fileio.cpp
 if(status != SUCCESS)
  return TXT_OFFSET + INVALID_VALUE;              
 *value *= sign;                    //正負號
 return SUCCESS;
}

static int def_ParseFile_TXT(DEF_t *def, char *filename)          //去改變各個channel的偏移值
{
 int status = SUCCESS;
 int ch, value;
 unsigned long flag = 0L;
 INI_ITEM_t item;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return TXT_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容  改為INI_ITEM_t形式
 {
  status = txt_GetItemCH(&item, &ch, &value);
  if(status == SUCCESS){
   if((flag & (1L << ch)) != 0) //check repeat           //檢查是否重複用過
    return TXT_REPEAT_CH;
   def->channel[ch].offset = value;             //依照讀取到的內容改變def的channel[].offset
   flag |= (1L << ch);                 //用過的把該bit改為1
  }
 }

 ini_FileClose(fp);
 return status;
}

/*===========================  tool for frm file  ===========================*/
static void frm_InitFRM(FRM_NODE *node)               //預設frm的值
{
 int i;
 node->frmno = -1;
 for(i = 0; i < 32; i++)
  node->frm[i] = 0L;
 node->next = NULL;
}

static int frm_GetGroupFRM(char *str, int *frmno)            //取得frame的編號
{
 int status;
 status = ini_ParseNumber_pre(str, "Frame", frmno);           //取得frame的編號
 if(status == SUCCESS)
  return status;
 return FRM_OFFSET + INVALID_GROUP;
}

static int frm_GetItemCH(INI_ITEM_t *item, int *ch, int *value)         //取得各個channel的位置的值
{
 int status;
 status = ini_GetCH(item->itemname, ch);              //取得channel的編號
 if(status != SUCCESS)
  return FRM_OFFSET + INVALID_NAME;
 status = ini_GetValue(item->itemvalue, value);            //取得位置的值
 if(status != SUCCESS)
  return FRM_OFFSET + INVALID_VALUE;
 return SUCCESS;

}

static int frm_InsertPool(FRM_NODE **pool, int *idx)           //倍增空間
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_FRM == 0){
  size = *idx * 2;
  *pool = (FRM_NODE *)realloc(*pool, sizeof(FRM_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   frm_InitFRM(&(*pool)[i]);
 }
 return SUCCESS;
}

static int def_ParseFile_FRM(DEF_t *def, char *filename)
{
 #define OUT 0
 #define IN 1
 int flag = OUT;
 int status = SUCCESS;
 int ch, value;
 unsigned long flagch = 0L;
 INI_ITEM_t item;
 FILEIO *fp;
 FRM_NODE *node;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return FRM_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item)) != INI_FILEEND)     //讀取內容  改為INI_ITEM_t形式
 {
  switch(item.type){                  //依照type來分別做
   case INI_GROUPTITLE:                //如果是title    即為[Frame N]
    if(flag == OUT)                 
     flag = IN;                 //標記未讀取過改為已讀取過
    else
     status = frm_InsertPool(&def->frmpool, &def->frmidx);      //有需要時倍增節點空間
    flagch = 0L;
    node = &def->frmpool[def->frmidx];
    status = frm_GetGroupFRM(item.itemname, &node->frmno);       //取得frame的編號
    break;
   case INI_GROUPITEM:                 //如果是item    即為channel1 = 1300
    if(flag == OUT)                 //如果標記為未讀過  代表沒有title
     status = FRM_OFFSET + NOGROUP_ITEM;
    if(status == SUCCESS)
     status = frm_GetItemCH(&item, &ch, &value);         //取得item的channel編號
    if(status == SUCCESS){
     if((flagch & (1L << ch)) != 0)            //防止重複讀取用
      return FRM_REPEAT_CH;
     node->frm[ch] = value;              //把值填入節點中
     flagch |= (1L << ch);
    }
    break;
   case INI_UNKNOWNITEM:                //讀到不知明物體
    return FRM_OFFSET + UNKNOWN_LINE;
  }
 }
 ini_FileClose(fp);
 if(status == SUCCESS)
  status = frm_InsertPool(&def->frmpool, &def->frmidx);
 return status;
}

/*===========================  tool for act file  ===========================*/
static void act_InitACT(ACT_NODE *node)               //預設act的值
{
 node->actno = -1;
 node->frm = NULL;
 node->next = NULL;
 node->time = -1;
 node->data.frmno = -1;
}

static int act_GetItemSnd(char *str, char **filename)           //複製檔案名稱   聲音用
{
 int i;
 i = (int)strlen(str);
 if(i == 0)
  return ACT_OFFSET + INVALID_VALUE;
 *filename = (char *)malloc(sizeof(char) * (i+1));
 if(filename == NULL)
  return MEMORY_ERROR;
 strcpy(*filename, str);
 return SUCCESS;
}

static int act_GetItemPause(char *str, int *time)            //抓出時間的值
{
 int status;
 status = ini_ParseNumber_post(str, "ms", time);
 if(status != SUCCESS)
  return ACT_OFFSET + INVALID_VALUE;
 return status;
}

static int act_GetItemMTF(char *str, int *frmno, int *time)          //讀取MoveToFrame
{
 char *str1, *str2;
 int status;
 status = ini_DivideString(str, &str1, &str2, ",");           //分割字串以","為中間點
 if(status == INI_DIVIDE_FAIL)
  return ACT_OFFSET + INVALID_VALUE;
 status = ini_GetValue(str1, frmno);               //抓取str1的值  即為frame的編號
 if(status != SUCCESS)
  return ACT_INVALID_FRMNO;
 status = ini_ParseNumber_post(str2, "ms", time);           //抓取str2的值  即為時間的值
 if(status != SUCCESS)
  return ACT_INVALID_TIME;
 return status;
}

static int act_ParseItem(DEF_t *def, INI_ITEM_t *item)           //分辨指令
{
 ACT_NODE *node;
 node = &def->actpool[def->actidx];
 int status;
 if(ini_IsItem(item, "MoveToFrame")){
  node->type = ACT_PLAYFRAMENO;               //如果指令為MoveToFrame  則要讀取兩個值
  status = act_GetItemMTF(item->itemvalue, &node->data.frmno, &node->time);
 }
 else if(ini_IsItem(item, "Pause")){
  node->type = ACT_PAUSE;                 //如果指令為Pause  則要讀一個值
  status = act_GetItemPause(item->itemvalue, &node->time);
 }
 else if(ini_IsItem(item, "playsnd")){
  node->type = ACT_PLAYSND;                //如果指令為playsnd     則要給檔案名稱
  status = act_GetItemSnd(item->itemvalue, &node->data.filename);
 }
 else                      //其他沒看過的指令就回傳錯誤訊息
  status = ACT_OFFSET + INVALID_NAME;
 if(status == SUCCESS)
  status = act_InsertPool(&def->actpool, &def->actidx);
 return status;
}

static int act_InsertPool(ACT_NODE **pool, int *idx)           //倍增節點
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_ACT == 0){
  size = *idx * 2;
  *pool = (ACT_NODE *)realloc(*pool, sizeof(ACT_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   act_InitACT(&(*pool)[i]);
 }
 return SUCCESS;
}

static int act_GetGroupACT(char *str, int *actno)            //取得Action編號
{
 int status;
 status = ini_ParseNumber_pre(str, "Action", actno);           //取得Action編號
 if(status == SUCCESS)
  return status;
 return ACT_OFFSET + INVALID_GROUP;
}

static int def_ParseFile_ACT(DEF_t *def, char *filename)
{
 #define OUT 0
 #define IN 1
 int flag = OUT;
 int status = SUCCESS;
 INI_ITEM_t item;
 ACT_NODE *node;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return ACT_OFFSET + OPEN_FILE_FAIL;
 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item)) != INI_FILEEND)     //讀取內容   改為INI_ITEM_t形式
 {
  node = &def->actpool[def->actidx];
  switch(item.type){                  //依型態做事
   case INI_GROUPTITLE:                //如果是title   即為[Action N]
    if(flag == OUT) 
     flag = IN;                 //標記改為已讀取
    status = act_GetGroupACT(item.itemname, &node->actno);       //讀取Action的編號
    if(status == SUCCESS){
     node->type = ACT_START;              //節點type改為ACT_START
     status = act_InsertPool(&def->actpool, &def->actidx);
    }
    break;
   case INI_GROUPITEM:                 //如果是item
    if(flag == IN)                 //如果標記為未讀過  代表沒有title
     status = act_ParseItem(def, &item);           //要依照指令去分別編寫
    else
     status = ACT_OFFSET + NOGROUP_ITEM;
    break;
   case INI_UNKNOWNITEM:
    return ACT_OFFSET + UNKNOWN_LINE;
  }
 }
 ini_FileClose(fp);
// follow code are move to def_ParseFile_DEF for not only one act file case
// node = &def->actpool[def->actidx];
// node->type = ACT_START;
// node->actno = -1;
// status = act_InsertPool(&def->actpool, &def->actidx);
 return status;
}

/*===========================  tool for cmd file  ===========================*/
static void cmd_InitCMD(CMD_NODE *node)               //預設cmd的值
{
 node->actno = -1;
 node->command = -1;
 node->name[0] = '\0';
 node->next = NULL;

}

static int cmd_GetItemCMD(char *str, int *cmd)             //讀取cmd的值
{
 int i;
 if(strlen(str) == 1){                  //先判斷指令是否為正常的英文
  if(str[0] >= 'A' && str[0] <= 'Z')
   *cmd = str[0];
  else if(str[0] >= 'a' && str[0] <= 'z')
   *cmd = str[0] - 'a' + 'A';
  else
   return CMD_OFFSET + INVALID_VALUE;
 }
 else{                      //或是特殊的按鍵   EX: F1
  for(i = 0; i < NUM_SKEY; i++){
   if(_stricmp(str, SKey[i].name) == 0)
    break;
  }
  if(i == NUM_SKEY)                  //全部找完   還不在範圍內  代表有誤
   return CMD_OFFSET + INVALID_VALUE;
  *cmd = SKey[i].value;                 //將指令改為特定的值
 }
 return SUCCESS;
}

static int cmd_GetItemACT(char *str, int *actno)            //取得act的編號
{
 int status;
 status = ini_GetValue(str, actno);               //取得act的編號
 if(status != SUCCESS)
  return CMD_OFFSET + INVALID_VALUE;
 return SUCCESS;
}

static int cmd_CheckCMD(CMD_NODE *cmd)               //檢查有沒有缺少的
{
 if(cmd->actno == -1)
  return CMD_NO_ACTNO;
 if(cmd->command == -1)
  return CMD_NO_CMD;
 if(strlen(cmd->name) == 0)
  return CMD_NO_NAME;
 return SUCCESS;
}

static int cmd_InsertPool(CMD_NODE **pool, int *idx)           //倍增節點
{
 int i;
 int size;
 *idx += 1;
 if(*idx % BASE_CMD == 0){
  size = *idx * 2;
  *pool = (CMD_NODE *)realloc(*pool, sizeof(CMD_NODE) * size);
  if(*pool == NULL)
   return MEMORY_ERROR;
  for(i = *idx; i < size; i++)
   cmd_InitCMD(&(*pool)[i]);
 }
 return SUCCESS;
}

static int cmd_InsertCMD(DEF_t *def, CMD_NODE *cmd)            //要插入新指令時用
{
 int status = SUCCESS;
 status = cmd_CheckCMD(cmd);                 //檢查有沒有少東西
 if(status == SUCCESS)
  status = cmd_InsertPool(&def->cmdpool, &def->cmdidx);         //倍增節點用
 return status;
}

static int def_ParseFile_CMD(DEF_t *def, char *filename)
{
 int status = SUCCESS;
 int flag = OUT;
 CMD_NODE *cmd;
 INI_ITEM_t item;
 FILEIO *fp;

 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return CMD_OFFSET + OPEN_FILE_FAIL;
 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容   改為INI_ITEM_t形式
 {
  switch(item.type){                  //依型態判斷要做什麼
   case INI_GROUPTITLE:                //如果是title   即為[Command]
    if(ini_IsGroup(&item, "command")){            //判斷title
     if(flag == IN) // insert before cmd           //有新增過的話
      status = cmd_InsertCMD(def, cmd);          
     else
      flag = IN;
    }
    else
     return CMD_OFFSET + INVALID_GROUP;
    cmd = &def->cmdpool[def->cmdidx];
    break;
   case INI_GROUPITEM:                 //如果是item   即name = XXX   command = XX...
    if(flag == OUT)                 //沒標記過代表沒有Title  格式有誤
     return CMD_OFFSET + NOGROUP_ITEM;
    if(ini_IsItem(&item, "name"))             
     strcpy(cmd->name, item.itemvalue);           //name只要複製名稱就好
    else if(ini_IsItem(&item, "action"))           
     status = cmd_GetItemACT(item.itemvalue, &cmd->actno);      //action   要取得action的編號
    else if(ini_IsItem(&item, "command"))
     status = cmd_GetItemCMD(item.itemvalue, &cmd->command);      //command   要讀出按鍵的值
    else
     return CMD_OFFSET + INVALID_NAME;
    break;
   case INI_UNKNOWNITEM:
    return CMD_OFFSET + UNKNOWN_LINE;
  }
 }
 if(status == SUCCESS)
  status = cmd_InsertCMD(def, cmd);
 ini_FileClose(fp);
 return status;
}

/*===========================  tool for def file  ===========================*/

static int def_GetCH(char *str, int *ch)              //抓channel的編號
{
 int status;
 status = ini_GetCH(str, ch);                //抓channel的編號
 if(status == SUCCESS)
  return SUCCESS;
 return DEF_CH_INVALID_CH;
}

static int def_GetPINS(char *str, int *pin)              //抓pin的編號
{
 int status;
 status = ini_ParseNumber_pre(str, "S", pin);            //抓pin的編號
 *pin -= 1;                     //判斷重複用
 if(status == SUCCESS)
 if((*pin <= 31) && (*pin >= 0))                //判斷要為S0 ~ S31
  return SUCCESS;
 return DEF_CH_INVALID_PIN;
}

static int def_GetMode(char *str, int *mode_idx)
{
 int i;
 for(i = 0; i < NUM_SERVO; i++){                //執行NUM_SERVO個servo名稱
  if(_stricmp(str, Servo[i].name) == 0)             //判斷輸入的servo是否正確
   break;
 }
 if(i < NUM_SERVO){                   
  *mode_idx = i;
  return SUCCESS;
 }
 else                      //如果不是中途跳出   代表輸入的內容不在範圍內
  return DEF_CH_INVALID_MODE;
}

static int def_ParseItem_Channels(DEF_t* def, INI_ITEM_t* item)         //抓channels group的內容
{
 int status;
 int ch, pin, mode_idx;
 char *str1, *str2;
 status = def_GetCH(item->itemname, &ch);             //抓channel 的編號

 if(status == SUCCESS)
  status = ini_DivideString(item->itemvalue, &str1, &str2, ",");       //以","分割字串
 if(status == SUCCESS)
  status = def_GetPINS(str1, &pin);              //抓pin的編號
 if(status == SUCCESS)
  status = def_GetMode(str2, &mode_idx);             //抓模式的字串
 if(status == SUCCESS){
  if(def->channel[ch].pin != -1)               //判斷重複用
   return DEF_CH_REPEAT_CH;
  if((def->usedChannels & (1L << pin)) != 0)            //判斷重複用    
   return DEF_CH_REPEAT_PIN;
  def->usedChannels |= (1L << pin);              //把要用的channel加進去
  def->channel[ch].pin = pin;
  def->channel[ch].mode_idx = mode_idx;
 }
 return status;
}

static int def_GetValueFrmMode(char *str, int *mode)           //判斷字串 true/false
{
 if((str == NULL) || (_stricmp(str, "false") == 0))
  *mode = INIT_FRM_FALSE;
 else if(_stricmp(str, "true") == 0)
  *mode = INIT_FRM_TRUE;
 else          
  return DEF_SET_INVALID_MODE;
 return SUCCESS;
}

static int def_GetItemRBVer(char *str, int *rbidx)            //抓取RB型號
{
 int i;
 for(i = 0; i < NUM_RBVer; i++){                //執行NUM_RBVer次   即RB型號個數
  if(_stricmp(str, RBVer[i].name) == 0)
   break;
 }
 if(i < NUM_RBVer){
  *rbidx = i;
  return SUCCESS;
 }             
 else                      //如果不是中途跳出   代表輸入的內容不在範圍內
  return DEF_SET_OFFSET + INVALID_VALUE;
}

static int def_GetItemInitFrm(char *str, int *frmno, int *mode)         //抓取HomeFrame的內容  
{
 int status;
 char *str1, *str2;
 status = ini_DivideString(str, &str1, &str2, ",");           //以","作分隔分開字串
 if(status == INI_DIVIDE_FAIL){
  str1 = str;
  str2 = NULL;
 }
 status = ini_GetValue(str1, frmno);               //取得frm編號
 if(status != SUCCESS)
  return DEF_SET_INVALID_FRMNO;
 status = def_GetValueFrmMode(str2, mode);             //判斷字串 true/false
 return status;
}

static int def_ParseItem_Settings(DEF_t* def, INI_ITEM_t* item)         //判斷settings group的內容   以便去做各種事情
{
 int status = SUCCESS;

 if (ini_IsItem(item, "initaction") == true){            //判斷item是否為initaction
  status = ini_GetValue(item->itemvalue, &def->initact);         //抓取值
  if(status != SUCCESS)
   return DEF_SET_OFFSET + INVALID_VALUE;
 }
 else if(ini_IsItem(item, "homeframe") == true)            //判斷item是否為homeframe
  status = def_GetItemInitFrm(item->itemvalue, &def->initfrm, &def->initfrm_mode);  //抓取HomeFrame的內容 
 else if(ini_IsItem(item, "roboard") == true)            //判斷item是否為roboard 
  status = def_GetItemRBVer(item->itemvalue, &def->rbidx);        //抓取RB型號
 else
  status = DEF_SET_OFFSET + INVALID_NAME;

 return status;
}

static int def_ParseItem_File(DEF_t *def, INI_ITEM_t *item)          //中繼站   來什麼就去開什麼黨來讀
{
 int status;

 if (ini_IsItem(item, "cmd") == true)
  status = def_ParseFile_CMD(def, item->itemvalue);
 else if(ini_IsItem(item, "act") == true)
  status = def_ParseFile_ACT(def, item->itemvalue);
 else if(ini_IsItem(item, "frame") == true)
  status = def_ParseFile_FRM(def, item->itemvalue);
 else if(ini_IsItem(item, "offset") == true)
  status = def_ParseFile_TXT(def, item->itemvalue);
 else
  status = DEF_FIL_OFFSET + INVALID_NAME;
 return status;
}


static int def_ParseFile_DEF(char* filename, DEF_t* def)
{
    #define DEFGROUP_INFO      (0)
    #define DEFGROUP_FILES     (1)
    #define DEFGROUP_CHANNELS  (2)
    #define DEFGROUP_SETTINGS  (3)
 #define DEFGROUP_UNSET     (4)
 FILEIO *fp;
    INI_ITEM_t item;
 int gflag = DEFGROUP_UNSET;
 int status = SUCCESS;

// demofile_InitialDEF(def);
 fp = ini_FileOpen(GetPath(filename));              //開啟檔案
 if(fp == NULL)
  return DEF_OFFSET + OPEN_FILE_FAIL;

 while ((status == SUCCESS) && (ini_ReadNextItem(fp, &item) != INI_FILEEND))     //讀取內容   並轉成INI_ITEM_t結構內容
 {
  switch(item.type)
        {
            case INI_GROUPTITLE:                //如果是title   即為[Info]...
    if (ini_IsGroup(&item, "Info") == true)
     gflag = DEFGROUP_INFO;         
    else if (ini_IsGroup(&item, "Files") == true)
     gflag = DEFGROUP_FILES;         
    else if (ini_IsGroup(&item, "Channels") == true)
     gflag = DEFGROUP_CHANNELS;
    else if (ini_IsGroup(&item, "Settings") == true)
     gflag = DEFGROUP_SETTINGS;
    else
     status = DEF_OFFSET + INVALID_GROUP;
                break;
            case INI_GROUPITEM:                 //如果是item   即為 XXX = XXXX...
    switch(gflag)                 //依照gflag去分別看
    {
     case DEFGROUP_CHANNELS:
      status = def_ParseItem_Channels(def, &item);
      break;
     case DEFGROUP_SETTINGS:
      status = def_ParseItem_Settings(def, &item);
      break;
     case DEFGROUP_FILES:
      status = def_ParseItem_File(def, &item);
      break;
     case DEFGROUP_INFO:
      break;
     case DEFGROUP_UNSET:
      status = DEF_OFFSET + NOGROUP_ITEM;

    }
                break;
   case INI_UNKNOWNITEM:
    if(gflag != DEFGROUP_INFO)
    status = DEF_OFFSET + UNKNOWN_LINE;
    break;
        } //end switch(item...
    } //end while(ini_...

 ini_FileClose(fp);                   //關閉檔案
 // Set "end" for last action 
 if(status == SUCCESS){
  def->actpool[def->actidx].type = ACT_START;
  def->actpool[def->actidx].actno = -1;
  status = act_InsertPool(&def->actpool, &def->actidx);
 }
 return status;

}

/*===========================  tool function   ===========================*/
int tool_GetItemRBVer(char *str, int *rbidx)
{
 return def_GetItemRBVer(str, rbidx);
}

int tool_GetMode(char *str, int *mode_idx)
{
 return def_GetMode(str, mode_idx);
}

int tool_GetGroupFRM(char *str, int *frmno)
{
 return frm_GetGroupFRM(str, frmno);
}

int tool_InsertACTPool(ACT_NODE **pool, int *idx)
{
 return act_InsertPool(pool, idx);
}

int tool_ParseFile_FRM(DEF_t *def, char *filename)
{
 strcpy(FileDir, "");
 return def_ParseFile_FRM(def, filename);
}

int tool_ReadFile(char* dirname, DEF_t* def)
{
 int i;
 char filename[255];
 i = (int)strlen(dirname);

 strcpy(FileDir, dirname);
 if(FileDir[i-1] != '/')
  strcat(FileDir, "/");

 while (( i = (int)strcspn(dirname, "/\\")) != strlen(dirname))
  dirname = &dirname[i + 1];
 strcpy(filename, dirname);
 strcat(filename, ".def");
 return def_ParseFile_DEF(filename, def);
}

int tool_InitDEF(DEF_t *def)                 //初始化DEF_t的值
{
 int i;

 def->usedChannels = 0L;
 def->initact = -1;
 def->initfrm = -1;
 def->initfrm_mode = INIT_FRM_FALSE;
 def->inithome = NULL;
 def->initactnode = NULL;
 for (i=0; i<32; i++) {
  def->channel[i].pin = -1;
  def->channel[i].mode_idx = 0;
  def->channel[i].offset = 0;
 }

 def->actidx = 0;
 def->actpool = (ACT_NODE *)malloc(sizeof(ACT_NODE) * BASE_ACT);
 def->acttable = NULL;

 def->cmdidx = 0;
 def->cmdpool = (CMD_NODE *)malloc(sizeof(CMD_NODE) * BASE_CMD);
 def->cmdtable = NULL;

 def->frmidx = 0;
 def->frmpool = (FRM_NODE *)malloc(sizeof(FRM_NODE) * BASE_FRM);
 def->frmtable = NULL;

 if((def->actpool == NULL) || (def->cmdpool == NULL) || (def->frmpool == NULL))
  return MEMORY_ERROR;
 for(i = 0; i < BASE_ACT; i++)
  act_InitACT(&def->actpool[i]);
 for(i = 0; i < BASE_CMD; i++)
  cmd_InitCMD(&def->cmdpool[i]);
 for(i = 0; i < BASE_FRM; i++)
  frm_InitFRM(&def->frmpool[i]);
 return SUCCESS;
}

void tool_FreeDEF(DEF_t *def)                 //刪掉創出來的空間
{
 free(def->actpool);
 free(def->cmdpool);
 free(def->frmpool);
 free(def->acttable);
 free(def->cmdtable);
 free(def->frmtable);
}


Share:

2012/3/19

[RoBoRC第六回] 介紹程式碼userio

這一次要介紹的是userio

userio主要是使用於接收key的值及一些常用的函式

什麼?

覺得接收key很簡單?

當然...在一平台下會認為接收key很簡單

但這userio可是適用於各個平台!

不管是LINUX,WINCE...等等

幾乎都可以執行

接下來就來研究看看吧!



userio.h
#ifndef __USERIO_H
#define __USERIO_H

#include "defines.h"


#ifdef __cplusplus
extern "C" {
#endif

//MESSAGE
bool msg_SetLogFile(char* logfile);
void msg_CloseLogFile(void);

void showmsg(const char* fmt, ...);


//KEYBOARD:
void keyboard_init(int type);
#define KEYBOARD_STD    (1)
#define KEYBOARD_ADV    (2)

void keyboard_close(void);

unsigned keyboard_getkey(void);
unsigned keyboard_waitkey(void);
#define KBENTER         (0x000d)
#define KBTAB           (0x0009)
#define KBESC           (0x001b)
#define KBBACKSPACE     (0x0008)
#define KBSPACE         (0x0020)

#define KBLEFT          (0x0025)
#define KBRIGHT         (0x0027)
#define KBUP            (0x0026)
#define KBDOWN          (0x0028)

#define KBHOME          (0x0024)
#define KBEND           (0x0023)
#define KBPGUP          (0x0021)
#define KBPGDN          (0x0022)

#define KBINS           (0x002d)
#define KBDEL           (0x002e)

#define KBF1            (0x0070)
#define KBF2            (0x0071)
#define KBF3            (0x0072)
#define KBF4            (0x0073)
#define KBF5            (0x0074)
#define KBF6            (0x0075)
#define KBF7            (0x0076)
#define KBF8            (0x0077)
#define KBF9            (0x0078)
#define KBF10           (0x0079)
#define KBF11           (0x007a)
#define KBF12           (0x007b)

#define KBSHIFT         (0x0010)
#define KBLSHIFT        (0x00a0)
#define KBRSHIFT        (0x00a1)
#define KBCTRL          (0x0011)
#define KBLCTRL         (0x00a2)
#define KBRCTRL         (0x00a3)
#define KBALT           (0x0012)
#define KBLALT          (0x00a4)
#define KBRALT          (0x00a5)

#ifdef __cplusplus
}
#endif
#endif





userio.cpp
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#ifdef USE_RBDLL
 #define  USE_COMMON
 #include <roboard_dll.h>
#else
 #define  USE_COMMON
 #include <roboard.h>
#endif
#include "userio.h"


#if defined(RB_LINUX)
    #include <unistd.h>
    //#include <termios.h>
    #include <ncurses.h>
#elif defined(RB_MSVC_WIN32)
    #include <windows.h>
    #include <conio.h>
#elif defined(RB_MSVC_WINCE)
    #include <windows.h>
#elif defined(RB_BC_DOS) || defined(RB_DJGPP)
    #include <conio.h>
    #define _getch getch
    #define _kbhit kbhit
#endif

#define KEYBOARD_NOUSE  (0)
static int keyboard_inUse = KEYBOARD_NOUSE;



/*****************  Common Message Functions  ******************/
static FILE* MSG_outputDevice = stdout;

bool msg_SetLogFile(char* logfile) {
    msg_CloseLogFile();

 if (logfile == NULL)                  //logfile為NULL  就把MSG_outputDevice也改為NULL  回傳true
 {
  MSG_outputDevice = NULL;
  return true;
 }

 if ((MSG_outputDevice = fopen(logfile, "w")) != NULL) return true;       //如果開啟logfile成功  回傳true

 MSG_outputDevice = stdout;
    return false;
}

void msg_CloseLogFile(void) {                 //確定MSG_outputDevice為stdout
    if ((MSG_outputDevice != stdout) && (MSG_outputDevice != NULL))
        fclose(MSG_outputDevice);

 MSG_outputDevice = stdout;
}


#ifdef _MANAGED
 #pragma managed(push, off)
#endif
void showmsg(const char* fmt, ...) {               //show message在螢幕上
    char buf[256];
    va_list args;

 va_start(args, fmt);
 vsprintf(buf, fmt, args);
 va_end(args);

    #ifdef RB_LINUX
        if ((keyboard_inUse == KEYBOARD_STD) && (MSG_outputDevice == stdout))
        {
            printw("%s", buf);
            refresh();
            return;
        }
    #endif

 fprintf(MSG_outputDevice, "%s", buf);
    fflush(MSG_outputDevice);
}
#ifdef _MANAGED
 #pragma managed(pop)
#endif
/*-------------- end of Common Message Functions --------------*/



/*****************  Common Keyboard Functions  *****************/
static unsigned keymap[512] = 
    {
        0, 0, 0, 0, 0, 0, 0, 0, KBBACKSPACE, KBTAB, 0, 0, 0, KBENTER, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBESC, 0, 0, 0, 0,
        KBSPACE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',   0,   0,   0,   0,   0,   0,
          0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',   0,  0 ,   0,   0,   0,
          0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',   0,  0 ,   0,   0,   0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBF1, KBF2, KBF3, KBF4, KBF5,
        KBF6, KBF7, KBF8, KBF9, KBF10, 0, 0, KBHOME, KBUP, KBPGUP, 0, KBLEFT, 0, KBRIGHT, 0, KBEND,
        KBDOWN, KBPGDN, KBINS, KBDEL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, KBF11, KBF12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };


void keyboard_init(int type) {                 //init keyboard
    if (keyboard_inUse != KEYBOARD_NOUSE) return; else keyboard_inUse = type;
    switch (type)
    {
        case KEYBOARD_STD:
            #if defined(RB_LINUX)
                initscr();
                cbreak();
                nonl();
                noecho();
                scrollok(stdscr, TRUE);
                nodelay(stdscr, TRUE);
                intrflush(stdscr,FALSE);
                keypad(stdscr,TRUE);
                refresh();
            #elif defined(RB_MSVC_WINCE)
    keyboard_getkey();
            #endif
   return;
        case KEYBOARD_ADV:
   return;
    }

 keyboard_inUse = KEYBOARD_NOUSE;
}

void keyboard_close(void) {                  //close keyboard
    if (keyboard_inUse == KEYBOARD_NOUSE) return;

    switch (keyboard_inUse)
    {
        case KEYBOARD_STD:
            #if defined(RB_LINUX)
                endwin();
            #elif defined(RB_MSVC_WINCE)
                fflush(stdin);
            #endif
            break;
        case KEYBOARD_ADV:
            break;
    }

    keyboard_inUse = KEYBOARD_NOUSE;
}


static unsigned keyboard_getkey_std(void) {              //讀取keyboard的值   適用各種平台
    #if defined(RB_LINUX)
        int c = getch();
        
        if ((c == 27) || ((c >= 0x20) && (c <= 0x7f))) return keymap[c];
    
        switch (c)
        {
            case KEY_BACKSPACE:
            case 127: //some linux maps BACKSPACE to delete (127)
                return KBBACKSPACE;
            case KEY_ENTER:
            case '\r':
                return KBENTER;
            case '\t':
                return KBTAB;
    
            case KEY_UP:    return KBUP;
            case KEY_DOWN:  return KBDOWN;
            case KEY_LEFT:  return KBLEFT;
            case KEY_RIGHT: return KBRIGHT;
    
            case KEY_HOME:  return KBHOME;
            case KEY_END:   return KBEND;
            case KEY_NPAGE: return KBPGDN;
            case KEY_PPAGE: return KBPGUP;
    
            case KEY_IC:    return KBINS;
            case KEY_DC:    return KBDEL;

            case KEY_F(1):  return KBF1;
            case KEY_F(2):  return KBF2;
            case KEY_F(3):  return KBF3;
            case KEY_F(4):  return KBF4;
            case KEY_F(5):  return KBF5;
            case KEY_F(6):  return KBF6;
            case KEY_F(7):  return KBF7;
            case KEY_F(8):  return KBF8;
            case KEY_F(9):  return KBF9;
            case KEY_F(10): return KBF10;
            case KEY_F(11): return KBF11;
            case KEY_F(12): return KBF12;

            case ERR:       return 0;
        }
        
        return 0;
    #elif defined(RB_MSVC_WINCE)
        static bool          vkeystat[256] = {false};
        static unsigned long vkeytime[256] = {0L};

        int c;
        unsigned firstkey = 0;
        
        for (c=0; c<512; c++)
        {
            if ((keymap[c] == 0) || ((c >= 'a') && (c <= 'z'))) continue;

            if ((GetAsyncKeyState(keymap[c]) & 0x8000) == 0)
                vkeystat[keymap[c]] = false;
            else
            if (vkeystat[keymap[c]] == false)
            {
    vkeystat[keymap[c]] = true;
                vkeytime[keymap[c]] = timer_nowtime() + 800L;
                if (firstkey == 0) firstkey = keymap[c];
            }
   else
   if (timer_nowtime() > vkeytime[keymap[c]])
   {
                vkeytime[keymap[c]] = timer_nowtime() + 90L;
                if (firstkey == 0) firstkey = keymap[c];
   }
        }

        return firstkey;
    #else
        int c;
        
        if (!_kbhit()) return 0; else c = _getch();

        if ((c != 0) && (c != 0xe0))
            return keymap[c];
        else
            return keymap[_getch() + 256];
    #endif
}


unsigned keyboard_getkey(void) {                //根據keyboard的狀態來回傳
    switch (keyboard_inUse)
    {
  case KEYBOARD_STD:
            return keyboard_getkey_std();
        case KEYBOARD_ADV:
         return 0;
    }//end switch (keyboard_inUse)

 return 0;
}

unsigned keyboard_waitkey(void) {                //等待按完一個按鍵才繼續動作
    unsigned c;

    if (keyboard_inUse == KEYBOARD_NOUSE) return 0;

 while ((c = keyboard_getkey()) == 0);
 return c;
}
/*----------------- end of Keyboard Functions -----------------*/

Share:

2012/3/12

[RoBoRC第五回] 介紹程式碼const & errcode

本周的RoBoRC介紹兩個程式

const 以及 errcode

別緊張

這兩個都沒有很難

本周就輕鬆一下吧~

const.h
這裡主要是定義結構用

#ifndef __CONST_H
#define __CONST_H

#define NUM_SERVO (17)
#define NUM_RBVer (7)
#define NUM_SKEY  (17)

typedef struct _strint_{
 const char* name;
 unsigned int value;
}STRINT;

typedef struct _servo_{
 const char* name;
 unsigned int value;
 bool feedback;
}_SERVO;

typedef _SERVO SERVO[NUM_SERVO];
typedef STRINT SKEY[NUM_SKEY];
typedef STRINT RBVER[NUM_RBVer];

extern SERVO Servo;
extern RBVER RBVer;
extern SKEY SKey;

#endif



const.cpp
剛剛定義結構的內容   有servo,RBver等

#include "rcservo.h"
#include "userio.h"
#include "common.h"
#include "const.h"

 
_SERVO Servo[] = {
    {"DEFAULT", RCSERVO_SERVO_DEFAULT, true},
    {"DEFAULT_NOFB", RCSERVO_SERVO_DEFAULT_NOFB, false},
    {"KONDO_KRS786", RCSERVO_KONDO_KRS786, true},
    {"KONDO_KRS788", RCSERVO_KONDO_KRS788, true},
    {"KONDO_KRS78X", RCSERVO_KONDO_KRS78X, true},
    {"KONDO_KRS4014", RCSERVO_KONDO_KRS4014, true},
    {"KONDO_KRS4024", RCSERVO_KONDO_KRS4024, true},
    {"HITEC_HSR8498", RCSERVO_HITEC_HSR8498, true},
    {"FUTABA_S3003", RCSERVO_FUTABA_S3003, false},
    {"SHAYYE_SYS214050", RCSERVO_SHAYYE_SYS214050, false},
    {"TOWERPRO_MG995", RCSERVO_TOWERPRO_MG995, false},
    {"TOWERPRO_MG996", RCSERVO_TOWERPRO_MG996, false},
    {"DMP_RS0263", RCSERVO_DMP_RS0263, false},
 {"DMP_RS1270", RCSERVO_DMP_RS1270, false},
 {"GWS_S777", RCSERVO_GWS_S777, false},
 {"GWS_S03T", RCSERVO_GWS_S03T, false},
 {"GWS_MICRO", RCSERVO_GWS_MICRO, false}
};

STRINT RBVer[] = {
 {"RB_100b1", RB_100b1},
 {"RB_100b2", RB_100b2},
 {"RB_100b3", RB_100b3},
 {"RB_100", RB_100},
 {"RB_100RD", RB_100RD},
 {"RB_110", RB_110},
 {"RB_050", RB_050}
};

STRINT SKey[] = {
    {"F1",  KBF1},
    {"F2",  KBF2},
    {"F3",  KBF3},
    {"F4",  KBF4},
    {"F5",  KBF5},
    {"F6",  KBF6},
    {"F7",  KBF7},
    {"F8",  KBF8},
    {"F9",  KBF9},
    {"F10", KBF10},
    {"F11", KBF11},
    {"F12", KBF12},
    {"ENTER", KBENTER},
// {"SPACE", KBSPACE},
    {"UP",    KBUP},
    {"DOWN",  KBDOWN},
    {"LEFT",  KBLEFT},
    {"RIGHT", KBRIGHT}
// {"PGUP",  KBPGUP},
// {"PGDN",  KBPGDN}
};

errcode.h
顧名思義,error code用    將一些錯誤條件define為值

#ifndef __ERRCODE_H
#define __ERRCODE_H

#define SUCCESS 0

// ================= demofile error cede ==================
// for general case
#define OFFSET     0
#define OPEN_FILE_FAIL   (OFFSET+0)
#define UNKNOWN_LINE   (OFFSET+1) //not [XXX] , XX = YY
#define INVALID_GROUP   (OFFSET+2) 
#define NOGROUP_ITEM   (OFFSET+3)
#define INVALID_NAME   (OFFSET+4)
#define INVALID_VALUE   (OFFSET+5)


// for def file
#define DEF_OFFSET    100
// in  [setting] group
#define DEF_SET_OFFSET   200
#define DEF_SET_INVALID_FRMNO (DEF_SET_OFFSET+6)
#define DEF_SET_INVALID_MODE (DEF_SET_OFFSET+7)
// in [channel] group
#define DEF_CH_OFFSET   300
#define DEF_CH_INVALID_CH  (DEF_CH_OFFSET+6)
#define DEF_CH_REPEAT_CH  (DEF_CH_OFFSET+7)
#define DEF_CH_INVALID_PIN  (DEF_CH_OFFSET+8)
#define DEF_CH_REPEAT_PIN  (DEF_CH_OFFSET+9)
#define DEF_CH_INVALID_MODE  (DEF_CH_OFFSET+10)
// in [Files] group
#define DEF_FIL_OFFSET   400
// for cmd file
#define CMD_OFFSET    500
#define CMD_NO_ACTNO   (CMD_OFFSET+6)
#define CMD_NO_CMD    (CMD_OFFSET+7)
#define CMD_NO_NAME    (CMD_OFFSET+8)


// for act file
#define ACT_OFFSET    600
#define ACT_INVALID_FRMNO  (ACT_OFFSET+6)
#define ACT_INVALID_TIME  (ACT_OFFSET+7)

// for frm file
#define FRM_OFFSET    700
#define FRM_REPEAT_CH   (FRM_OFFSET+6)

// for offset file
#define TXT_OFFSET    800
#define TXT_REPEAT_CH   (TXT_OFFSET+6)
// +++++++++++++++++++++++ end +++++++++++++++++++++++


// code for fileio
#define FILEIO_OFFSET   900
#define INI_FILEEND    (FILEIO_OFFSET+0)
#define INI_INVALID_CH   (FILEIO_OFFSET+1)
#define INI_INVALID_VALUE  (FILEIO_OFFSET+2) 
#define INI_DIVIDE_FAIL   (FILEIO_OFFSET+3) //string doesn't have separate char
#define INI_DIVIDE_STR1   (FILEIO_OFFSET+4)
#define INI_DIVIDE_STR2   (FILEIO_OFFSET+5)
#define INI_INVALID_NO   (FILEIO_OFFSET+6)
#define INI_INVALIDCHANNEL  (FILEIO_OFFSET+7)
#define INI_NUMPRE_NULL   (FILEIO_OFFSET+8)
#define INI_NUMPRE_INVALID  (FILEIO_OFFSET+9)
#define INI_NUMPRE_FAIL   (FILEIO_OFFSET+10)
#define INI_NUMPOST_NULL  (FILEIO_OFFSET+11)  // str = NULL
#define INI_NUMPOST_INVALID  (FILEIO_OFFSET+12) // unit error
#define INI_NUMPOST_FAIL  (FILEIO_OFFSET+13) // value error

//memory error
#define MEMORY_ERROR   (1000)

// fode for map
#define MAP_OFFSET    1100
#define MAP_NOFINDINITFRM  (MAP_OFFSET+0)
#define MAP_NOFINDFRM   (MAP_OFFSET+1)
#define MAP_REPEAT_FRMNO  (MAP_OFFSET+2)
#define MAP_NOFINEINITACT  (MAP_OFFSET+3)
#define MAP_NOFINDACT   (MAP_OFFSET+4)
#define MAP_REPEAT_ACTNO  (MAP_OFFSET+5)
#define MAP_REPEAT_CMD   (MAP_OFFSET+6)

#ifdef __cplusplus
extern "C" {
#endif

void errcode_ShowErr(int code);
void errcode_SetErrStr(const char *str);
void errcode_SetErrGroup(const char *str);
void errcode_SetErrFRM(const int frmno);
void errcode_SetErrACT(const int actno);
void errcode_SetErrCMD(const int cmd);

#ifdef __cplusplus
}
#endif

#endif


errcode.cpp
error code輸出錯誤訊息用

#include <string.h>
#include "errcode.h"
#include "userio.h"
#include "const.h"

#define DIVISOR  100
#define DEF   (DEF_OFFSET / DIVISOR)
#define DEF_SET  (DEF_SET_OFFSET / DIVISOR)
#define DEF_CH  (DEF_CH_OFFSET / DIVISOR)
#define DEF_FILE (DEF_FIL_OFFSET / DIVISOR)
#define CMD   (CMD_OFFSET / DIVISOR)
#define ACT   (ACT_OFFSET / DIVISOR)
#define FRM   (FRM_OFFSET / DIVISOR)
#define TXT   (TXT_OFFSET / DIVISOR)
#define MAP   (MAP_OFFSET / DIVISOR)

static char ErrLine[1024] = "";
static char ErrFile[256] = "";
static char ErrGroup[256] = "";
static int errfrm;
static int erract;
static char errcmd[10];

static void def_ErrShow(int code);
static void def_SetErrShow(int code);
static void def_CHErrShow(int code);
static void def_FileErrShow(int code);
static void cmd_ErrShow(int code);
static void act_ErrShow(int code);
static void frm_ErrShow(int code);
static void txt_ErrShow(int code);
static void map_ErrShow(int code);

static void map_ErrShow(int code)
{
 int i = code % DIVISOR;
 const char *str[] = {
  "map : can't find initial frame : %d\n",
  "map : an act has an undefined frame : %d\n",
  "map : repeat frame number : %d\n",
  "map : can't find initial action : %d\n",
  "map : a command point to an undefined act : %d\n",
  "map : repeat action  number : %d\n",
  "map : repeat command : %s\n"
 };
 switch(i){
  case 0: case 1: case 2:
   showmsg(str[i], errfrm);
   break;
  case 3: case 4: case 5:
   showmsg(str[i], erract);
   break;
  case 6:
   showmsg(str[i], errcmd);
   break;
 }
}

static void def_SetErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Setting");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid frame number appears in group %s : %s",
  "%s file : invalid initial frame mode appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void def_CHErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Channels");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid channel appears in group %s : %s",
  "%s file : repeat channel appears in group %s : %s",
  "%s file : invalid pin appears in group %s : %s",
  "%s file : repeat pin appears in group %s : %s",
  "%s file : invalid servo mode appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void def_FileErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 strcpy(ErrGroup, "Files");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void cmd_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"cmd");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears : %s\n",
  "%s file : invalid item value appears : %s\n",
  "%s file : a command don't define active number\n",
  "%s file : a command don't define command key\n",
  "%s file : a command don't define command name\n",
 };
 switch(i){
  case 0: case 6: case 7: case 8: case 9:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3: case 4: case 5:
   showmsg(str[i], ErrFile, ErrLine);
   break;
 }
}

static void act_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"act");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : invalid frame number in group %s : %s",
  "%s file : incalid time appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void frm_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"frm");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s",
  "%s file : repeat channal in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

static void txt_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"offset");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears : %s",
  "%s file : invalid item value appears : %s",
  "%s file : repeat channal : %s",
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  default:
   showmsg(str[i], ErrFile, ErrLine);
   break;
 }
}

static void def_ErrShow(int code)
{
 int i = code % DIVISOR;
 strcpy(ErrFile,"def");
 const char *str[] = {
  "Open %s file fail\n",
  "%s file : unknown line : %s\n",
  "%s file : invalid group : %s\n",
  "%s file : no group item : %s\n",
  "%s file : invalid item name appears in group %s : %s",
  "%s file : invalid item value appears in group %s : %s"
 };
 switch(i){
  case 0:
   showmsg(str[i], ErrFile);
   break;
  case 1: case 2: case 3:
   showmsg(str[i], ErrFile, ErrLine);
   break;
  default:
   showmsg(str[i], ErrFile, ErrGroup, ErrLine);
   break;
 }
}

void errcode_ShowErr(int code)
{
 int i;
 i = code / DIVISOR;
 switch(i){
  case DEF:
   def_ErrShow(code);
   break;
  case DEF_SET:
   def_SetErrShow(code);
   break;
  case DEF_CH:
   def_CHErrShow(code);
   break;
  case DEF_FILE:
   def_FileErrShow(code);
   break;
  case CMD:
   cmd_ErrShow(code);
   break;
  case ACT:
   act_ErrShow(code);
   break;
  case FRM:
   frm_ErrShow(code);
   break;
  case TXT:
   txt_ErrShow(code);
   break;
  case MAP:
   map_ErrShow(code);
 }
 showmsg("\nPress any key to quit\n");
 keyboard_waitkey();
}

void errcode_SetErrFRM(const int frmno)
{
 errfrm = frmno;
}

void errcode_SetErrACT(const int actno)
{
 erract = actno;
}
void errcode_SetErrGroup(const char *str)
{
 strcpy(ErrGroup, str);
}

void errcode_SetErrStr(const char *str)
{
 strcpy(ErrLine, str);
}

void errcode_SetErrCMD(const int cmd)
{
 int i;
 if((cmd > 'A') && (cmd < 'Z')){
  errcmd[0] = cmd;
  errcmd[1] = '\0';
 }
 else{
  for(i = 0; i < NUM_SKEY; i++){
   if(cmd == SKey[i].value)
    strcpy(errcmd, SKey[i].name);
  }
 }
}  





基本上這邊講的都蠻簡單的

也可以當作複習基本功囉~

下次開始就要進入較麻煩的部分了

敬請期待

Share:

2012/3/5

[開箱文] DMP 瞻營全總部 (RoBoard總部)近期更新

各位大家好~~~

本魔又來為大家推出新的更新照囉~

現在RB總部真的是越來越完整了!!

到時候完全蓋好後   本魔會推出一個完美精裝版的!!!!

從二樓看整個大廳(真的是超大的!!)

大廳的燈(有沒有覺得來到N星級飯店的感覺!?)

主管辦公室(採光好,氣氛佳~    lu大辦公室像這樣歐~)

主管辦公室(很大吧?)

辦公室(透明窗可以直接看到外部大廳~  這樣就不會有很沉悶的感覺了)

階梯教室(兩台投影機+豪華座椅)

階梯教室(據說未來RB研習營都會在這舉辦~ 歡迎大家到時踴躍報名參加)

階梯教室(本魔偷偷搶先試坐啦~)

五軸CNC機台(機器人製造專用機台!)

 
噴砂機(機器人製造專用機台!)

雷射雕刻機(機器人製造專用機台!)

台灣自產的桌上型3D printer(RB實習生可以使用的~)

台灣自產的桌上型三軸雕刻機(一樣可以給RB實習生用的~)






其他還有許多秘密場景由於本魔等級不夠所以沒辦法拍囉~ 

(ex: N星級廁所 , 電影院投影設備 , 神秘辦公室 ...等)

像RPG遊戲總是會有警衛跟你說 : [噴火龍太強了~你還是別去送死吧!]

不過本魔會努力練等的!!!
Share:

[RoBoRC第四回] 介紹程式碼fileio

接下來要介紹的是fileio.h / fileio.cpp
主要就是讀取資料
以及一些將字串分割的函式

而且fileio也可以直接讀取壓縮黨(zip)內的內容


fileio.h
#ifndef __FILEIO_H
#define __FILEIO_H

#include "defines.h"

#if defined(RB_MSVC_WIN32)
 //#define USE_ZZIP
#endif

#ifdef USE_ZZIP                     //定義讀取檔案的格式型態
    #include <zzip/zzip.h>
    typedef ZZIP_FILE   FILEIO;
 typedef zzip_size_t FILEIO_SIZE_T;
 typedef zzip_off_t  FILEIO_OFF_T;
#else
    #include <stdio.h>
    typedef FILE   FILEIO;
 typedef size_t FILEIO_SIZE_T;
 typedef long   FILEIO_OFF_T;
#endif


#define INI_MAXLINESIZE     (1024)
#define INI_MAXELEMSIZE     (256)

typedef struct
{
    int  type;
    char itemname[INI_MAXELEMSIZE+1];
    char itemvalue[INI_MAXELEMSIZE+1];

} INI_ITEM_t; // type : INI_GROUPTITLE , INI_GROUPITEM or UNKNOW. itemname = itemvalue <==> cmd = XXXX.cmd
//-- values for INI_ITEM_t.type
     #define  INI_GROUPTITLE   (0)
     #define  INI_GROUPITEM    (1)
     #define  INI_UNKNOWNITEM  (2)


#ifdef __cplusplus
extern "C" {                     //讓C++' 將以下內容用C語言讀取
#endif

int  ini_ReadNextItem(FILEIO* ini_fp, INI_ITEM_t* iniitem);
bool  ini_IsGroup(INI_ITEM_t* item, const char* title);
bool  ini_IsItem(INI_ITEM_t* item, const char* name);
bool  ini_IsNumber(char* str);
void  ini_InitialItem(INI_ITEM_t* item);
char* ini_RemoveSpace(char* str);              //may break str's content
int   ini_ParseNumber_pre(char *str, const char *prefix, int *data);
int   ini_ParseNumber_post(char *str, const char *postfix, int *data);
int   ini_DivideString(char *str, char **str1, char **str2, const char *fix);
int   ini_GetCH(char *str, int *ch);
int   ini_GetValue(char *str, int *value);


FILEIO*    ini_FileOpen(char* filename);
void    ini_FileClose(FILEIO* fp);
FILEIO*       fileio_FileOpen(char* filename, const char* mode);
void          fileio_FileClose(FILEIO* fp);
FILEIO_SIZE_T fileio_Read(void* buf, FILEIO_SIZE_T size, FILEIO_SIZE_T count, FILEIO* fp);
char*         fileio_ReadLine(FILEIO* fp, char* buf, int maxcnt);
int           fileio_GetChar(FILEIO* fp);
int           fileio_Seek(FILEIO* fp, FILEIO_OFF_T offset, int origin);
FILEIO_OFF_T  fileio_GetPos(FILEIO* fp);
FILEIO_SIZE_T fileio_GetSize(FILEIO* fp);
bool          fileio_Exist(char* filename);
int           fileio_IsFileEnd(FILEIO* fp);





#ifdef __cplusplus
}
#endif

#endif






fileio.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "fileio.h"
#include "errcode.h"

#if defined(RB_LINUX)
    #define _stricmp  strcasecmp
    #define _strnicmp strncasecmp
#elif defined(RB_BC_DOS) || defined(RB_DJGPP)
    #define _stricmp  stricmp
    #define _strnicmp strnicmp
#endif


/***********************  Functions for .ini Files  ***************************/

void ini_InitialItem(INI_ITEM_t* item)               //預設值
{
 item->itemname[0] = item->itemvalue[0] = '\0';
 item->type = INI_UNKNOWNITEM;
}

int ini_GetValue(char *str, int *value)               //將字串轉為數字   非數字則回傳'無效值'
{
 if(!ini_IsNumber(str))
  return INI_INVALID_VALUE;
 *value = atol(str);
 return SUCCESS;
}

static char* ini_RemoveComment(char* str) {              //將程式寫法改為電腦讀取方法   即int a; >> "int a\0"
 if (str != NULL)
  str[strcspn(str, ";")] = '\0';                //strcspn   尋找字元位置
 return str;
}

int ini_DivideString(char *str, char **str1, char **str2, const char *fix)      //分割字串以fix為分割點
{
 int i;
 i = (int)strcspn(str, fix);
 if(str[i] == '\0')
  return INI_DIVIDE_FAIL;
 str[i] = '\0';
 *str1 = ini_RemoveSpace(str);
 *str2 = ini_RemoveSpace(&str[i+1]);
 if(strlen(*str1) == 0)
  return INI_DIVIDE_STR1;
 if(strlen(*str2) == 0)
  return INI_DIVIDE_STR2;
 return SUCCESS;
}

char* ini_RemoveSpace(char* str) {                //刪除前後的無意義字元  ex: ' ' , '\t'
 int i;

 if (str == NULL) return str;

    i = (int)strlen(str);
    if (i == 0) return str; else i--; //ignore empty string

    //remove tail space chars
 while((i >= 0) && ((str[i] == ' ') || (str[i] == '\t')))
  i--;

    str[i + 1] = '\0';
    //remove head space chars
    i = 0;
 while ((str[i] == ' ') || (str[i] == '\t')) i++;
    return &(str[i]);
 /*
 //remove all space in the string
 int i = 0, j = 0;
 while ((str[i] = str[j++]) != '\0')
  if (str[i] != ' ') i++;
 */
}

bool ini_IsNumber(char* str) {                 //判斷是否為正整數
 if (*str == '\0') return false;

 while (*str != '\0')
 {
        if ((*str < '0') || (*str > '9')) return false;
  str++;
 }
    return true;
}

int ini_ParseNumber_pre(char *str, const char *prefix, int *data)        //分析字首
{
 int i;
// ini_RemoveSpace(str);
 i = (int)strlen(prefix);
 if (str == NULL)
  return INI_NUMPRE_NULL;                 //若str為空值   回傳INI_NUMPRE_NULL
 if((strlen(str) <= (unsigned)i) || (_strnicmp(str, prefix, i) != 0))
  return INI_NUMPRE_INVALID;                //若prefix字數大於str 或 prefix與str的前 i 個數不同 回傳INI_NUMPRE_INVALID
 str = ini_RemoveSpace(&str[i]);                //刪除前後的無意義字元  ex: ' ' , '\t'
 if(!ini_IsNumber(str))
  return INI_NUMPRE_FAIL;                 //不為數字回傳INI_NUMPRE_FAIL
 *data = atol(str);                   //轉為long
 return SUCCESS;
}

int ini_ParseNumber_post(char *str, const char *postfix, int *data)        //分析字尾
{
 int i;
 char *str2;
 if(str == NULL)
  return INI_NUMPOST_NULL;                //若str為空值   回INI_NUMPOST_NULL
 i = (int)strcspn(str, postfix);                //尋找字元相同位置   相同的前一個
 if(str[i] != '\0'){                   //要判斷不為\0     因為\0就已經是結尾了
  str2 = ini_RemoveSpace(&str[i]);              //刪除前後的無意義字元  ex: ' ' , '\t'
  if(_stricmp(str2, postfix) != 0)              
   return INI_NUMPRE_INVALID;               //判斷字串若不相同回傳INI_NUMPRE_INVALID  不區分大小寫
 }
 str[i] = '\0';                    //簡單的說就是保留前 i 個與postfix不同的字
 str = ini_RemoveSpace(str);
 if(!ini_IsNumber(str))                  
  return INI_NUMPRE_FAIL;                 //刪除前後的無意義字元  ex: ' ' , '\t'
 *data = atoi(str);                   //轉換為數字
 return SUCCESS;
}

FILEIO* ini_FileOpen(char* filename) {               //呼叫fileio_FileOpen  然後回傳檔案位置   在205行
 return fileio_FileOpen(filename, "r");
}

void ini_FileClose(FILEIO* fp) {                //把檔案關掉
 fileio_FileClose(fp);
}


int ini_ReadNextItem(FILEIO* fp, INI_ITEM_t* iniitem) {           //讀取檔案
    char buf[INI_MAXLINESIZE+1];
    char *str = "";
 char *str1, *str2;
 ini_InitialItem(iniitem);                 //把iniitem設為預設值  在20行
 
 iniitem->itemname[0] = iniitem->itemvalue[0] = '\0';
    //read a line
 

    while (!fileio_IsFileEnd(fp))                //判斷檔案室否已經到達結尾  在318行
    {
  str = fileio_ReadLine(fp, buf, INI_MAXLINESIZE);          //讀取一行檔案內容  在232行
        str = ini_RemoveSpace(ini_RemoveComment(str));           //改成電腦讀取方式  並且去除空格等無意義字元
  if (strlen(str) != 0) break;               //如果字串長度為零   就再重讀一行
    }
 if(strlen(str) == 0)                  //如果出來還是為零  代表檔案是空的
  return INI_FILEEND;                  //回傳INI_FILEEND

 errcode_SetErrStr(str);
    //parse the line
     // [XXXXXXXX]
 if ((str[0] == '[') && (str[strlen(str)-1] == ']')){          //如果讀取的檔案前後有[]   代表為itemname
  errcode_SetErrGroup(str);
  str[strlen(str)-1] = '\0';
  strcpy(iniitem->itemname, ini_RemoveSpace(&str[1]));         //把讀進來的字放到itemname去
  iniitem->type = INI_GROUPTITLE;               //型態設為INI_GROUPTITLE
    }
    // XXXX = YYYYY
 else if((ini_DivideString(str, &str1, &str2, "=")) != INI_DIVIDE_FAIL){      //分割字串以"="為分割點  在40行
   strcpy(iniitem->itemname,  str1);              //前面為itemname
   strcpy(iniitem->itemvalue, str2);              //後面為itemvalue
   iniitem->type = INI_GROUPITEM;              //型態設為INI_GROUPITEM
 }
 else
   iniitem->type = INI_UNKNOWNITEM;              //其他設定為INI_UNKNOWNITEM
 return SUCCESS;
}


//====================   Parsing Functions  ====================>:
bool ini_IsGroup(INI_ITEM_t* item, const char* title) {           //判斷itemname是否為title
 if (_stricmp(item->itemname, title) == 0) return true;
 return false;
}

bool ini_IsItem(INI_ITEM_t* item, const char* name) {           //判斷itemname是否為name
 if (_stricmp(item->itemname, name) == 0) return true;
 return false;
}

int ini_GetCH(char *str, int *ch)                //抓出channel的編號
{
 int status;
 status = ini_ParseNumber_pre(str, "CH", ch);            //分析字首  在92行
 if(status != SUCCESS)                  
  status = ini_ParseNumber_pre(str, "Channel", ch);
 if(status == SUCCESS)
 if((*ch <= 31) && (*ch >= 0))               
  return SUCCESS;

 return INI_INVALIDCHANNEL;
}

/*---------------------  end of Func. for .ini Files  ------------------------*/



FILEIO* fileio_FileOpen(char* filename, const char* mode) {          //可以開啟zip檔   也可以正常開啟
    #ifdef USE_ZZIP
  char str[256];

  strcpy(str, mode);
        return zzip_fopen(filename, strcat(str, "i")); //mode | ZZIP_CASELESS
    #else
        return fopen(filename, mode);
    #endif
}

void fileio_FileClose(FILEIO* fp) {                   //關閉檔案用
    #ifdef USE_ZZIP
        zzip_fclose(fp);
    #else
        fclose(fp);
    #endif
}

FILEIO_SIZE_T fileio_Read(void* buf, FILEIO_SIZE_T size, FILEIO_SIZE_T count, FILEIO* fp) {  //一次讀取count個大小為size的資料
    #ifdef USE_ZZIP
        return zzip_fread(buf, size, count, fp);
    #else
        return fread(buf, size, count, fp);
    #endif
}

char* fileio_ReadLine(FILEIO* fp, char* buf, int maxcnt) {          //先讀取字元  排成一行回傳一行字
    int i = 0, c;
  
    for (i=0; i<maxcnt; i++)
    {
        if ((c=fileio_GetChar(fp)) == EOF) break;             //讀取檔案的字元  如果讀到EOF跳出  在298行
        if ((c == '\r') || (c == '\n')) break;             //如果遇到\r或\n也跳出
        buf[i] = c;                    //其他正常字元  放入buf
    }
    buf[i] = '\0';                    //遇到結尾 給一個結尾符號
  
    //clear remaining chars in the current line
    if (i == maxcnt)                   //如果上面的迴圈不是因為遇到條件跳出的話
    {
        while((c=fileio_GetChar(fp)) != EOF)             //向後把特殊符號拿掉  不然後造成下一次讀取的錯誤
            if ((c == '\r') || (c == '\n')) break;
    }
  
    return buf;
}

/*
#ifdef USE_ZZIP
 static char INI_ReadBuf[256];
 static int  INI_CurChar = -1;
#endif
int ini_GetChar(INIFILE* fp) {
    #ifdef USE_ZZIP

        int i;
      
        if ((INI_CurChar == -1) || (INI_ReadBuf[INI_CurChar] == '\0'))
        {
            i = (int)zzip_fread(INI_ReadBuf, sizeof(INI_ReadBuf[0]), 255, fp);
            if (i <= 0) return EOF;

            INI_ReadBuf[i] = '\0';
            INI_CurChar = 0;
        }

        return INI_ReadBuf[INI_CurChar++];
    #else
        return fgetc(fp);
    #endif
}

int ini_IsFileEnd(INIFILE* fp) {
    #ifdef USE_ZZIP
  long cur_offset, end_offset;

  if ((INI_CurChar == -1) || (INI_ReadBuf[INI_CurChar] == '\0'))
  {
   cur_offset = zzip_tell(fp);
   zzip_seek(fp, 0L, SEEK_END);
   end_offset = zzip_tell(fp);

   if (cur_offset >= end_offset) return 1;
   zzip_seek(fp, cur_offset, SEEK_SET);
  }
  return 0;
 #else
        return feof(fp);
    #endif
}
*/

int fileio_GetChar(FILEIO* fp) {                //讀取檔案的字元
    #ifdef USE_ZZIP
  char buf[1];
  int  i = (int)zzip_fread(buf, sizeof(buf[0]), 1, fp);

  if (i <= 0) return EOF; else return (int)buf[0];
    #else
        return fgetc(fp);
    #endif
}

bool fileio_Exist(char* filename) {                //檢查檔案室否存在
 FILEIO* fp;

 if ((fp = fileio_FileOpen(filename, "r")) == NULL) return false;

 fileio_FileClose(fp);
    return true;
}

int fileio_IsFileEnd(FILEIO* fp) {                //判斷檔案室否已經到達結尾
    #ifdef USE_ZZIP
  FILEIO_OFF_T cur_offset, end_offset;

  cur_offset = zzip_tell(fp);
  zzip_seek(fp, 0L, SEEK_END);
  end_offset = zzip_tell(fp);

  if (cur_offset >= end_offset) return 1;
  zzip_seek(fp, cur_offset, SEEK_SET);

  return 0;
 #else
        return feof(fp);
    #endif
}

FILEIO_SIZE_T fileio_GetSize(FILEIO* fp) {              //取得檔案結尾用
 FILEIO_OFF_T cur_offset, end_offset;

 #ifdef USE_ZZIP
  cur_offset = zzip_tell(fp);
  zzip_seek(fp, 0L, SEEK_END);
  end_offset = zzip_tell(fp);
  zzip_seek(fp, cur_offset, SEEK_SET);
 #else
  cur_offset = ftell(fp);                 //cur_offset現在的位置
  fseek(fp, 0L, SEEK_END);
  end_offset = ftell(fp);                 //end_offset為檔案結尾
  fseek(fp, cur_offset, SEEK_SET);              
    #endif

 return end_offset;
}

int fileio_Seek(FILEIO* fp, FILEIO_OFF_T offset, int origin) {         //fseek  也可用於zzip
 #ifdef USE_ZZIP
  if (zzip_seek(fp, offset, origin) >= 0L) return 0;
  return -1;
 #else
  return fseek(fp, offset, origin);              //改變檔案所在位置
    #endif
}

FILEIO_OFF_T  fileio_GetPos(FILEIO* fp) {              //ftell  也可用於zzip
 #ifdef USE_ZZIP
  return zzip_tell(fp);
 #else
  return ftell(fp);                   //回傳檔案目前位置
    #endif
}

Share:
技術提供:Blogger.

追蹤者