Skip to content

Commit 295915c

Browse files
committed
Added new flags, cleared code. Bumped version
1 parent af24f55 commit 295915c

3 files changed

Lines changed: 174 additions & 87 deletions

File tree

csvgen.go

Lines changed: 169 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,37 @@ import (
1212

1313
var (
1414
// Config vars
15-
pkg string
16-
subpkg string
17-
out string
18-
fname string
19-
fInfo os.FileInfo
15+
pkg string
16+
subpkg string
17+
out string
18+
fname string
19+
parseEmpty bool
20+
marshal bool
21+
unmarshal bool
22+
23+
fInfo os.FileInfo
2024

2125
// Package vars
2226
pkgCnt string
2327
f *File
2428
p = parser.Parser{AllStructs: true}
2529
)
2630

31+
const fieldPrefix = "um"
32+
2733
func main() {
28-
flags := cli.New("This app generates csv Marshall and Unmarshal functions", "0.0.2")
34+
flags := cli.New("This app generates csv Marshall and Unmarshal functions", "1.0.1")
2935
flags.StringVarP(&pkg, "pkg", "p", "", "output package")
3036
flags.StringVarP(&subpkg, "subpkg", "s", "", "output subpkg name")
3137
flags.StringVarP(&fname, "fname", "f", "", "input file")
3238
flags.StringVarP(&out, "out", "o", "", "output file")
39+
flags.BoolVarP(&parseEmpty, "parseempty", "e", false, "parse empty fields with values: '', 0, 0.0, false. Default: false")
40+
flags.BoolVarP(&marshal, "marshal", "m", true, "generate MarshalCSV or not")
41+
flags.BoolVarP(&unmarshal, "unmarshal", "u", true, "generate UnmarshalCSV or not")
3342

3443
flags.Parse()
3544

45+
fmt.Println("unmarshal:", unmarshal, "\n", "marshal:", marshal)
3646
pkgCnt = "main"
3747
if pkg != "" {
3848
pkgCnt = pkg
@@ -122,27 +132,28 @@ func GenerateCode() {
122132
}
123133

124134
// GenerateFuncs processes every structure.
125-
// Generated functions MarshallCSV and UnmarshallCSV process builtin types,
126-
// call MarshallCSV and UnmarshallCSV for custom types
135+
// Generated functions MarshalCSV and UnmarshalCSV process builtin types,
136+
// call MarshalCSV and UnmarshalCSV for custom types
127137
// and process pointer types assuming that pointers were initiated (memory is
128138
// allocated).
129139
// So the best way is to verify data structures before marshalling
130140
// and unmarshalling for null pointers to prevent SEGFAULT
131141
func GenerateFuncs(vstr parser.StructInfo) {
132142

133-
// func (this *Type) UnmarshalCSV(in []string) error {
134-
// i := 0
135-
// if x, err := strconv.ParseBool(in[i]); err == nil {
136-
// this.b = x
137-
// } else {
143+
// func (pv *Type) UnmarshalCSV(in []string) error {
144+
// if in == nil || len(in) < 2 {
145+
// return errors.New("Invalid input to UnmarshalCSV")
146+
// }
147+
// unm_b, err := strconv.ParseBool(in[0])
148+
// if err != nil {
138149
// return err
139150
// }
140-
// i++
141-
// if x, err := strconv.ParseInt(in[i], 10, 64); err == nil {
142-
// this.a = x
143-
// } else {
151+
// pv.b = b
152+
// unm_a, err := strconv.ParseInt(in[1], 10, 64)
153+
// if err == nil {
144154
// return err
145155
// }
156+
// this.a = a
146157
// }
147158
//
148159
// // func (this Type) MarshalCSV() []string {
@@ -156,11 +167,18 @@ func GenerateFuncs(vstr parser.StructInfo) {
156167
var unmarshallBody []Code
157168
var marshallBody []Code
158169

170+
chkError := If(
171+
Id("in").Op("==").Id("nil").Op("||").Id("len").Call(Id("in")).Op("<").Lit(len(vstr.Fields)),
172+
).Block(
173+
Return().Qual("github.com/pkg/errors", "New").Call(Lit("Invalid input to *" + vstr.Name + " UnmarshalCSV")),
174+
)
175+
unmarshallBody = append(unmarshallBody, chkError)
159176
unmarshallBody = append(unmarshallBody, Id("i").Op(":=").Lit(0))
160177
marshallBody = append(marshallBody, Id("out").Op(":=").Index().String().Values())
161178

162179
for ik, istr := range vstr.Fields {
163-
var g, j *Statement
180+
var g []Code
181+
var j *Statement
164182
star := ""
165183
ttype := istr.Type
166184
if istr.Type[0] == '*' {
@@ -170,22 +188,19 @@ func GenerateFuncs(vstr parser.StructInfo) {
170188

171189
unmarshallBody = append(unmarshallBody, nilCheck(star, istr.Name, istr.Type, false))
172190
marshallBody = append(marshallBody, nilCheck(star, istr.Name, istr.Type, true))
191+
173192
switch ttype {
174193
case "bool":
175-
g = If(
176-
List(Id("x"), Err()).Op(":=").Qual("strconv", "ParseBool").Call(Id("in").Index(Id("i"))),
177-
Err().Op("!=").Nil(),
178-
).Add(genReturn(star, istr.Name, ttype))
179-
j = marshalBody(Qual("strconv", "FormatBool").Call(Op(star).Id("this").Op(".").Id(istr.Name)))
194+
op := Qual("strconv", "ParseBool").Call(Id("in").Index(Id("i")))
195+
g = parseField(star, istr.Name, ttype, op, "false")
196+
j = marshalBody(Qual("strconv", "FormatBool").Call(Op(star).Id("pv").Op(".").Id(istr.Name)))
180197
case "float32":
181198
fallthrough
182199
case "float64":
183-
g = If(
184-
List(Id("x"), Err()).Op(":=").Qual("strconv", "ParseFloat").Call(List(Id("in").Index(Id("i")), Id(ttype[5:]))),
185-
Err().Op("!=").Nil(),
186-
).Add(genReturn(star, istr.Name, ttype))
200+
op := Qual("strconv", "ParseFloat").Call(List(Id("in").Index(Id("i")), Id(ttype[5:])))
201+
g = parseField(star, istr.Name, ttype, op, "0.0")
187202
j = marshalBody(Qual("strconv", "FormatFloat").
188-
Call(Op("float64").Call(Op(star).Id("this").Op(".").Id(istr.Name)),
203+
Call(Op("float64").Call(Op(star).Id("pv").Op(".").Id(istr.Name)),
189204
LitRune('f'), Lit(-1), Id(ttype[5:])),
190205
)
191206
case "int":
@@ -201,13 +216,10 @@ func GenerateFuncs(vstr parser.StructInfo) {
201216
if bn == "" {
202217
bn = "0"
203218
}
204-
g = If(
205-
List(Id("x"), Err()).Op(":=").Qual("strconv", "ParseInt").
206-
Call(List(Id("in").Index(Id("i")), Lit(10), Id(bn))),
207-
Err().Op("!=").Nil(),
208-
).Add(genReturn(star, istr.Name, ttype))
219+
op := Qual("strconv", "ParseInt").Call(List(Id("in").Index(Id("i")), Lit(10), Id(bn)))
220+
g = parseField(star, istr.Name, ttype, op, "0")
209221
j = marshalBody(Qual("strconv", "FormatInt").
210-
Call(Op("int64").Call(Op(star).Id("this").Op(".").Id(istr.Name)), Lit(10)),
222+
Call(Op("int64").Call(Op(star).Id("pv").Op(".").Id(istr.Name)), Lit(10)),
211223
)
212224
case "uint":
213225
fallthrough
@@ -222,29 +234,30 @@ func GenerateFuncs(vstr parser.StructInfo) {
222234
if bn == "" {
223235
bn = "0"
224236
}
225-
g = If(
226-
List(Id("x"), Err()).Op(":=").Qual("strconv", "ParseUint").
227-
Call(List(Id("in").Index(Id("i")), Lit(10), Id(bn))),
228-
Err().Op("!=").Nil(),
229-
).Add(genReturn(star, istr.Name, ttype))
237+
op := Qual("strconv", "ParseUint").Call(List(Id("in").Index(Id("i")), Lit(10), Id(bn)))
238+
g = parseField(star, istr.Name, ttype, op, "0")
230239
j = marshalBody(Qual("strconv", "FormatUint").
231-
Call(Op("uint64").Call(Op(star).Id("this").Op(".").Id(istr.Name)), Lit(10)),
240+
Call(Op("uint64").Call(Op(star).Id("pv").Op(".").Id(istr.Name)), Lit(10)),
232241
)
233242
case "string":
234-
g = Op(star).Id("this").Op(".").Id(istr.Name).Op("=").Id("in").Index(Id("i"))
235-
j = marshalBody(Op(star).Id("this").Op(".").Id(istr.Name))
243+
g = []Code{
244+
Op(star).Id("pv").Op(".").Id(istr.Name).Op("=").Id("in").Index(Id("i")),
245+
}
246+
j = marshalBody(Op(star).Id("pv").Op(".").Id(istr.Name))
236247
default:
237-
// By default generated code calls 'func (this *Type) UnmarshallCSV(s string) error'
238-
g = If(
239-
Err().Op(":=").Id("this").Op(".").Id(istr.Name).Op(".").Id("UnmarshallCSV").
240-
Call(Id("in").Index(Id("i"))),
241-
Err().Op("!=").Nil(),
242-
).Block(
243-
Return().Err(),
244-
)
245-
// By default generated code calls 'func (this Type) MarshallCSV() (string, error)'
248+
// By default generated code calls 'func (this *Type) UnmarshalCSV(s string) error'
249+
g = []Code{
250+
If(
251+
Err().Op(":=").Id("pv").Op(".").Id(istr.Name).Op(".").Id("UnmarshalCSV").
252+
Call(Id("in").Index(Id("i"))),
253+
Err().Op("!=").Nil(),
254+
).Block(
255+
Return().Err(),
256+
),
257+
}
258+
// By default generated code calls 'func (this Type) MarshalCSV() (string, error)'
246259
j = If(
247-
List(Id("mt"), Err()).Op(":=").Id("this").Op(".").Id(istr.Name).Op(".").Id("MarshallCSV").
260+
List(Id("mt"), Err()).Op(":=").Id("pv").Op(".").Id(istr.Name).Op(".").Id("MarshalCSV").
248261
Call(),
249262
Err().Op("!=").Nil(),
250263
).Block(
@@ -253,7 +266,7 @@ func GenerateFuncs(vstr parser.StructInfo) {
253266
marshalBody(Id("mt")),
254267
)
255268
}
256-
unmarshallBody = append(unmarshallBody, g)
269+
unmarshallBody = append(unmarshallBody, g...)
257270
marshallBody = append(marshallBody, j)
258271
if ik != (len(vstr.Fields) - 1) {
259272
unmarshallBody = append(unmarshallBody, Id("i").Op("++"))
@@ -263,56 +276,90 @@ func GenerateFuncs(vstr parser.StructInfo) {
263276
}
264277
}
265278

266-
f.Comment("UnmarshalCSV " + vstr.Name + " func")
267-
f.Func().Params(
268-
Id("this").Op("*").Id(vstr.Name),
269-
).Id("UnmarshalCSV").Params(
270-
Id("in").Index().String(),
271-
).Id("error").Block(
272-
unmarshallBody...,
273-
)
279+
if unmarshal {
280+
f.Comment("UnmarshalCSV " + vstr.Name + " func")
281+
f.Func().Params(
282+
Id("pv").Op("*").Id(vstr.Name),
283+
).Id("UnmarshalCSV").Params(
284+
Id("in").Index().String(),
285+
).Id("error").Block(
286+
unmarshallBody...,
287+
)
274288

275-
f.Line()
289+
f.Line()
290+
}
276291

277-
f.Comment("MarshalCSV " + vstr.Name + " func")
278-
f.Func().Params(
279-
Id("this").Id(vstr.Name),
280-
).Id("MarshalCSV").Params().
281-
Parens(Index().String().Op(",").Id("error")).Block(
282-
marshallBody...,
283-
)
292+
if marshal {
293+
f.Comment("MarshalCSV " + vstr.Name + " func")
294+
f.Func().Params(
295+
Id("pv").Id(vstr.Name),
296+
).Id("MarshalCSV").Params().
297+
Parens(Index().String().Op(",").Id("error")).Block(
298+
marshallBody...,
299+
)
300+
}
301+
302+
if unmarshal {
303+
AddList(vstr)
304+
}
284305
}
285306

286-
func genReturn(star string, fieldName string, fieldType string) *Statement {
307+
func parseField(star string, fieldName string, fieldType string, op *Statement, defv string) []Code {
308+
fldNm := fieldPrefix + strings.Title(fieldName)
309+
parseBlock := []Code{
310+
List(Id(fldNm), Err()).Op(":=").Add(op),
311+
If(
312+
Err().Op("!=").Nil(),
313+
).Block(
314+
Return().Err(),
315+
),
316+
}
317+
287318
var conv *Statement
288319

289320
// Check for float and int
290321
if fieldType[len(fieldType)-2:] != "64" {
291-
conv = Id(fieldType).Call(Id("x"))
322+
conv = Id(fieldType).Call(Id(fldNm))
292323
} else {
293-
conv = Id("x")
324+
conv = Id(fldNm)
294325
}
295-
return Block(
296-
Return().Err(),
297-
).Else().Block(
298-
Op(star).Id("this").Op(".").Id(fieldName).Op("=").Add(conv),
299-
)
326+
327+
parseBlock = append(parseBlock, Op(star).Id("pv").Op(".").Id(fieldName).Op("=").Add(conv))
328+
329+
// Parse empty string with type rules
330+
// if in[i] == "" {
331+
// pv.Pp = 0
332+
// } else {
333+
// ...
334+
// }
335+
if parseEmpty {
336+
parseBlock = []Code{
337+
If(
338+
Id("in").Index(Id("i")).Op("==").Lit(""),
339+
).Block(
340+
Op(star).Id("pv").Op(".").Id(fieldName).Op("=").Id(defv),
341+
).Else().Block(
342+
parseBlock...,
343+
),
344+
}
345+
}
346+
return parseBlock
300347
}
301348

302349
func marshalBody(typeRes *Statement) *Statement {
303-
return Id("out").Op("=").Id("append").Call(Id("out"), Add(typeRes))
350+
return Id("out").Op("=").Append(Id("out"), Add(typeRes))
304351
}
305352

306353
func nilCheck(star string, iname, itype string, marshall bool) *Statement {
307354
var s, t *Statement
308355
if marshall {
309-
t = List(Id("out"), Qual("errors", "New").Call(Lit("nil pointer found at "+iname+" "+itype)))
356+
t = List(Id("out"), Qual("github.com/pkg/errors", "New").Call(Lit("nil pointer found at "+iname+" "+itype)))
310357
} else {
311-
t = Qual("errors", "New").Call(Lit("nil pointer found at " + iname + " " + itype))
358+
t = Qual("github.com/pkg/errors", "New").Call(Lit("nil pointer found at " + iname + " " + itype))
312359
}
313360
if star == "*" {
314361
s = If(
315-
Id("this").Op(".").Id(iname).Op("==").Id("nil"),
362+
Id("pv").Op(".").Id(iname).Op("==").Id("nil"),
316363
).Block(
317364
Return().Add(t),
318365
)
@@ -321,3 +368,44 @@ func nilCheck(star string, iname, itype string, marshall bool) *Statement {
321368
}
322369
return s
323370
}
371+
372+
func AddList(vstr parser.StructInfo) {
373+
// type FooList []Foo
374+
375+
// func (pl *FooList) Push(in []string) error {
376+
// nf := Foo{}
377+
// if err := nf.UnmarshalCSV(in); err != nil {
378+
// return errors.Wrap(err, "Error in UnmarshalCSV Foo")
379+
// }
380+
// *pl = append(*pl, nf)
381+
// return nil
382+
// }
383+
384+
f.Line()
385+
386+
f.Comment(vstr.Name + "List csvparse.Pusher implementation")
387+
f.Type().Id(vstr.Name + "List").Index().Id(vstr.Name)
388+
389+
f.Line()
390+
391+
f.Comment("Push function for " + vstr.Name + "List struct")
392+
f.Func().Params(
393+
Id("pl").Op("*").Id(vstr.Name+"List"),
394+
).Id("Push").Params(Id("in").Index().String()).
395+
Parens(Error()).Block(
396+
Id("nf").Op(":=").Id(vstr.Name).Values(),
397+
If(
398+
Err().Op(":=").Id("nf").Op(".").Id("UnmarshalCSV").Call(Id("in")),
399+
Err().Op("!=").Nil(),
400+
).Block(
401+
Return(Qual("github.com/pkg/errors", "Wrapf").Call(
402+
Err(),
403+
Lit("Error in UnmarshalCSV "+vstr.Name+" in line %#v "),
404+
Id("in")),
405+
),
406+
),
407+
Op("*").Id("pl").Op("=").Append(Op("*").Id("pl"), Id("nf")),
408+
Return(Id("nil")),
409+
)
410+
411+
}

parser/parser.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,8 @@ func getPkgPath(fname string, isDir bool) (string, error) {
149149
if rel := strings.TrimPrefix(fname, prefix); rel != fname {
150150
if !isDir {
151151
return path.Dir(rel), nil
152-
} else {
153-
return path.Clean(rel), nil
154152
}
153+
return path.Clean(rel), nil
155154
}
156155
}
157156

tests/fixture/test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ type Boo struct {
2525

2626
type Zoo string
2727

28-
func (this *Zoo) UnmarshallCSV(in string) error {
29-
*this = Zoo(in)
28+
func (tz *Zoo) UnmarshallCSV(in string) error {
29+
*tz = Zoo(in)
3030
return nil
3131
}
3232

33-
func (this *Zoo) MarshallCSV() (string, error) {
34-
return string(*this), nil
33+
func (tz *Zoo) MarshallCSV() (string, error) {
34+
return string(*tz), nil
3535
}

0 commit comments

Comments
 (0)