From a2a474bb34043a4aad2827b7f46ef7b22eae2df3 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 13 May 2011 22:06:55 +0000 Subject: [PATCH] added qse_awk_rtx_getfirstmapvalitr()/qse_awk_rtx_getnextmapvalitr() --- qse/include/qse/awk/Awk.hpp | 27 ++++---- qse/include/qse/awk/awk.h | 42 +++++++++++- qse/lib/awk/Awk.cpp | 125 +++++++++++++++++++++--------------- qse/lib/awk/val.c | 20 +++++- qse/samples/awk/awk07.cpp | 7 ++ qse/samples/awk/awk10.c | 38 +++++++++-- 6 files changed, 185 insertions(+), 74 deletions(-) diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index 89b52be3..67ff85d7 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp 441 2011-04-22 14:28:43Z hyunghwan.chung $ + * $Id: Awk.hpp 458 2011-05-13 04:06:55Z hyunghwan.chung $ * Copyright 2006-2011 Chung, Hyung-Hwan. This file is part of QSE. @@ -459,7 +459,7 @@ public: /// The IndexIterator class is a helper class to make simple /// iteration over array elements. /// - class IndexIterator + class IndexIterator: public qse_awk_val_map_itr_t { public: friend class Value; @@ -474,26 +474,29 @@ public: /// The IndexIterator() function creates an iterator /// for an arrayed value. /// - IndexIterator (): pair (QSE_NULL), buckno (0) {} + IndexIterator () + { + this->pair = QSE_NULL; + this->buckno = 0; + } protected: - IndexIterator (pair_t* pair, size_t buckno): - pair (pair), buckno (buckno) {} + IndexIterator (pair_t* pair, size_t buckno) + { + this->pair = pair; + this->buckno = buckno; + } public: bool operator== (const IndexIterator& ii) const { - return pair == ii.pair && buckno == ii.buckno; + return this->pair == ii.pair && this->buckno == ii.buckno; } bool operator!= (const IndexIterator& ii) const { return !operator== (ii); } - - protected: - pair_t* pair; - size_t buckno; }; /// @@ -664,8 +667,8 @@ public: /// iterator that can be passed to getNextIndex() if not /// IndexIterator getNextIndex ( - Index* idx, ///< index holder - const IndexIterator& iter ///< current position + Index* idx, ///< index holder + const IndexIterator& curitr ///< current position ) const; protected: diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 8686cbf4..c0d10e24 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 457 2011-05-12 16:16:57Z hyunghwan.chung $ + * $Id: awk.h 458 2011-05-13 04:06:55Z hyunghwan.chung $ * Copyright 2006-2011 Chung, Hyung-Hwan. This file is part of QSE. @@ -265,6 +265,21 @@ struct qse_awk_val_ref_t }; typedef struct qse_awk_val_ref_t qse_awk_val_ref_t; +/** + * The qse_awk_val_map_itr_t type defines the iterator to map value fields. + */ +struct qse_awk_val_map_itr_t +{ + qse_htb_pair_t* pair; + qse_size_t buckno; +}; +typedef struct qse_awk_val_map_itr_t qse_awk_val_map_itr_t; + + +#define QSE_AWK_VAL_MAP_ITR_KPTR(itr) QSE_HTB_KPTR((itr)->pair) +#define QSE_AWK_VAL_MAP_ITR_KLEN(itr) QSE_HTB_KLEN((itr)->pair) +#define QSE_AWK_VAL_MAP_ITR_VPTR(itr) QSE_HTB_VPTR((itr)->pair) + /** * The qse_awk_nde_type_t defines the node types. */ @@ -1929,6 +1944,31 @@ qse_awk_val_t* qse_awk_rtx_getmapvalfld ( qse_size_t klen ); +/** + * The qse_awk_rtx_getfirstmapvalitr() returns the iterator to the + * first pair in the map. It returns #QSE_NULL and sets the pair field of + * @a itr to #QSE_NULL if the map contains no pair. Otherwise, it returns + * @a itr pointing to the first pair. + */ +qse_awk_val_map_itr_t* qse_awk_rtx_getfirstmapvalitr ( + qse_awk_rtx_t* rtx, + qse_awk_val_t* map, + qse_awk_val_map_itr_t* itr +); + +/** + * The qse_awk_rtx_getnextmapvalitr() returns the iterator to the + * next pair to @a itr in the map. It returns #QSE_NULL and sets the pair + * field of @a itr to #QSE_NULL if @a itr points to the last pair. + * Otherwise, it returns @a itr pointing to the next pair. + */ +qse_awk_val_map_itr_t* qse_awk_rtx_getnextmapvalitr ( + qse_awk_rtx_t* rtx, + qse_awk_val_t* map, + qse_awk_val_map_itr_t* itr +); + + /** * The qse_awk_rtx_makerefval() function creates a reference value. * @return value on success, QSE_NULL on failure diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 9f6033f6..65a98973 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp 457 2011-05-12 16:16:57Z hyunghwan.chung $ + * $Id: Awk.cpp 458 2011-05-13 04:06:55Z hyunghwan.chung $ * Copyright 2006-2011 Chung, Hyung-Hwan. This file is part of QSE. @@ -470,18 +470,23 @@ int Awk::Value::getStr (const char_t** str, size_t* len) const int Awk::Value::setVal (val_t* v) { - if (run == QSE_NULL) return -1; - return setVal (run, v); + if (this->run == QSE_NULL) + { + /* no runtime context assoicated. unfortunately, i can't + * set an error number for the same reason */ + return -1; + } + return setVal (this->run, v); } int Awk::Value::setVal (Run* r, val_t* v) { - if (run != QSE_NULL) + if (this->run != QSE_NULL) { - qse_awk_rtx_refdownval (run->rtx, val); + qse_awk_rtx_refdownval (this->run->rtx, val); if (cached.str.ptr != QSE_NULL) { - qse_awk_rtx_free (run->rtx, cached.str.ptr); + qse_awk_rtx_free (this->run->rtx, cached.str.ptr); cached.str.ptr = QSE_NULL; cached.str.len = 0; } @@ -490,16 +495,21 @@ int Awk::Value::setVal (Run* r, val_t* v) QSE_ASSERT (cached.str.ptr == QSE_NULL); qse_awk_rtx_refupval (r->rtx, v); - run = r; - val = v; + this->run = r; + this->val = v; return 0; } int Awk::Value::setInt (long_t v) { - if (run == QSE_NULL) return -1; - return setInt (run, v); + if (this->run == QSE_NULL) + { + /* no runtime context assoicated. unfortunately, i can't + * set an error number for the same reason */ + return -1; + } + return setInt (this->run, v); } int Awk::Value::setInt (Run* r, long_t v) @@ -519,8 +529,13 @@ int Awk::Value::setInt (Run* r, long_t v) int Awk::Value::setReal (real_t v) { - if (run == QSE_NULL) return -1; - return setReal (run, v); + if (this->run == QSE_NULL) + { + /* no runtime context assoicated. unfortunately, i can't + * set an error number for the same reason */ + return -1; + } + return setReal (this->run, v); } int Awk::Value::setReal (Run* r, real_t v) @@ -540,8 +555,13 @@ int Awk::Value::setReal (Run* r, real_t v) int Awk::Value::setStr (const char_t* str, size_t len) { - if (run == QSE_NULL) return -1; - return setStr (run, str, len); + if (this->run == QSE_NULL) + { + /* no runtime context assoicated. unfortunately, i can't + * set an error number for the same reason */ + return -1; + } + return setStr (this->run, str, len); } int Awk::Value::setStr (Run* r, const char_t* str, size_t len) @@ -561,8 +581,8 @@ int Awk::Value::setStr (Run* r, const char_t* str, size_t len) int Awk::Value::setStr (const char_t* str) { - if (run == QSE_NULL) return -1; - return setStr (run, str); + if (this->run == QSE_NULL) return -1; + return setStr (this->run, str); } int Awk::Value::setStr (Run* r, const char_t* str) @@ -582,8 +602,8 @@ int Awk::Value::setStr (Run* r, const char_t* str) int Awk::Value::setIndexedVal (const Index& idx, val_t* v) { - if (run == QSE_NULL) return -1; - return setIndexedVal (run, idx, v); + if (this->run == QSE_NULL) return -1; + return setIndexedVal (this->run, idx, v); } int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) @@ -612,15 +632,15 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) return -1; } - // increment the reference count of the value after - // it has been added to the map - qse_awk_rtx_refupval (r->rtx, v); - // free the previous value - if (run) qse_awk_rtx_refdownval (run->rtx, val); + if (this->run) + { + // if val is not nil, this->run can't be NULL + qse_awk_rtx_refdownval (this->run->rtx, val); + } - run = r; - val = map; + this->run = r; + this->val = map; } else { @@ -629,11 +649,11 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) // if the previous value is a map, things are a bit simpler // however it needs to check if the runtime context matches // with the previous one. - if (run != r) + if (this->run != r) { // it can't span across multiple runtime contexts - run->setError (QSE_AWK_EINVAL); - run->awk->retrieveError (run); + this->run->setError (QSE_AWK_EINVAL); + this->run->awk->retrieveError (run); return -1; } @@ -644,10 +664,6 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) r->awk->retrieveError (r); return -1; } - - // increment the reference count of the value after - // it has been added to the map - qse_awk_rtx_refupval (r->rtx, v); } return 0; @@ -763,7 +779,7 @@ int Awk::Value::getIndexed (const Index& idx, Value* v) const // get the value from the map. val_t* fv = qse_awk_rtx_getmapvalfld ( - run->rtx, val, (char_t*)idx.ptr, idx.len); + this->run->rtx, val, (char_t*)idx.ptr, idx.len); // the key is not found. it is not an error. v is just nil if (fv == QSE_NULL) @@ -773,45 +789,48 @@ int Awk::Value::getIndexed (const Index& idx, Value* v) const } // if v.set fails, it should return an error - return v->setVal (run, fv); + return v->setVal (this->run, fv); } Awk::Value::IndexIterator Awk::Value::getFirstIndex (Index* idx) const { - QSE_ASSERT (val != QSE_NULL); + QSE_ASSERT (this->val != QSE_NULL); - if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END; + if (this->val->type != QSE_AWK_VAL_MAP) return IndexIterator::END; - size_t buckno; - qse_awk_val_map_t* m = (qse_awk_val_map_t*)val; - pair_t* pair = qse_htb_getfirstpair (m->map, &buckno); - if (pair == QSE_NULL) return IndexIterator::END; // no more key + QSE_ASSERT (this->run != QSE_NULL); - idx->ptr = (const char_t*)QSE_HTB_KPTR(pair); - idx->len = QSE_HTB_KLEN(pair); + Awk::Value::IndexIterator itr; + qse_awk_val_map_itr_t* iptr; - return IndexIterator (pair, buckno); + iptr = qse_awk_rtx_getfirstmapvalitr (this->run->rtx, this->val, &itr); + if (iptr == QSE_NULL) return IndexIterator::END; // no more key + + idx->ptr = (const char_t*)QSE_AWK_VAL_MAP_ITR_KPTR(iptr); + idx->len = QSE_AWK_VAL_MAP_ITR_KLEN(iptr); + + return itr; } Awk::Value::IndexIterator Awk::Value::getNextIndex ( - Index* idx, const IndexIterator& iter) const + Index* idx, const IndexIterator& curitr) const { QSE_ASSERT (val != QSE_NULL); if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END; - qse_awk_val_map_t* m = (qse_awk_val_map_t*)val; + QSE_ASSERT (this->run != QSE_NULL); - pair_t* pair = (pair_t*)iter.pair; - size_t buckno = iter.buckno; - - pair = qse_htb_getnextpair (m->map, pair, &buckno); - if (pair == QSE_NULL) return IndexIterator::END; + Awk::Value::IndexIterator itr (curitr); + qse_awk_val_map_itr_t* iptr; - idx->ptr = (const char_t*)QSE_HTB_KPTR(pair); - idx->len = QSE_HTB_KLEN(pair); + iptr = qse_awk_rtx_getnextmapvalitr (this->run->rtx, this->val, &itr); + if (iptr == QSE_NULL) return IndexIterator::END; // no more key - return IndexIterator (pair, buckno); + idx->ptr = (const char_t*)QSE_AWK_VAL_MAP_ITR_KPTR(iptr); + idx->len = QSE_AWK_VAL_MAP_ITR_KLEN(iptr); + + return itr; } ////////////////////////////////////////////////////////////////// diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index f10b5616..e4c6292c 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -1,5 +1,5 @@ /* - * $Id: val.c 457 2011-05-12 16:16:57Z hyunghwan.chung $ + * $Id: val.c 458 2011-05-13 04:06:55Z hyunghwan.chung $ * Copyright 2006-2011 Chung, Hyung-Hwan. This file is part of QSE. @@ -527,6 +527,24 @@ qse_awk_val_t* qse_awk_rtx_getmapvalfld ( return QSE_HTB_VPTR(pair); } +qse_awk_val_map_itr_t* qse_awk_rtx_getfirstmapvalitr ( + qse_awk_rtx_t* rtx, qse_awk_val_t* map, qse_awk_val_map_itr_t* itr) +{ + QSE_ASSERT (map->type == QSE_AWK_VAL_MAP); + itr->pair = qse_htb_getfirstpair ( + ((qse_awk_val_map_t*)map)->map, &itr->buckno); + return itr->pair? itr: QSE_NULL; +} + +qse_awk_val_map_itr_t* qse_awk_rtx_getnextmapvalitr ( + qse_awk_rtx_t* rtx, qse_awk_val_t* map, qse_awk_val_map_itr_t* itr) +{ + QSE_ASSERT (map->type == QSE_AWK_VAL_MAP); + itr->pair = qse_htb_getnextpair ( + ((qse_awk_val_map_t*)map)->map, itr->pair, &itr->buckno); + return itr->pair? itr: QSE_NULL; +} + qse_awk_val_t* qse_awk_rtx_makerefval ( qse_awk_rtx_t* rtx, int id, qse_awk_val_t** adr) { diff --git a/qse/samples/awk/awk07.cpp b/qse/samples/awk/awk07.cpp index f88a1e59..3a3227ab 100644 --- a/qse/samples/awk/awk07.cpp +++ b/qse/samples/awk/awk07.cpp @@ -69,6 +69,13 @@ static int run_awk (QSE::StdAwk& awk) if (arg[0].setIndexedInt (run, QSE::StdAwk::Value::IntIndex(i), i*20) <= -1) return -1; } + if (arg[0].setIndexedStr (run, + QSE::StdAwk::Value::IntIndex(99), QSE_T("-2345")) <= -1) return -1; + + QSE::StdAwk::Value dummy; + if (dummy.setStr (run, QSE_T("4567")) <= -1) return -1; + if (arg[0].setIndexedVal (run, + QSE::StdAwk::Value::IntIndex(999), dummy) <= -1) return -1; // prepare a variable to hold the return value QSE::StdAwk::Value r; diff --git a/qse/samples/awk/awk10.c b/qse/samples/awk/awk10.c index ce737d70..4ac645fb 100644 --- a/qse/samples/awk/awk10.c +++ b/qse/samples/awk/awk10.c @@ -136,23 +136,47 @@ int main () /* print the return value */ if (rtv->type == QSE_AWK_VAL_MAP) { - qse_printf (QSE_T("ret [MAP]\n")); + qse_awk_val_map_itr_t itr; + qse_awk_val_map_itr_t* iptr; + + iptr = qse_awk_rtx_getfirstmapvalitr (rtx, rtv, &itr); + while (iptr) + { + qse_xstr_t str; + + str.ptr = qse_awk_rtx_valtocpldup ( + rtx, QSE_AWK_VAL_MAP_ITR_VPTR(iptr), &str.len); + if (str.ptr == QSE_NULL) + { + qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"), + qse_awk_rtx_geterrmsg(rtx)); + ret = -1; goto oops; + } + + qse_printf (QSE_T("ret [%.*s]=[%.*s]\n"), + (int)QSE_AWK_VAL_MAP_ITR_KLEN(iptr), + QSE_AWK_VAL_MAP_ITR_KPTR(iptr), + (int)str.len, str.ptr + ); + qse_awk_rtx_free (rtx, str.ptr); + + iptr = qse_awk_rtx_getnextmapvalitr (rtx, rtv, &itr); + } } else { - qse_char_t* str; - qse_size_t len; + qse_xstr_t str; - str = qse_awk_rtx_valtocpldup (rtx, rtv, &len); - if (str == QSE_NULL) + str.ptr = qse_awk_rtx_valtocpldup (rtx, rtv, &str.len); + if (str.ptr == QSE_NULL) { qse_fprintf (QSE_STDERR, QSE_T("error: %s\n"), qse_awk_rtx_geterrmsg(rtx)); ret = -1; goto oops; } - qse_printf (QSE_T("ret [%.*s]\n"), (int)len, str); - qse_awk_rtx_free (rtx, str); + qse_printf (QSE_T("ret [%.*s]\n"), (int)str.len, str.ptr); + qse_awk_rtx_free (rtx, str.ptr); } oops: