2018-11-27 17:37:41 +08:00
|
|
|
<%inc#include "create_model.h"
|
|
|
|
using namespace drogon_ctl;
|
|
|
|
%>
|
2018-10-31 16:45:27 +08:00
|
|
|
/**
|
|
|
|
*
|
2019-04-25 14:36:42 +08:00
|
|
|
* [[className]].cc
|
2018-11-27 17:37:41 +08:00
|
|
|
* DO NOT EDIT. This file is generated by drogon_ctl
|
2018-10-31 16:45:27 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
#include "[[className]].h"
|
2018-11-19 18:15:41 +08:00
|
|
|
#include <drogon/utils/Utilities.h>
|
2018-10-31 16:45:27 +08:00
|
|
|
#include <string>
|
2018-11-01 17:58:32 +08:00
|
|
|
<%c++
|
|
|
|
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|
|
|
auto className=@@.get<std::string>("className");
|
|
|
|
%>
|
2018-10-31 16:45:27 +08:00
|
|
|
|
2019-07-26 22:22:12 +08:00
|
|
|
using namespace drogon;
|
2019-04-25 14:36:42 +08:00
|
|
|
using namespace drogon_model::[[dbName]];
|
2018-11-01 17:58:32 +08:00
|
|
|
|
|
|
|
<%c++for(auto col:cols){
|
|
|
|
%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::string [[className]]::Cols::{%col._colName%} = "{%col._colName%}";
|
2018-11-01 17:58:32 +08:00
|
|
|
<%c++
|
|
|
|
}%>
|
2018-11-07 18:46:16 +08:00
|
|
|
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::string [[className]]::primaryKeyName = "[[primaryKeyName]]";
|
2018-11-07 18:46:16 +08:00
|
|
|
<%c++}else{%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::vector<std::string> [[className]]::primaryKeyName = {<%c++
|
2018-11-07 18:46:16 +08:00
|
|
|
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
2018-11-09 15:55:20 +08:00
|
|
|
for(size_t i=0;i<pkName.size();i++)
|
2018-11-07 18:46:16 +08:00
|
|
|
{
|
|
|
|
$$<<"\""<<pkName[i]<<"\"";
|
|
|
|
if(i<(pkName.size()-1))
|
|
|
|
$$<<",";
|
|
|
|
}
|
|
|
|
%>};
|
|
|
|
<%c++}%>
|
2019-08-22 22:23:50 +08:00
|
|
|
<%c++ if(@@.get<int>("hasPrimaryKey")>0){%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const bool [[className]]::hasPrimaryKey = true;
|
2018-10-31 16:45:27 +08:00
|
|
|
<%c++ }else{%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const bool [[className]]::hasPrimaryKey = false;
|
2018-10-31 16:45:27 +08:00
|
|
|
<%c++}%>
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::string [[className]]::tableName = "[[tableName]]";
|
2018-11-01 17:58:32 +08:00
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::vector<typename [[className]]::MetaData> [[className]]::_metaData={
|
2018-11-01 22:14:53 +08:00
|
|
|
<%c++for(size_t i=0;i<cols.size();i++){
|
2018-11-01 15:40:24 +08:00
|
|
|
auto &col=cols[i];
|
2018-11-05 16:00:49 +08:00
|
|
|
$$<<"{\""<<col._colName<<"\",\""<<col._colType<<"\",\""<<col._colDatabaseType<<"\","<<col._colLength<<","<<col._isAutoVal<<","<<col._isPrimaryKey<<","<<col._notNull<<"}";
|
2018-11-01 15:40:24 +08:00
|
|
|
if(i<(cols.size()-1))
|
|
|
|
$$<<",\n";
|
|
|
|
else
|
|
|
|
$$<<"\n";
|
|
|
|
}%>
|
|
|
|
};
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
assert(index < _metaData.size());
|
|
|
|
return _metaData[index]._colName;
|
|
|
|
}
|
2019-04-25 14:36:42 +08:00
|
|
|
[[className]]::[[className]](const Row &r) noexcept
|
2018-10-31 16:45:27 +08:00
|
|
|
{
|
|
|
|
<%c++
|
|
|
|
for(auto col:cols)
|
|
|
|
{
|
2018-10-31 17:32:46 +08:00
|
|
|
if(col._colType.empty())
|
|
|
|
continue;
|
2018-10-31 16:45:27 +08:00
|
|
|
%>
|
2018-12-07 19:08:17 +08:00
|
|
|
if(!r["{%col._colName%}"].isNull())
|
2018-10-31 16:45:27 +08:00
|
|
|
{
|
2018-11-05 16:00:49 +08:00
|
|
|
<%c++
|
|
|
|
if(col._colDatabaseType=="date")
|
|
|
|
{
|
2018-11-08 11:05:50 +08:00
|
|
|
$$<<" auto daysStr = r[\""<<col._colName<<"\"].as<std::string>();\n";
|
|
|
|
$$<<" struct tm stm;\n";
|
|
|
|
$$<<" memset(&stm,0,sizeof(stm));\n";
|
|
|
|
$$<<" strptime(daysStr.c_str(),\"%Y-%m-%d\",&stm);\n";
|
|
|
|
$$<<" long t = timelocal(&stm);\n";
|
|
|
|
// $$<<" _"<<col._colValName<<"=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
|
|
|
|
$$<<" _"<<col._colValName<<"=std::make_shared<::trantor::Date>(t*1000000);\n";
|
2018-11-05 16:00:49 +08:00
|
|
|
$$<<" }\n";
|
|
|
|
continue;
|
2018-11-08 16:31:39 +08:00
|
|
|
}
|
2018-12-01 21:29:31 +08:00
|
|
|
else if(col._colDatabaseType.find("timestamp")!=std::string::npos||col._colDatabaseType.find("datetime")!=std::string::npos)
|
2018-11-08 16:31:39 +08:00
|
|
|
{
|
|
|
|
$$<<" auto timeStr = r[\""<<col._colName<<"\"].as<std::string>();\n";
|
|
|
|
$$<<" struct tm stm;\n";
|
|
|
|
$$<<" memset(&stm,0,sizeof(stm));\n";
|
|
|
|
$$<<" auto p = strptime(timeStr.c_str(),\"%Y-%m-%d %H:%M:%S\",&stm);\n";
|
|
|
|
$$<<" size_t t = timelocal(&stm);\n";
|
|
|
|
$$<<" size_t decimalNum = 0;\n";
|
|
|
|
$$<<" if(*p=='.')\n";
|
|
|
|
$$<<" {\n";
|
|
|
|
$$<<" std::string decimals(p+1,&timeStr[timeStr.length()]);\n";
|
|
|
|
$$<<" while(decimals.length()<6)\n";
|
|
|
|
$$<<" {\n";
|
|
|
|
$$<<" decimals += \"0\";\n";
|
|
|
|
$$<<" }\n";
|
|
|
|
$$<<" decimalNum = (size_t)atol(decimals.c_str());\n";
|
|
|
|
$$<<" }\n";
|
|
|
|
// $$<<" _"<<col._colValName<<"=std::make_shared<::trantor::Date>(::trantor::Date(946656000000000).after(daysNum*86400));\n";
|
|
|
|
$$<<" _"<<col._colValName<<"=std::make_shared<::trantor::Date>(t*1000000+decimalNum);\n";
|
|
|
|
$$<<" }\n";
|
|
|
|
continue;
|
2018-11-19 18:15:41 +08:00
|
|
|
}
|
|
|
|
else if(col._colDatabaseType=="bytea")
|
|
|
|
{
|
2019-03-07 11:56:20 +08:00
|
|
|
$$<<" auto str = r[\""<<col._colName<<"\"].as<string_view>();\n";
|
2018-11-19 18:15:41 +08:00
|
|
|
$$<<" if(str.length()>=2&&\n";
|
|
|
|
$$<<" str[0]=='\\\\'&&str[1]=='x')\n";
|
|
|
|
$$<<" {\n";
|
2019-04-25 14:36:42 +08:00
|
|
|
$$<<" _"<<col._colValName<<"=std::make_shared<std::vector<char>>(drogon::utils::hexToBinaryVector(str.data()+2,str.length()-2));\n";
|
2018-11-19 18:15:41 +08:00
|
|
|
$$<<" }\n";
|
|
|
|
$$<<" }\n";
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-05 16:00:49 +08:00
|
|
|
%>
|
2018-12-07 19:08:17 +08:00
|
|
|
_{%col._colValName%}=std::make_shared<{%col._colType%}>(r["{%col._colName%}"].as<{%col._colType%}>());
|
2018-10-31 16:45:27 +08:00
|
|
|
}
|
2018-10-31 17:32:46 +08:00
|
|
|
<%c++
|
|
|
|
}
|
|
|
|
%>
|
2018-10-31 16:45:27 +08:00
|
|
|
}
|
|
|
|
<%c++
|
2018-11-01 22:14:53 +08:00
|
|
|
for(size_t i=0;i<cols.size();i++)
|
2018-10-31 16:45:27 +08:00
|
|
|
{
|
2018-11-01 15:40:24 +08:00
|
|
|
auto & col = cols[i];
|
2018-10-31 16:45:27 +08:00
|
|
|
if(!col._colType.empty())
|
|
|
|
{
|
2019-08-22 22:23:50 +08:00
|
|
|
$$<<"const "<<col._colType<<" &"<<className<<"::getValueOf"<<col._colTypeName<<"() const noexcept\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<"{\n";
|
2019-08-22 22:23:50 +08:00
|
|
|
$$<<" const static "<<col._colType<<" defaultValue = "<<col._colType<<"();\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<" if(_"<<col._colValName<<")\n";
|
|
|
|
$$<<" return *_"<<col._colValName<<";\n";
|
2018-10-31 19:07:37 +08:00
|
|
|
$$<<" return defaultValue;\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<"}\n";
|
2018-11-20 10:54:46 +08:00
|
|
|
if(col._colType=="std::vector<char>")
|
|
|
|
{
|
2019-08-22 22:23:50 +08:00
|
|
|
$$<<"std::string "<<className<<"::getValueOf"<<col._colTypeName<<"AsString() const noexcept\n";
|
2018-11-20 10:54:46 +08:00
|
|
|
$$<<"{\n";
|
2019-08-22 22:23:50 +08:00
|
|
|
$$<<" const static std::string defaultValue = std::string();\n";
|
2018-11-20 10:54:46 +08:00
|
|
|
$$<<" if(_"<<col._colValName<<")\n";
|
|
|
|
$$<<" return std::string(_"<<col._colValName<<"->data(),_"<<col._colValName<<"->size());\n";
|
|
|
|
$$<<" return defaultValue;\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2019-08-24 18:43:05 +08:00
|
|
|
$$<<"const std::shared_ptr<"<<col._colType<<"> &"<<className<<"::get"<<col._colTypeName<<"() const noexcept\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<"{\n";
|
|
|
|
$$<<" return _"<<col._colValName<<";\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
|
2018-10-31 19:28:27 +08:00
|
|
|
if(!col._isAutoVal)
|
|
|
|
{
|
2018-11-01 17:58:32 +08:00
|
|
|
$$<<"void "<<className<<"::set"<<col._colTypeName<<"(const "<<col._colType<<" &"<<col._colValName<<") noexcept\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<"{\n";
|
2018-11-05 16:00:49 +08:00
|
|
|
if(col._colDatabaseType=="date")
|
|
|
|
{
|
|
|
|
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">("<<col._colValName<<".roundDay());\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">("<<col._colValName<<");\n";
|
|
|
|
}
|
2018-11-01 15:40:24 +08:00
|
|
|
$$<<" _dirtyFlag["<<i<<"] = true;\n";
|
2018-10-31 16:45:27 +08:00
|
|
|
$$<<"}\n";
|
2018-11-01 17:58:32 +08:00
|
|
|
|
|
|
|
if(col._colType=="std::string")
|
|
|
|
{
|
|
|
|
$$<<"void "<<className<<"::set"<<col._colTypeName<<"("<<col._colType<<" &&"<<col._colValName<<") noexcept\n";
|
|
|
|
$$<<"{\n";
|
|
|
|
$$<<" _"<<col._colValName<<" = std::make_shared<"<<col._colType<<">(std::move("<<col._colValName<<"));\n";
|
|
|
|
$$<<" _dirtyFlag["<<i<<"] = true;\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2018-11-20 10:54:46 +08:00
|
|
|
|
|
|
|
if(col._colType=="std::vector<char>")
|
|
|
|
{
|
|
|
|
$$<<"void "<<className<<"::set"<<col._colTypeName<<"(const std::string &"<<col._colValName<<") noexcept\n";
|
|
|
|
$$<<"{\n";
|
|
|
|
$$<<" _"<<col._colValName<<" = std::make_shared<std::vector<char>>("<<col._colValName<<".c_str(),"<<col._colValName<<".c_str()+"<<col._colValName<<".length());\n";
|
|
|
|
$$<<" _dirtyFlag["<<i<<"] = true;\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2018-10-31 16:45:27 +08:00
|
|
|
}
|
2018-11-07 18:46:16 +08:00
|
|
|
if(col._isPrimaryKey&&@@.get<int>("hasPrimaryKey")==1)
|
2018-11-01 17:58:32 +08:00
|
|
|
{
|
|
|
|
$$<<"const typename "<<className<<"::PrimaryKeyType & "<<className<<"::getPrimaryKey() const\n";
|
|
|
|
$$<<"{\n";
|
|
|
|
$$<<" assert(_"<<col._colValName<<");\n";
|
|
|
|
$$<<" return *_"<<col._colValName<<";\n";
|
|
|
|
$$<<"}\n";
|
2018-10-31 19:28:27 +08:00
|
|
|
}
|
2018-10-31 16:45:27 +08:00
|
|
|
}
|
|
|
|
$$<<"\n";
|
|
|
|
}
|
2018-12-02 15:55:42 +08:00
|
|
|
if(@@.get<std::string>("rdbms")=="postgresql")
|
|
|
|
{
|
2018-12-29 18:02:39 +08:00
|
|
|
$$<<"void "<<className<<"::updateId(const uint64_t id)\n";
|
2018-12-02 15:55:42 +08:00
|
|
|
$$<<"{\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2018-12-28 18:22:02 +08:00
|
|
|
else if(@@.get<std::string>("rdbms")=="mysql"||@@.get<std::string>("rdbms")=="sqlite3")
|
2018-12-02 15:55:42 +08:00
|
|
|
{
|
2018-12-29 18:02:39 +08:00
|
|
|
$$<<"void "<<className<<"::updateId(const uint64_t id)\n";
|
2018-12-02 15:55:42 +08:00
|
|
|
$$<<"{\n";
|
|
|
|
for(auto col:cols)
|
|
|
|
{
|
|
|
|
if(col._isAutoVal)
|
|
|
|
{
|
2018-12-29 18:02:39 +08:00
|
|
|
$$<<" _"<<col._colValName<<" = std::make_shared<uint64_t>(id);\n";
|
2018-12-02 15:55:42 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2018-11-07 18:46:16 +08:00
|
|
|
if(@@.get<int>("hasPrimaryKey")>1)
|
|
|
|
{
|
|
|
|
$$<<"typename "<<className<<"::PrimaryKeyType "<<className<<"::getPrimaryKey() const\n";
|
|
|
|
$$<<"{\n";
|
|
|
|
$$<<" return std::make_tuple(";
|
|
|
|
int count=0;
|
|
|
|
for(auto col:cols)
|
|
|
|
{
|
|
|
|
if(col._isPrimaryKey)
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
$$<<"*_"<<col._colValName;
|
|
|
|
if(count<@@.get<int>("hasPrimaryKey"))
|
|
|
|
$$<<",";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$$<<");\n";
|
|
|
|
$$<<"}\n";
|
|
|
|
}
|
2018-11-01 15:40:24 +08:00
|
|
|
%>
|
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::vector<std::string> &[[className]]::insertColumns() noexcept
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
static const std::vector<std::string> _inCols={
|
2018-11-01 22:14:53 +08:00
|
|
|
<%c++for(size_t i=0;i<cols.size();i++){
|
2018-11-01 15:40:24 +08:00
|
|
|
auto col=cols[i];
|
|
|
|
if(!col._isAutoVal&&!col._colType.empty())
|
|
|
|
{
|
|
|
|
$$<<" \""<<col._colName<<"\"";
|
|
|
|
if(i<(cols.size()-1))
|
|
|
|
$$<<",\n";
|
|
|
|
else
|
|
|
|
$$<<"\n";
|
|
|
|
}
|
|
|
|
}%>
|
|
|
|
};
|
|
|
|
return _inCols;
|
|
|
|
}
|
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
void [[className]]::outputArgs(drogon::orm::internal::SqlBinder &binder) const
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
<%c++for(auto col:cols){
|
|
|
|
if(!col._isAutoVal&&!col._colType.empty())
|
|
|
|
{
|
|
|
|
%>
|
2018-12-07 19:08:17 +08:00
|
|
|
if(get{%col._colTypeName%}())
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
2018-12-07 19:08:17 +08:00
|
|
|
binder << getValueOf{%col._colTypeName%}();
|
2018-11-01 15:40:24 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
binder << nullptr;
|
|
|
|
}
|
|
|
|
<%c++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
%>
|
|
|
|
}
|
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
const std::vector<std::string> [[className]]::updateColumns() const
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
std::vector<std::string> ret;
|
2018-11-01 22:14:53 +08:00
|
|
|
for(size_t i=0;i<sizeof(_dirtyFlag);i++)
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
if(_dirtyFlag[i])
|
|
|
|
{
|
|
|
|
ret.push_back(getColumnName(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-04-25 14:36:42 +08:00
|
|
|
void [[className]]::updateArgs(drogon::orm::internal::SqlBinder &binder) const
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
<%c++
|
2018-11-01 22:14:53 +08:00
|
|
|
for(size_t i=0;i<cols.size();i++)
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
|
|
|
auto & col=cols[i];
|
|
|
|
if(col._colType.empty()||col._isAutoVal)
|
|
|
|
continue;
|
|
|
|
%>
|
2018-12-07 19:08:17 +08:00
|
|
|
if(_dirtyFlag[{%i%}])
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
2018-12-07 19:08:17 +08:00
|
|
|
if(get{%col._colTypeName%}())
|
2018-11-01 15:40:24 +08:00
|
|
|
{
|
2018-12-07 19:08:17 +08:00
|
|
|
binder << getValueOf{%col._colTypeName%}();
|
2018-11-01 15:40:24 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
binder << nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
<%c++
|
|
|
|
}
|
|
|
|
%>
|
2018-11-07 18:46:16 +08:00
|
|
|
}
|
2019-04-25 14:36:42 +08:00
|
|
|
Json::Value [[className]]::toJson() const
|
2018-11-20 14:08:08 +08:00
|
|
|
{
|
|
|
|
Json::Value ret;
|
|
|
|
<%c++for(auto col:cols){%>
|
2018-12-07 19:08:17 +08:00
|
|
|
if(get{%col._colTypeName%}())
|
2018-11-20 14:08:08 +08:00
|
|
|
{
|
|
|
|
<%c++if(col._colDatabaseType=="date"){%>
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=get{%col._colTypeName%}()->toDbStringLocal();
|
2018-12-01 21:29:31 +08:00
|
|
|
<%c++}else if(col._colDatabaseType.find("timestamp")!=std::string::npos||col._colDatabaseType.find("datetime")!=std::string::npos){%>
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=get{%col._colTypeName%}()->toDbStringLocal();
|
2018-12-01 21:29:31 +08:00
|
|
|
<%c++}else if(col._colDatabaseType=="bytea"||col._colDatabaseType.find("blob")!=std::string::npos){%>
|
2019-04-25 14:36:42 +08:00
|
|
|
ret["{%col._colName%}"]=drogon::utils::base64Encode((const unsigned char *)get{%col._colTypeName%}()->data(),get{%col._colTypeName%}()->size());
|
2018-11-23 19:46:59 +08:00
|
|
|
<%c++}else if(col._colType=="int64_t"){%>
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=(Json::Int64)getValueOf{%col._colTypeName%}();
|
2018-12-01 21:29:31 +08:00
|
|
|
<%c++}else if(col._colType=="uint64_t"){%>
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=(Json::UInt64)getValueOf{%col._colTypeName%}();
|
2018-11-20 14:08:08 +08:00
|
|
|
<%c++}else{%>
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=getValueOf{%col._colTypeName%}();
|
2018-11-20 14:08:08 +08:00
|
|
|
<%c++}%>
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-07 19:08:17 +08:00
|
|
|
ret["{%col._colName%}"]=Json::Value();
|
2018-11-20 14:08:08 +08:00
|
|
|
}
|
|
|
|
<%c++
|
|
|
|
}%>
|
|
|
|
return ret;
|
|
|
|
}
|