Skip to content

Commit

Permalink
Merge pull request #8 from sboh1214/feature/section
Browse files Browse the repository at this point in the history
Parse SectionArray
  • Loading branch information
ksjae authored Oct 6, 2020
2 parents 8b21317 + b9b5273 commit 00dd970
Show file tree
Hide file tree
Showing 41 changed files with 583 additions and 115 deletions.
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
excluded:
- Carthage
- Pods
- .build

line_length: 100

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
![Lint](https://github.com/sboh1214/HwpKit/workflows/Lint/badge.svg)
[![codecov](https://codecov.io/gh/sboh1214/HwpKit/branch/master/graph/badge.svg)](https://codecov.io/gh/sboh1214/HwpKit)

[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=sboh1214_HwpKit&metric=alert_status)](https://sonarcloud.io/dashboard?id=sboh1214_HwpKit)
[![CodeFactor](https://www.codefactor.io/repository/github/sboh1214/hwpkit/badge)](https://www.codefactor.io/repository/github/sboh1214/hwpkit)

Swift Package for Reading & Writing HWP File

## Install
Expand Down
7 changes: 7 additions & 0 deletions Sources/HwpKit/Enums/HwpCharType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

public enum HwpCharType: String, Codable {
case char
case inline
case extended
}
1 change: 1 addition & 0 deletions Sources/HwpKit/Enums/HwpStreamName.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
public enum HwpStreamName: String {
case fileHeader = "FileHeader"
case docInfo = "DocInfo"
case bodyText = "BodyText"
case summary = "\005HwpSummaryInformation"
case previewText = "PrvText"
case previewImage = "PrvImage"
Expand Down
106 changes: 52 additions & 54 deletions Sources/HwpKit/Enums/HwpTag.swift
Original file line number Diff line number Diff line change
@@ -1,67 +1,65 @@
// swiftlint:disable identifier_name

let BEGIN: UInt32 = 0x10

/**
’문서 정보’의 데이터 레코드
*/
final class HwpDocInfoTag {
static let DOCUMENT_PROPERTIES: UInt32 = BEGIN
static let ID_MAPPINGS: UInt32 = BEGIN + 1
static let BIN_DATA: UInt32 = BEGIN + 2
static let FACE_NAME: UInt32 = BEGIN + 3
static let BORDER_FILL: UInt32 = BEGIN + 4
static let CHAR_SHAPE: UInt32 = BEGIN + 5
static let TAB_DEF: UInt32 = BEGIN + 6
static let NUMBERING: UInt32 = BEGIN + 7
static let BULLET: UInt32 = BEGIN + 8
static let PARA_SHAPE: UInt32 = BEGIN + 9
static let STYLE: UInt32 = BEGIN + 10
static let DOC_DATA: UInt32 = BEGIN + 11
static let DISTRIBUTE_DOC_DATA: UInt32 = BEGIN + 12
static let RESERVED: UInt32 = BEGIN + 13
static let COMPATIBLE_DOCUMENT: UInt32 = BEGIN + 14
static let LAYOUT_COMPATIBILITY: UInt32 = BEGIN + 15
static let TRACKCHANGE: UInt32 = BEGIN + 16
static let MEMO_SHAPE: UInt32 = BEGIN + 76
static let FORBIDDEN_CHAR: UInt32 = BEGIN + 78
static let TRACK_CHANGE: UInt32 = BEGIN + 80
static let TRACK_CHANGE_AUTHOR: UInt32 = BEGIN + 81
static let documentProperties: UInt32 = BEGIN
static let idMappings: UInt32 = BEGIN + 1
static let binData: UInt32 = BEGIN + 2
static let faceName: UInt32 = BEGIN + 3
static let borderFill: UInt32 = BEGIN + 4
static let charShape: UInt32 = BEGIN + 5
static let tabDef: UInt32 = BEGIN + 6
static let numbering: UInt32 = BEGIN + 7
static let bullet: UInt32 = BEGIN + 8
static let paraShape: UInt32 = BEGIN + 9
static let style: UInt32 = BEGIN + 10
static let docData: UInt32 = BEGIN + 11
static let distributeDocData: UInt32 = BEGIN + 12
static let reserved: UInt32 = BEGIN + 13
static let compatibleDocument: UInt32 = BEGIN + 14
static let layoutCompatibility: UInt32 = BEGIN + 15
static let trackChange: UInt32 = BEGIN + 16
static let memoShape: UInt32 = BEGIN + 76
static let forbiddenChar: UInt32 = BEGIN + 78
static let trackChangeContent: UInt32 = BEGIN + 80
static let trackChangeAuthor: UInt32 = BEGIN + 81
}

/**
‘본문’의 데이터 레코드
*/
final class HwpSectionTag {
static let PARA_HEADER: UInt32 = BEGIN + 50
static let PARA_TEXT: UInt32 = BEGIN + 51
static let PARA_CHAR_SHAPE: UInt32 = BEGIN + 52
static let PARA_LINE_SEG: UInt32 = BEGIN + 53
static let PARA_RANGE_TAG: UInt32 = BEGIN + 54
static let CTRL_HEADER: UInt32 = BEGIN + 55
static let LIST_HEADER: UInt32 = BEGIN + 56
static let PAGE_DEF: UInt32 = BEGIN + 57
static let FOOTNOTE_SHAPE: UInt32 = BEGIN + 58
static let PAGE_BORDER_FILL: UInt32 = BEGIN + 59
static let SHAPE_COMPONENT: UInt32 = BEGIN + 60
static let TABLE: UInt32 = BEGIN + 61
static let SHAPE_COMPONENT_LINE: UInt32 = BEGIN + 62
static let SHAPE_COMPONENT_RECTANGLE: UInt32 = BEGIN + 63
static let SHAPE_COMPONENT_ELLIPSE: UInt32 = BEGIN + 64
static let SHAPE_COMPONENT_ARC: UInt32 = BEGIN + 65
static let SHAPE_COMPONENT_POLYGON: UInt32 = BEGIN + 66
static let SHAPE_COMPONENT_CURVE: UInt32 = BEGIN + 67
static let SHAPE_COMPONENT_OLE: UInt32 = BEGIN + 68
static let SHAPE_COMPONENT_PICTURE: UInt32 = BEGIN + 69
static let SHAPE_COMPONENT_CONTAINER: UInt32 = BEGIN + 70
static let CTRL_DATA: UInt32 = BEGIN + 71
static let EQEDIT: UInt32 = BEGIN + 72
static let RESERVED: UInt32 = BEGIN + 73
static let SHAPE_COMPONENT_TEXTART: UInt32 = BEGIN + 74
static let FORM_OBJECT: UInt32 = BEGIN + 75
static let MEMO_SHAPE: UInt32 = BEGIN + 76
static let MEMO_LIST: UInt32 = BEGIN + 77
static let CHART_DATA: UInt32 = BEGIN + 79
static let VIDEO_DATA: UInt32 = BEGIN + 82
static let SHAPE_COMPONENT_UNKNOWN: UInt32 = BEGIN + 99
static let paraHeader: UInt32 = BEGIN + 50
static let paraText: UInt32 = BEGIN + 51
static let paraCharShape: UInt32 = BEGIN + 52
static let paraLineSeg: UInt32 = BEGIN + 53
static let paraRangeTag: UInt32 = BEGIN + 54
static let ctrlHeader: UInt32 = BEGIN + 55
static let listHeader: UInt32 = BEGIN + 56
static let pageDef: UInt32 = BEGIN + 57
static let footnoteShape: UInt32 = BEGIN + 58
static let pageBorderFill: UInt32 = BEGIN + 59
static let shapeComponent: UInt32 = BEGIN + 60
static let table: UInt32 = BEGIN + 61
static let shapeComponentLine: UInt32 = BEGIN + 62
static let shapeComponentRectangle: UInt32 = BEGIN + 63
static let shapeComponentEllipse: UInt32 = BEGIN + 64
static let shapeComponentArc: UInt32 = BEGIN + 65
static let shapeComponentPolygon: UInt32 = BEGIN + 66
static let shapeComponentCurve: UInt32 = BEGIN + 67
static let shapeComponentOle: UInt32 = BEGIN + 68
static let shapeComponentPicture: UInt32 = BEGIN + 69
static let shapeComponentContainer: UInt32 = BEGIN + 70
static let ctrlData: UInt32 = BEGIN + 71
static let eqEdit: UInt32 = BEGIN + 72
static let reserved: UInt32 = BEGIN + 73
static let shapeComponentTextart: UInt32 = BEGIN + 74
static let formObject: UInt32 = BEGIN + 75
static let memoShape: UInt32 = BEGIN + 76
static let memoList: UInt32 = BEGIN + 77
static let chartData: UInt32 = BEGIN + 79
static let videoData: UInt32 = BEGIN + 82
static let shapeComponentUnknown: UInt32 = BEGIN + 99
}
7 changes: 6 additions & 1 deletion Sources/HwpKit/HwpFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public class HwpFile {
public let fileHeader: HwpFileHeader
public let docInfo: HwpDocInfo
public let previewText: HwpPreviewText
public let sectionArray: [HwpSection]

public init(filePath: String) throws {
let ole: OLEFile
Expand All @@ -16,11 +17,15 @@ public class HwpFile {
let streams = Dictionary(uniqueKeysWithValues: ole.root.children.map { ($0.name, $0 ) })
let reader = StreamReader(ole, streams)

fileHeader = try HwpFileHeader(reader.getDataFromStream(.fileHeader, false))
let fileHeader = try HwpFileHeader(reader.getDataFromStream(.fileHeader, false))
self.fileHeader = fileHeader

let docInfoData = try reader.getDataFromStream(.docInfo, fileHeader.isCompressed)
docInfo = try HwpDocInfo(docInfoData, fileHeader.version)

sectionArray = try reader.getDataFromStorage(.bodyText, fileHeader.isCompressed)
.map {try HwpSection($0, fileHeader.version)}

guard let previewTextStream = streams[HwpStreamName.previewText.rawValue] else {
throw HwpError.streamDoesNotExist(name: HwpStreamName.previewText)
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Foundation
*/
public struct HwpParaShape: HwpDataWithVersion {
/**속성 1*/
public let property1:UInt32
public let property1: UInt32
/**왼쪽 여백*/
public let marginLeft: Int32
/**오른쪽 여백*/
Expand All @@ -19,7 +19,7 @@ public struct HwpParaShape: HwpDataWithVersion {
/**문단 간격 아래*/
public let paragraphSpacingBottom: Int32
/**줄 간격. 한글 2007 이하 버전(5.0.2.5 버전 미만)에서 사용.*/
public let lineSpacing:Int32
public let lineSpacing: Int32
/**탭 정의 아이디(TabDef ID) 참조 값*/
public let tabDefId: UInt16
/**번호 문단 ID(Numbering ID) 또는 글머리표 문단 모양 ID(Bullet ID) 참조 값*/
Expand All @@ -35,12 +35,12 @@ public struct HwpParaShape: HwpDataWithVersion {
/**문단 테두리 아래쪽 간격*/
public let borderSpacingBottom: Int16
/**속성 2(표 40 참조) (5.0.1.7 버전 이상)*/
public var property2: UInt32? = nil
public var property2: UInt32?
/**속성 3(표 41 참조) (5.0.2.5 버전 이상)*/
public var property3: UInt32? = nil
public var property3: UInt32?
/**줄 간격(5.0.2.5 버전 이상)*/
public var lineSpacing2: UInt32? = nil
public var lineSpacing2: UInt32?

init(_ data: Data, _ version: HwpVersion) throws {
var reader = DataReader(data)
defer {
Expand All @@ -60,10 +60,10 @@ public struct HwpParaShape: HwpDataWithVersion {
borderSpacingRight = reader.read(Int16.self)
borderSpacingTop = reader.read(Int16.self)
borderSpacingBottom = reader.read(Int16.self)
if version >= HwpVersion(5,0,1,7) {
if version >= HwpVersion(5, 0, 1, 7) {
property2 = reader.read(UInt32.self)
}
if version >= HwpVersion(5,0,2,5) {
if version >= HwpVersion(5, 0, 2, 5) {
property3 = reader.read(UInt32.self)
lineSpacing2 = reader.read(UInt32.self)
}
Expand Down
File renamed without changes.
6 changes: 6 additions & 0 deletions Sources/HwpKit/Model/Section/HwpChar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Foundation

public struct HwpChar: Codable {
public let type: HwpCharType
public let value: WCHAR
}
16 changes: 16 additions & 0 deletions Sources/HwpKit/Model/Section/HwpCtrlHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Foundation

/**
컨트롤 헤더

컨트롤 문자가 존재하면 컨트롤 문자로부터 존재하는 컨트롤 정보를 생성한다.
Tag ID : HWPTAG_CTRL_HEADER
*/
public struct HwpCtrlHeader: HwpData {
public let ctrlId: UInt32

init(_ data: Data) throws {
var reader = DataReader(data)
ctrlId = reader.read(UInt32.self)
}
}
26 changes: 26 additions & 0 deletions Sources/HwpKit/Model/Section/HwpListHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

/**
문단 리스트 헤더

Tag ID : HWPTAG_LIST_HEADER
*/
public struct HwpListHeader: HwpData {
/**
문단 수

한글문서에선 Int16으로 되어있으나 대부분의 경우 Int32 으로 읽어야 문제가 없다
*/
public let paragraphCount: Int32
public let property: UInt32

init(_ data: Data) throws {
var reader = DataReader(data)
defer {
precondition(reader.isEOF())
}

paragraphCount = reader.read(Int32.self)
property = reader.read(UInt32.self)
}
}
29 changes: 29 additions & 0 deletions Sources/HwpKit/Model/Section/HwpParaCharShape.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation

/**
문단의 글자 모양

Tag ID : HWPTAG_PARA_CHAR_SHAPE
*/
public struct HwpParaCharShape: HwpData {
/**글자 모양이 바뀌는 시작 위치*/
public var startingIndex: [UInt32]
/**글자 모양 ID*/
public var shapeId: [UInt32]

init(_ data: Data) throws {
var reader = DataReader(data)
defer {
precondition(reader.isEOF())
}

var startingIndex = [UInt32]()
var shapeId = [UInt32]()
while !reader.isEOF() {
startingIndex.append(reader.read(UInt32.self))
shapeId.append(reader.read(UInt32.self))
}
self.startingIndex = startingIndex
self.shapeId = shapeId
}
}
60 changes: 60 additions & 0 deletions Sources/HwpKit/Model/Section/HwpParaHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Foundation

/**
문단 헤더

Tag ID : HWPTAG_PARA_HEADER
텍스트의 수가 1 이상이면 문자 수만큼 텍스트를 로드하고 그렇지 않을 경우 PARA_BREAK로 문단을 생성한다.
*/
public struct HwpParaHeader: HwpDataWithVersion {
/**if (nchars & 0x80000000) { nchars &= 0x7fffffff;}*/
public let isLastInList: Bool
/**text(=chars)*/
public let charCount: UInt32
/**
control mask

(UINT32)(1<<ctrlch) 조합
ctrlch는 HwpCtrlAPI.Hwp 2.1 CtrlCh 참고
*/
public let controlMask: UInt32
/**문단 모양 아이디 참조값*/
public let paraShapeId: UInt16
/**문단 스타일 아이디 참조값*/
public let paraStyleId: UInt8
/**단 나누기 종류*/
public let columnType: UInt8
/**글자 모양 정보 수*/
public let charShapeInfoCount: UInt16
/**range tag 정보 수*/
public let rangeTagInfoCount: UInt16
/**각 줄에 대한 align에 대한 정보 수*/
public let alignInfoCount: UInt16
/**문단 Instance ID (unique ID)*/
public let paraId: UInt32
/**변경추적 병합 문단여부. (5.0.3.2 버전 이상)*/
public var isTraceChange: UInt16?

init(_ data: Data, _ version: HwpVersion) throws {
var reader = DataReader(data)
let value = reader.read(UInt32.self)
if (value & 0x80000000) == 0x80000000 {
isLastInList = true
charCount = (value & 0x7fffffff)
} else {
isLastInList = false
charCount = value
}
controlMask = reader.read(UInt32.self)
paraShapeId = reader.read(UInt16.self)
paraStyleId = reader.read(UInt8.self)
columnType = reader.read(UInt8.self)
charShapeInfoCount = reader.read(UInt16.self)
rangeTagInfoCount = reader.read(UInt16.self)
alignInfoCount = reader.read(UInt16.self)
paraId = reader.read(UInt32.self)
if version >= HwpVersion(5, 0, 3, 2) {
isTraceChange = reader.read(UInt16.self)
}
}
}
Loading

0 comments on commit 00dd970

Please sign in to comment.