簡體   English   中英

用C解析iCalendar文件

[英]Parsing an iCalendar file in C

我正在尋找使用C解析iCalendar文件的方法。我有一個現有的結構設置,並已准備就緒,並且想逐行解析組件。

例如,我需要解析以下內容:

UID:uid1@example.com
DTSTAMP:19970714T170000Z
ORGANIZER;CN=John Doe;SENT-BY="mailto:smith@example.com":mailto:john.doe@example.com
CATEGORIES:Project Report, XYZ, Weekly Meeting
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party

以下是一些規則:

  • 每行的第一個單詞是屬性名稱
  • 屬性名稱后跟冒號(:)或分號(;)
  • 如果是冒號,則屬性值將直接位於內容的右側到行尾
  • 此處添加了另一層復雜性,因為允許使用逗號分隔的值列表,然后將其存儲在數組中。 因此,例如一個CATEGORIES將在數組中包含3個元素作為值
  • 如果在屬性名稱后有半冒號,則后面有可選參數
  • 可選參數格式為ParamName = ParamValue。 再次支持逗號分隔的列表。
  • ORGANIZER行上可以看到一個以上的可選參數。 在下一個參數和值之后將是另一個分號。
  • 為了使用另一個扳手,值中允許使用引號。 如果值用引號引起來,則需要將其視為值的一部分,而不是語法的一部分。 因此,引號中的分號並不意味着會有另一個參數將成為值的一部分。

我正在使用strchr()strtok()並從中獲得了一些基本元素,但是它變得非常混亂且雜亂無章,似乎不是執行此操作的正確方法。

如何使用標准C庫(或POSIX regex庫)實現這種復雜的解析器? (不是尋找完整的解決方案,只是起點)

該答案假設您想使用Standard C來滾動自己的解析器。實際上,通常最好使用現有的解析器,因為他們已經考慮並處理了所有可能出現的奇怪問題。

我的高級方法是:

  • 讀一行
  • 將指向該行開頭的指針傳遞給函數parse_line
    • 在指針上使用strcspn標識第一個的位置:; (如果找不到標記,則中止)
    • 將文本保存為屬性名稱
    • 而解析指針指向;
      • 調用解析指針的函數extract_name_value_pair傳遞地址。
      • 該函數將提取並保存名稱和值,並更新指針以指向; :輸入后。 當然,這個函數必須處理值中的引號和它們可能是的事實; :值中
    • (此時解析指針始終是:
    • 將字符串的其余部分傳遞給函數parse_csv ,該函數將查找逗號分隔的值(再次注意引號),並將找到的結果存儲在正確的位置。

parse_csv ,應該首先開發和測試功能parse_csvextract_name_value_pair 做一個測試套件,並檢查它們是否正常工作。 然后編寫您的整體解析器函數,並根據需要調用這些函數。


另外,將所有內存分配代碼編寫為單獨的函數。 考慮一下要存儲解析結果的數據結構。然后對該數據結構進行編碼,並進行測試,完全獨立於解析代碼。 只有這樣,才能編寫解析代碼和調用函數,以將結果數據插入數據結構中。

確實不希望將內存管理代碼與解析代碼混在一起。 這使得調試難度成倍增加。


當制作一個接受字符串的函數時(例如上述所有三個命名函數,以及您認為需要的任何其他幫助器),它們的接口都有一些選擇:

  • 接受指向以null結尾的字符串的指針
  • 接受指針以開始和結束
  • 接受要開始的指針和整數長度

每種方法都有其優點和缺點:煩人的是,到處都寫空終止符,然后在需要時取消它們; 但是當您想使用strcspn或其他字符串函數但收到一段長度計數的字符串時,這也很煩人。

此外,當函數需要讓調用者知道其在解析中消耗了多少文本時,您有兩種選擇:

  • 接受字符指針,返回消耗的字符數; 調用函數會將兩者加在一起以了解發生了什么
  • 接受指向字符的指針,並更新指向字符的指針。 然后可以將返回值用於錯誤代碼。

沒有一個正確的答案,根據經驗,您會更好地決定哪種選項可以生成最干凈的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM